diff --git a/.github/workflows/check-change-note.yml b/.github/workflows/check-change-note.yml index e951b17b89b..aa255d4cf5a 100644 --- a/.github/workflows/check-change-note.yml +++ b/.github/workflows/check-change-note.yml @@ -8,6 +8,7 @@ on: - "*/ql/src/**/*.qll" - "*/ql/lib/**/*.ql" - "*/ql/lib/**/*.qll" + - "*/ql/lib/**/*.yml" - "!**/experimental/**" - "!ql/**" - "!swift/**" diff --git a/.github/workflows/close-stale.yml b/.github/workflows/close-stale.yml index 6bdee05d6a1..9805fb44f48 100644 --- a/.github/workflows/close-stale.yml +++ b/.github/workflows/close-stale.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/stale@v7 + - uses: actions/stale@v8 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: 'This issue is stale because it has been open 14 days with no activity. Comment or remove the `Stale` label in order to avoid having this issue closed in 7 days.' diff --git a/.github/workflows/ruby-build.yml b/.github/workflows/ruby-build.yml index 6fdd497a802..8190d8c08fa 100644 --- a/.github/workflows/ruby-build.yml +++ b/.github/workflows/ruby-build.yml @@ -48,6 +48,9 @@ jobs: run: | brew install gnu-tar echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH + - name: Install cargo-cross + if: runner.os == 'Linux' + run: cargo install cross --version 0.2.5 - uses: ./.github/actions/os-version id: os_version - name: Cache entire extractor @@ -78,8 +81,18 @@ jobs: - name: Run tests if: steps.cache-extractor.outputs.cache-hit != 'true' run: cd extractor && cargo test --verbose - - name: Release build - if: steps.cache-extractor.outputs.cache-hit != 'true' + # On linux, build the extractor via cross in a centos7 container. + # This ensures we don't depend on glibc > 2.17. + - name: Release build (linux) + if: steps.cache-extractor.outputs.cache-hit != 'true' && runner.os == 'Linux' + run: | + cd extractor + cross build --release + mv target/x86_64-unknown-linux-gnu/release/extractor target/release/ + mv target/x86_64-unknown-linux-gnu/release/autobuilder target/release/ + mv target/x86_64-unknown-linux-gnu/release/generator target/release/ + - name: Release build (windows and macos) + if: steps.cache-extractor.outputs.cache-hit != 'true' && runner.os != 'Linux' run: cd extractor && cargo build --release - name: Generate dbscheme if: ${{ matrix.os == 'ubuntu-latest' && steps.cache-extractor.outputs.cache-hit != 'true'}} @@ -227,3 +240,54 @@ jobs: shell: bash run: | codeql database analyze --search-path "${{ runner.temp }}/ruby-bundle" --format=sarifv2.1.0 --output=out.sarif ../database ruby-code-scanning.qls + + # This is a copy of the 'test' job that runs in a centos7 container. + # This tests that the extractor works correctly on systems with an old glibc. + test-centos7: + defaults: + run: + working-directory: ${{ github.workspace }} + strategy: + fail-fast: false + runs-on: ubuntu-latest + container: + image: centos:centos7 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + needs: [package] + steps: + - name: Install gh cli + run: | + yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo + # fetch-codeql requires unzip and jq + # jq is available in epel-release (https://docs.fedoraproject.org/en-US/epel/) + yum install -y gh unzip epel-release + yum install -y jq + - uses: actions/checkout@v3 + - name: Fetch CodeQL + uses: ./.github/actions/fetch-codeql + + # Due to a bug in Actions, we can't use runner.temp in the run blocks here. + # https://github.com/actions/runner/issues/2185 + + - name: Download Ruby bundle + uses: actions/download-artifact@v3 + with: + name: codeql-ruby-bundle + path: ${{ runner.temp }} + - name: Unzip Ruby bundle + shell: bash + run: unzip -q -d "$RUNNER_TEMP"/ruby-bundle "$RUNNER_TEMP"/codeql-ruby-bundle.zip + + - name: Run QL test + shell: bash + run: | + codeql test run --search-path "$RUNNER_TEMP"/ruby-bundle --additional-packs "$RUNNER_TEMP"/ruby-bundle ruby/ql/test/library-tests/ast/constants/ + - name: Create database + shell: bash + run: | + codeql database create --search-path "$RUNNER_TEMP"/ruby-bundle --language ruby --source-root ruby/ql/test/library-tests/ast/constants/ ../database + - name: Analyze database + shell: bash + run: | + codeql database analyze --search-path "$RUNNER_TEMP"/ruby-bundle --format=sarifv2.1.0 --output=out.sarif ../database ruby-code-scanning.qls diff --git a/.github/workflows/ruby-qltest.yml b/.github/workflows/ruby-qltest.yml index 370375cea93..765ed8ce8c7 100644 --- a/.github/workflows/ruby-qltest.yml +++ b/.github/workflows/ruby-qltest.yml @@ -4,6 +4,7 @@ on: push: paths: - "ruby/**" + - "shared/**" - .github/workflows/ruby-build.yml - .github/actions/fetch-codeql/action.yml - codeql-workspace.yml diff --git a/cpp/ql/lib/change-notes/2023-03-20-boost-deprecated-dataflow-configurations.md b/cpp/ql/lib/change-notes/2023-03-20-boost-deprecated-dataflow-configurations.md index b4389ba5b59..a9d2a4d2c80 100644 --- a/cpp/ql/lib/change-notes/2023-03-20-boost-deprecated-dataflow-configurations.md +++ b/cpp/ql/lib/change-notes/2023-03-20-boost-deprecated-dataflow-configurations.md @@ -1,4 +1,4 @@ --- category: deprecated --- -* The `SslContextCallAbstractConfig`, `SslContextCallConfig`, `SslContextCallBannedProtocolConfig`, `SslContextCallTls12ProtocolConfig`, `SslContextCallTls13ProtocolConfig`, `SslContextCallTlsProtocolConfig`, `SslContextFlowsToSetOptionConfig`, `SslOptionConfig` dataflow configurations from `BoostorgAsio` have been deprecated. Please use `SslContextCallConfigSig`, `SslContextCallMake`, `SslContextCallFlow`, `SslContextCallBannedProtocolFlow`, `SslContextCallTls12ProtocolFlow`, `SslContextCallTls13ProtocolFlow`, `SslContextCallTlsProtocolFlow`, `SslContextFlowsToSetOptionFlow`. +* The `SslContextCallAbstractConfig`, `SslContextCallConfig`, `SslContextCallBannedProtocolConfig`, `SslContextCallTls12ProtocolConfig`, `SslContextCallTls13ProtocolConfig`, `SslContextCallTlsProtocolConfig`, `SslContextFlowsToSetOptionConfig`, `SslOptionConfig` dataflow configurations from `BoostorgAsio` have been deprecated. Please use `SslContextCallConfigSig`, `SslContextCallGlobal`, `SslContextCallFlow`, `SslContextCallBannedProtocolFlow`, `SslContextCallTls12ProtocolFlow`, `SslContextCallTls13ProtocolFlow`, `SslContextCallTlsProtocolFlow`, `SslContextFlowsToSetOptionFlow`. diff --git a/cpp/ql/lib/change-notes/2023-03-23-dataflow-renaming.md b/cpp/ql/lib/change-notes/2023-03-23-dataflow-renaming.md new file mode 100644 index 00000000000..54df71fae46 --- /dev/null +++ b/cpp/ql/lib/change-notes/2023-03-23-dataflow-renaming.md @@ -0,0 +1,6 @@ +--- +category: deprecated +--- +* The recently introduced new data flow and taint tracking APIs have had a + number of module and predicate renamings. The old APIs remain in place for + now. diff --git a/cpp/ql/lib/change-notes/2023-03-28-dataflow-rm-footgun.md b/cpp/ql/lib/change-notes/2023-03-28-dataflow-rm-footgun.md new file mode 100644 index 00000000000..82dc0a1d893 --- /dev/null +++ b/cpp/ql/lib/change-notes/2023-03-28-dataflow-rm-footgun.md @@ -0,0 +1,4 @@ +--- +category: fix +--- +* Fixed some accidental predicate visibility in the backwards-compatible wrapper for data flow configurations. In particular `DataFlow::hasFlowPath`, `DataFlow::hasFlow`, `DataFlow::hasFlowTo`, and `DataFlow::hasFlowToExpr` were accidentally exposed in a single version. diff --git a/cpp/ql/lib/change-notes/2023-03-30-bufferaccess.md b/cpp/ql/lib/change-notes/2023-03-30-bufferaccess.md new file mode 100644 index 00000000000..1cd611501be --- /dev/null +++ b/cpp/ql/lib/change-notes/2023-03-30-bufferaccess.md @@ -0,0 +1,4 @@ +--- +category: feature +--- +* Added overridable predicates `getSizeExpr` and `getSizeMult` to the `BufferAccess` class (`semmle.code.cpp.security.BufferAccess.qll`). This makes it possible to model a larger class of buffer reads and writes using the library. \ No newline at end of file diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/ExtendedRangeAnalysis.qll b/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/ExtendedRangeAnalysis.qll index bc63d740c32..cba3a94c7af 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/ExtendedRangeAnalysis.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/ExtendedRangeAnalysis.qll @@ -3,3 +3,4 @@ import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis // Import each extension we want to enable import extensions.SubtractSelf import extensions.ConstantBitwiseAndExprRange +import extensions.StrlenLiteralRangeExpr diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/extensions/StrlenLiteralRangeExpr.qll b/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/extensions/StrlenLiteralRangeExpr.qll new file mode 100644 index 00000000000..39326e89a51 --- /dev/null +++ b/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/extensions/StrlenLiteralRangeExpr.qll @@ -0,0 +1,18 @@ +private import cpp +private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr + +/** + * Provides range analysis information for calls to `strlen` on literal strings. + * For example, the range of `strlen("literal")` will be 7. + */ +class StrlenLiteralRangeExpr extends SimpleRangeAnalysisExpr, FunctionCall { + StrlenLiteralRangeExpr() { + getTarget().hasGlobalOrStdName("strlen") and getArgument(0).isConstant() + } + + override int getLowerBounds() { result = getArgument(0).getValue().length() } + + override int getUpperBounds() { result = getArgument(0).getValue().length() } + + override predicate dependsOnChild(Expr e) { none() } +} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateCleartextWrite.qll b/cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateCleartextWrite.qll index 416bf4b04f8..e733940bdc1 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateCleartextWrite.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateCleartextWrite.qll @@ -54,7 +54,7 @@ module PrivateCleartextWrite { predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } } - module WriteFlow = TaintTracking::Make; + module WriteFlow = TaintTracking::Global; class PrivateDataSource extends Source { PrivateDataSource() { this.getExpr() instanceof PrivateDataExpr } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticExprSpecific.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticExprSpecific.qll index f72edf2f806..0b3249a3013 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticExprSpecific.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticExprSpecific.qll @@ -12,12 +12,92 @@ private import semmle.code.cpp.ir.ValueNumbering module SemanticExprConfig { class Location = Cpp::Location; - class Expr = IR::Instruction; + /** A `ConvertInstruction` or a `CopyValueInstruction`. */ + private class Conversion extends IR::UnaryInstruction { + Conversion() { + this instanceof IR::CopyValueInstruction + or + this instanceof IR::ConvertInstruction + } + + /** Holds if this instruction converts a value of type `tFrom` to a value of type `tTo`. */ + predicate converts(SemType tFrom, SemType tTo) { + tFrom = getSemanticType(this.getUnary().getResultIRType()) and + tTo = getSemanticType(this.getResultIRType()) + } + } + + /** + * Gets a conversion-like instruction that consumes `op`, and + * which is guaranteed to not overflow. + */ + private IR::Instruction safeConversion(IR::Operand op) { + exists(Conversion conv, SemType tFrom, SemType tTo | + conv.converts(tFrom, tTo) and + conversionCannotOverflow(tFrom, tTo) and + conv.getUnaryOperand() = op and + result = conv + ) + } + + /** Holds if `i1 = i2` or if `i2` is a safe conversion that consumes `i1`. */ + private predicate idOrSafeConversion(IR::Instruction i1, IR::Instruction i2) { + not i1.getResultIRType() instanceof IR::IRVoidType and + ( + i1 = i2 + or + i2 = safeConversion(i1.getAUse()) and + i1.getBlock() = i2.getBlock() + ) + } + + module Equiv = QlBuiltins::EquivalenceRelation; + + /** + * The expressions on which we perform range analysis. + */ + class Expr extends Equiv::EquivalenceClass { + /** Gets the n'th instruction in this equivalence class. */ + private IR::Instruction getInstruction(int n) { + result = + rank[n + 1](IR::Instruction instr, int i, IR::IRBlock block | + this = Equiv::getEquivalenceClass(instr) and block.getInstruction(i) = instr + | + instr order by i + ) + } + + /** Gets a textual representation of this element. */ + string toString() { result = this.getUnconverted().toString() } + + /** Gets the basic block of this expression. */ + IR::IRBlock getBlock() { result = this.getUnconverted().getBlock() } + + /** Gets the unconverted instruction associated with this expression. */ + IR::Instruction getUnconverted() { result = this.getInstruction(0) } + + /** + * Gets the final instruction associated with this expression. This + * represents the result after applying all the safe conversions. + */ + IR::Instruction getConverted() { + exists(int n | + result = this.getInstruction(n) and + not exists(this.getInstruction(n + 1)) + ) + } + + /** Gets the type of the result produced by this instruction. */ + IR::IRType getResultIRType() { result = this.getConverted().getResultIRType() } + + /** Gets the location of the source code for this expression. */ + Location getLocation() { result = this.getUnconverted().getLocation() } + } SemBasicBlock getExprBasicBlock(Expr e) { result = getSemanticBasicBlock(e.getBlock()) } private predicate anyConstantExpr(Expr expr, SemType type, string value) { - exists(IR::ConstantInstruction instr | instr = expr | + exists(IR::ConstantInstruction instr | getSemanticExpr(instr) = expr | type = getSemanticType(instr.getResultIRType()) and value = instr.getValue() ) @@ -58,41 +138,46 @@ module SemanticExprConfig { predicate nullLiteral(Expr expr, SemAddressType type) { anyConstantExpr(expr, type, _) } predicate stringLiteral(Expr expr, SemType type, string value) { - anyConstantExpr(expr, type, value) and expr instanceof IR::StringConstantInstruction + anyConstantExpr(expr, type, value) and + expr.getUnconverted() instanceof IR::StringConstantInstruction } predicate binaryExpr(Expr expr, Opcode opcode, SemType type, Expr leftOperand, Expr rightOperand) { - exists(IR::BinaryInstruction instr | instr = expr | + exists(IR::BinaryInstruction instr | + instr = expr.getUnconverted() and type = getSemanticType(instr.getResultIRType()) and - leftOperand = instr.getLeft() and - rightOperand = instr.getRight() and + leftOperand = getSemanticExpr(instr.getLeft()) and + rightOperand = getSemanticExpr(instr.getRight()) and // REVIEW: Merge the two `Opcode` types. opcode.toString() = instr.getOpcode().toString() ) } predicate unaryExpr(Expr expr, Opcode opcode, SemType type, Expr operand) { - type = getSemanticType(expr.getResultIRType()) and - ( - exists(IR::UnaryInstruction instr | instr = expr | - operand = instr.getUnary() and - // REVIEW: Merge the two operand types. - opcode.toString() = instr.getOpcode().toString() - ) - or - exists(IR::StoreInstruction instr | instr = expr | - operand = instr.getSourceValue() and - opcode instanceof Opcode::Store - ) + exists(IR::UnaryInstruction instr | instr = expr.getUnconverted() | + type = getSemanticType(instr.getResultIRType()) and + operand = getSemanticExpr(instr.getUnary()) and + // REVIEW: Merge the two operand types. + opcode.toString() = instr.getOpcode().toString() + ) + or + exists(IR::StoreInstruction instr | instr = expr.getUnconverted() | + type = getSemanticType(instr.getResultIRType()) and + operand = getSemanticExpr(instr.getSourceValue()) and + opcode instanceof Opcode::Store ) } predicate nullaryExpr(Expr expr, Opcode opcode, SemType type) { - type = getSemanticType(expr.getResultIRType()) and - ( - expr instanceof IR::LoadInstruction and opcode instanceof Opcode::Load - or - expr instanceof IR::InitializeParameterInstruction and + exists(IR::LoadInstruction load | + load = expr.getUnconverted() and + type = getSemanticType(load.getResultIRType()) and + opcode instanceof Opcode::Load + ) + or + exists(IR::InitializeParameterInstruction init | + init = expr.getUnconverted() and + type = getSemanticType(init.getResultIRType()) and opcode instanceof Opcode::InitializeParameter ) } @@ -122,8 +207,10 @@ module SemanticExprConfig { newtype TSsaVariable = TSsaInstruction(IR::Instruction instr) { instr.hasMemoryResult() } or TSsaOperand(IR::Operand op) { op.isDefinitionInexact() } or - TSsaPointerArithmeticGuard(IR::PointerArithmeticInstruction instr) { - exists(Guard g, IR::Operand use | use = instr.getAUse() | + TSsaPointerArithmeticGuard(ValueNumber instr) { + exists(Guard g, IR::Operand use | + use = instr.getAUse() and use.getIRType() instanceof IR::IRAddressType + | g.comparesLt(use, _, _, _, _) or g.comparesLt(_, use, _, _, _) or g.comparesEq(use, _, _, _, _) or @@ -138,7 +225,7 @@ module SemanticExprConfig { IR::Instruction asInstruction() { none() } - IR::PointerArithmeticInstruction asPointerArithGuard() { none() } + ValueNumber asPointerArithGuard() { none() } IR::Operand asOperand() { none() } } @@ -156,15 +243,15 @@ module SemanticExprConfig { } class SsaPointerArithmeticGuard extends SsaVariable, TSsaPointerArithmeticGuard { - IR::PointerArithmeticInstruction instr; + ValueNumber vn; - SsaPointerArithmeticGuard() { this = TSsaPointerArithmeticGuard(instr) } + SsaPointerArithmeticGuard() { this = TSsaPointerArithmeticGuard(vn) } - final override string toString() { result = instr.toString() } + final override string toString() { result = vn.toString() } - final override Location getLocation() { result = instr.getLocation() } + final override Location getLocation() { result = vn.getLocation() } - final override IR::PointerArithmeticInstruction asPointerArithGuard() { result = instr } + final override ValueNumber asPointerArithGuard() { result = vn } } class SsaOperand extends SsaVariable, TSsaOperand { @@ -179,7 +266,9 @@ module SemanticExprConfig { final override IR::Operand asOperand() { result = op } } - predicate explicitUpdate(SsaVariable v, Expr sourceExpr) { v.asInstruction() = sourceExpr } + predicate explicitUpdate(SsaVariable v, Expr sourceExpr) { + getSemanticExpr(v.asInstruction()) = sourceExpr + } predicate phi(SsaVariable v) { v.asInstruction() instanceof IR::PhiInstruction } @@ -192,9 +281,9 @@ module SemanticExprConfig { } Expr getAUse(SsaVariable v) { - result.(IR::LoadInstruction).getSourceValue() = v.asInstruction() + result.getUnconverted().(IR::LoadInstruction).getSourceValue() = v.asInstruction() or - result = valueNumber(v.asPointerArithGuard()).getAnInstruction() + result.getUnconverted() = v.asPointerArithGuard().getAnInstruction() } SemType getSsaVariableType(SsaVariable v) { @@ -236,7 +325,7 @@ module SemanticExprConfig { final override predicate hasRead(SsaVariable v) { exists(IR::Operand operand | operand.getDef() = v.asInstruction() or - operand.getDef() = valueNumber(v.asPointerArithGuard()).getAnInstruction() + operand.getDef() = v.asPointerArithGuard().getAnInstruction() | not operand instanceof IR::PhiInputOperand and operand.getUse().getBlock() = block @@ -257,7 +346,7 @@ module SemanticExprConfig { final override predicate hasRead(SsaVariable v) { exists(IR::PhiInputOperand operand | operand.getDef() = v.asInstruction() or - operand.getDef() = valueNumber(v.asPointerArithGuard()).getAnInstruction() + operand.getDef() = v.asPointerArithGuard().getAnInstruction() | operand.getPredecessorBlock() = pred and operand.getUse().getBlock() = succ @@ -303,17 +392,21 @@ module SemanticExprConfig { } Expr getBoundExpr(Bound bound, int delta) { - result = bound.(IRBound::Bound).getInstruction(delta) + result = getSemanticExpr(bound.(IRBound::Bound).getInstruction(delta)) } class Guard = IRGuards::IRGuardCondition; predicate guard(Guard guard, BasicBlock block) { block = guard.getBlock() } - Expr getGuardAsExpr(Guard guard) { result = guard } + Expr getGuardAsExpr(Guard guard) { result = getSemanticExpr(guard) } predicate equalityGuard(Guard guard, Expr e1, Expr e2, boolean polarity) { - guard.comparesEq(e1.getAUse(), e2.getAUse(), 0, true, polarity) + exists(IR::Instruction left, IR::Instruction right | + getSemanticExpr(left) = e1 and + getSemanticExpr(right) = e2 and + guard.comparesEq(left.getAUse(), right.getAUse(), 0, true, polarity) + ) } predicate guardDirectlyControlsBlock(Guard guard, BasicBlock controlled, boolean branch) { @@ -324,16 +417,17 @@ module SemanticExprConfig { guard.controlsEdge(bb1, bb2, branch) } - Guard comparisonGuard(Expr e) { result = e } + Guard comparisonGuard(Expr e) { getSemanticExpr(result) = e } predicate implies_v2(Guard g1, boolean b1, Guard g2, boolean b2) { none() // TODO } + + /** Gets the expression associated with `instr`. */ + SemExpr getSemanticExpr(IR::Instruction instr) { result = Equiv::getEquivalenceClass(instr) } } -SemExpr getSemanticExpr(IR::Instruction instr) { result = instr } - -IR::Instruction getCppInstruction(SemExpr e) { e = result } +predicate getSemanticExpr = SemanticExprConfig::getSemanticExpr/1; SemBasicBlock getSemanticBasicBlock(IR::IRBlock block) { result = block } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticType.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticType.qll index ce3f4ed90b4..b86db02702c 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticType.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticType.qll @@ -250,16 +250,26 @@ SemType getSemanticType(Specific::Type type) { Specific::unknownType(type) and result = TSemUnknownType() } +private class SemNumericOrBooleanType extends SemSizedType { + SemNumericOrBooleanType() { + this instanceof SemNumericType + or + this instanceof SemBooleanType + } +} + /** * Holds if the conversion from `fromType` to `toType` can never overflow or underflow. */ -predicate conversionCannotOverflow(SemNumericType fromType, SemNumericType toType) { +predicate conversionCannotOverflow(SemNumericOrBooleanType fromType, SemNumericOrBooleanType toType) { // Identity cast fromType = toType or // Treat any cast to an FP type as safe. It can lose precision, but not overflow. toType instanceof SemFloatingPointType and fromType = any(SemNumericType n) or + fromType instanceof SemBooleanType and toType instanceof SemIntegerType + or exists(SemIntegerType fromInteger, SemIntegerType toInteger, int fromSize, int toSize | fromInteger = fromType and toInteger = toType and diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/FloatDelta.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/FloatDelta.qll index 500f7b2cac5..f6004cdaa80 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/FloatDelta.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/FloatDelta.qll @@ -17,16 +17,7 @@ module FloatDelta implements DeltaSig { Delta fromInt(int n) { result = n } bindingset[f] - Delta fromFloat(float f) { - result = - min(float diff, float res | - diff = (res - f) and res = f.ceil() - or - diff = (f - res) and res = f.floor() - | - res order by diff - ) - } + Delta fromFloat(float f) { result = f } } module FloatOverflow implements OverflowSig { diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll index 639d1176a91..2c8d3742ec2 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll @@ -502,7 +502,7 @@ UtilSig UtilParam> { SemSsaVariable v2, SemGuard guardEq, boolean eqIsTrue, D::Delta d1, D::Delta d2, D::Delta oldDelta | - guardEq = semEqFlowCond(v, semSsaRead(v2, d1), d2, true, eqIsTrue) and + guardEq = semEqFlowCond(v, semSsaRead(pragma[only_bind_into](v2), d1), d2, true, eqIsTrue) and result = boundFlowCond(v2, e, oldDelta, upper, testIsTrue) and // guardEq needs to control guard guardEq.directlyControls(result.getBasicBlock(), eqIsTrue) and @@ -598,24 +598,6 @@ UtilSig UtilParam> { delta = D::fromInt(0) and (upper = true or upper = false) or - exists(SemExpr x | e2.(SemAddExpr).hasOperands(e1, x) | - // `x instanceof ConstantIntegerExpr` is covered by valueFlowStep - not x instanceof SemConstantIntegerExpr and - not e1 instanceof SemConstantIntegerExpr and - if strictlyPositiveIntegralExpr(x) - then upper = false and delta = D::fromInt(1) - else - if semPositive(x) - then upper = false and delta = D::fromInt(0) - else - if strictlyNegativeIntegralExpr(x) - then upper = true and delta = D::fromInt(-1) - else - if semNegative(x) - then upper = true and delta = D::fromInt(0) - else none() - ) - or exists(SemExpr x, SemSubExpr sub | e2 = sub and sub.getLeftOperand() = e1 and @@ -1085,13 +1067,196 @@ UtilSig UtilParam> { delta = D::fromFloat(f) and if semPositive(e) then f >= 0 else any() ) + or + exists( + SemBound bLeft, SemBound bRight, D::Delta dLeft, D::Delta dRight, boolean fbeLeft, + boolean fbeRight, D::Delta odLeft, D::Delta odRight, SemReason rLeft, SemReason rRight + | + boundedAddOperand(e, upper, bLeft, false, dLeft, fbeLeft, odLeft, rLeft) and + boundedAddOperand(e, upper, bRight, true, dRight, fbeRight, odRight, rRight) and + delta = D::fromFloat(D::toFloat(dLeft) + D::toFloat(dRight)) and + fromBackEdge = fbeLeft.booleanOr(fbeRight) + | + b = bLeft and origdelta = odLeft and reason = rLeft and bRight instanceof SemZeroBound + or + b = bRight and origdelta = odRight and reason = rRight and bLeft instanceof SemZeroBound + ) + or + exists( + SemRemExpr rem, D::Delta d_max, D::Delta d1, D::Delta d2, boolean fbe1, boolean fbe2, + D::Delta od1, D::Delta od2, SemReason r1, SemReason r2 + | + rem = e and + b instanceof SemZeroBound and + not (upper = true and semPositive(rem.getRightOperand())) and + not (upper = true and semPositive(rem.getLeftOperand())) and + boundedRemExpr(rem, true, d1, fbe1, od1, r1) and + boundedRemExpr(rem, false, d2, fbe2, od2, r2) and + ( + if D::toFloat(d1).abs() > D::toFloat(d2).abs() + then ( + d_max = d1 and fromBackEdge = fbe1 and origdelta = od1 and reason = r1 + ) else ( + d_max = d2 and fromBackEdge = fbe2 and origdelta = od2 and reason = r2 + ) + ) + | + upper = true and delta = D::fromFloat(D::toFloat(d_max).abs() - 1) + or + upper = false and delta = D::fromFloat(-D::toFloat(d_max).abs() + 1) + ) + or + exists( + D::Delta dLeft, D::Delta dRight, boolean fbeLeft, boolean fbeRight, D::Delta odLeft, + D::Delta odRight, SemReason rLeft, SemReason rRight + | + boundedMulOperand(e, upper, true, dLeft, fbeLeft, odLeft, rLeft) and + boundedMulOperand(e, upper, false, dRight, fbeRight, odRight, rRight) and + delta = D::fromFloat(D::toFloat(dLeft) * D::toFloat(dRight)) and + fromBackEdge = fbeLeft.booleanOr(fbeRight) + | + b instanceof SemZeroBound and origdelta = odLeft and reason = rLeft + or + b instanceof SemZeroBound and origdelta = odRight and reason = rRight + ) ) } + pragma[nomagic] private predicate boundedConditionalExpr( SemConditionalExpr cond, SemBound b, boolean upper, boolean branch, D::Delta delta, boolean fromBackEdge, D::Delta origdelta, SemReason reason ) { bounded(cond.getBranchExpr(branch), b, delta, upper, fromBackEdge, origdelta, reason) } + + pragma[nomagic] + private predicate boundedAddOperand( + SemAddExpr add, boolean upper, SemBound b, boolean isLeft, D::Delta delta, boolean fromBackEdge, + D::Delta origdelta, SemReason reason + ) { + // `semValueFlowStep` already handles the case where one of the operands is a constant. + not semValueFlowStep(add, _, _) and + ( + isLeft = true and + bounded(add.getLeftOperand(), b, delta, upper, fromBackEdge, origdelta, reason) + or + isLeft = false and + bounded(add.getRightOperand(), b, delta, upper, fromBackEdge, origdelta, reason) + ) + } + + pragma[nomagic] + private predicate boundedRemExpr( + SemRemExpr rem, boolean upper, D::Delta delta, boolean fromBackEdge, D::Delta origdelta, + SemReason reason + ) { + bounded(rem.getRightOperand(), any(SemZeroBound zb), delta, upper, fromBackEdge, origdelta, + reason) + } + + /** + * Define `cmp(true) = <=` and `cmp(false) = >=`. + * + * Holds if `mul = left * right`, and in order to know if `mul cmp(upper) 0 + k` (for + * some `k`) we need to know that `left cmp(upperLeft) 0 + k1` and + * `right cmp(upperRight) 0 + k2` (for some `k1` and `k2`). + */ + pragma[nomagic] + private predicate boundedMulOperandCand( + SemMulExpr mul, SemExpr left, SemExpr right, boolean upper, boolean upperLeft, + boolean upperRight + ) { + not boundFlowStepMul(mul, _, _) and + mul.getLeftOperand() = left and + mul.getRightOperand() = right and + ( + semPositive(left) and + ( + // left, right >= 0 + semPositive(right) and + ( + // max(left * right) = max(left) * max(right) + upper = true and + upperLeft = true and + upperRight = true + or + // min(left * right) = min(left) * min(right) + upper = false and + upperLeft = false and + upperRight = false + ) + or + // left >= 0, right <= 0 + semNegative(right) and + ( + // max(left * right) = min(left) * max(right) + upper = true and + upperLeft = false and + upperRight = true + or + // min(left * right) = max(left) * min(right) + upper = false and + upperLeft = true and + upperRight = false + ) + ) + or + semNegative(left) and + ( + // left <= 0, right >= 0 + semPositive(right) and + ( + // max(left * right) = max(left) * min(right) + upper = true and + upperLeft = true and + upperRight = false + or + // min(left * right) = min(left) * max(right) + upper = false and + upperLeft = false and + upperRight = true + ) + or + // left, right <= 0 + semNegative(right) and + ( + // max(left * right) = min(left) * min(right) + upper = true and + upperLeft = false and + upperRight = false + or + // min(left * right) = max(left) * max(right) + upper = false and + upperLeft = true and + upperRight = true + ) + ) + ) + } + + /** + * Holds if `isLeft = true` and `mul`'s left operand is bounded by `delta`, + * or if `isLeft = false` and `mul`'s right operand is bounded by `delta`. + * + * If `upper = true` the computed bound contributes to an upper bound of `mul`, + * and if `upper = false` it contributes to a lower bound. + * The `fromBackEdge`, `origdelta`, `reason` triple are defined by the recursive + * call to `bounded`. + */ + pragma[nomagic] + private predicate boundedMulOperand( + SemMulExpr mul, boolean upper, boolean isLeft, D::Delta delta, boolean fromBackEdge, + D::Delta origdelta, SemReason reason + ) { + exists(boolean upperLeft, boolean upperRight, SemExpr left, SemExpr right | + boundedMulOperandCand(mul, left, right, upper, upperLeft, upperRight) + | + isLeft = true and + bounded(left, any(SemZeroBound zb), delta, upperLeft, fromBackEdge, origdelta, reason) + or + isLeft = false and + bounded(right, any(SemZeroBound zb), delta, upperRight, fromBackEdge, origdelta, reason) + ) + } } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SignAnalysisCommon.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SignAnalysisCommon.qll index 94ef40e83fa..ec3427558d4 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SignAnalysisCommon.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SignAnalysisCommon.qll @@ -198,6 +198,16 @@ module SignAnalysis Utils> { } } + /** An expression of an unsigned type. */ + private class UnsignedExpr extends FlowSignExpr { + UnsignedExpr() { Utils::getTrackedType(this) instanceof SemUnsignedIntegerType } + + override Sign getSignRestriction() { + result = TPos() or + result = TZero() + } + } + pragma[nomagic] private predicate binaryExprOperands(SemBinaryExpr binary, SemExpr left, SemExpr right) { binary.getLeftOperand() = left and binary.getRightOperand() = right @@ -328,10 +338,11 @@ module SignAnalysis Utils> { * - `isEq = false` : `v != eqbound` */ private predicate eqBound(SemExpr eqbound, SemSsaVariable v, SemSsaReadPosition pos, boolean isEq) { - exists(SemGuard guard, boolean testIsTrue, boolean polarity | - pos.hasReadOfVar(v) and - semGuardControlsSsaRead(guard, pos, testIsTrue) and - guard.isEquality(eqbound, Utils::semSsaRead(v, D::fromInt(0)), polarity) and + exists(SemGuard guard, boolean testIsTrue, boolean polarity, SemExpr e | + pos.hasReadOfVar(pragma[only_bind_into](v)) and + semGuardControlsSsaRead(guard, pragma[only_bind_into](pos), testIsTrue) and + e = Utils::semSsaRead(pragma[only_bind_into](v), D::fromInt(0)) and + guard.isEquality(eqbound, e, polarity) and isEq = polarity.booleanXor(testIsTrue).booleanNot() and not unknownSign(eqbound) ) diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index 12ad778c119..aa4f7c79fef 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -8,3 +8,4 @@ upgrades: upgrades dependencies: codeql/ssa: ${workspace} codeql/tutorial: ${workspace} + codeql/util: ${workspace} diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlow.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlow.qll index 617362ab4f0..865d7b4d6ce 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlow.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlow.qll @@ -2,7 +2,7 @@ * Provides an implementation of global (interprocedural) data flow. This file * re-exports the local (intraprocedural) data flow analysis from * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Make` and `MakeWithState` modules. + * through the `Global` and `GlobalWithState` modules. */ private import DataFlowImplCommon @@ -73,10 +73,10 @@ signature module ConfigSig { */ default FlowFeature getAFeature() { none() } - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ default predicate sourceGrouping(Node source, string sourceGroup) { none() } - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ default predicate sinkGrouping(Node sink, string sinkGroup) { none() } /** @@ -166,10 +166,10 @@ signature module StateConfigSig { */ default FlowFeature getAFeature() { none() } - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ default predicate sourceGrouping(Node source, string sourceGroup) { none() } - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ default predicate sinkGrouping(Node sink, string sinkGroup) { none() } /** @@ -182,15 +182,15 @@ signature module StateConfigSig { } /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * Gets the exploration limit for `partialFlow` and `partialFlowRev` * measured in approximate number of interprocedural steps. */ signature int explorationLimitSig(); /** - * The output of a data flow computation. + * The output of a global data flow computation. */ -signature module DataFlowSig { +signature module GlobalFlowSig { /** * A `Node` augmented with a call context (except for sinks) and an access path. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. @@ -203,28 +203,28 @@ signature module DataFlowSig { * The corresponding paths are generated from the end-points and the graph * included in the module `PathGraph`. */ - predicate hasFlowPath(PathNode source, PathNode sink); + predicate flowPath(PathNode source, PathNode sink); /** * Holds if data can flow from `source` to `sink`. */ - predicate hasFlow(Node source, Node sink); + predicate flow(Node source, Node sink); /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowTo(Node sink); + predicate flowTo(Node sink); /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowToExpr(DataFlowExpr sink); + predicate flowToExpr(DataFlowExpr sink); } /** - * Constructs a standard data flow computation. + * Constructs a global data flow computation. */ -module Make implements DataFlowSig { +module Global implements GlobalFlowSig { private module C implements FullStateConfigSig { import DefaultState import Config @@ -233,10 +233,15 @@ module Make implements DataFlowSig { import Impl } +/** DEPRECATED: Use `Global` instead. */ +deprecated module Make implements GlobalFlowSig { + import Global +} + /** - * Constructs a data flow computation using flow state. + * Constructs a global data flow computation using flow state. */ -module MakeWithState implements DataFlowSig { +module GlobalWithState implements GlobalFlowSig { private module C implements FullStateConfigSig { import Config } @@ -244,6 +249,11 @@ module MakeWithState implements DataFlowSig { import Impl } +/** DEPRECATED: Use `GlobalWithState` instead. */ +deprecated module MakeWithState implements GlobalFlowSig { + import GlobalWithState +} + signature class PathNodeSig { /** Gets a textual representation of this element. */ string toString(); diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index c47b0308855..6ea97954bdf 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -8,6 +8,7 @@ private import DataFlowImplCommon private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommonPublic +private import codeql.util.Unit import DataFlow /** @@ -91,10 +92,10 @@ signature module FullStateConfigSig { */ FlowFeature getAFeature(); - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ predicate sourceGrouping(Node source, string sourceGroup); - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ predicate sinkGrouping(Node sink, string sinkGroup); /** @@ -445,11 +446,7 @@ module Impl { } private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } + class Ap = Unit; private class Cc = boolean; @@ -3633,7 +3630,7 @@ module Impl { * The corresponding paths are generated from the end-points and the graph * included in the module `PathGraph`. */ - predicate hasFlowPath(PathNode source, PathNode sink) { + predicate flowPath(PathNode source, PathNode sink) { exists(PathNodeImpl flowsource, PathNodeImpl flowsink | source = flowsource and sink = flowsink | @@ -3643,6 +3640,9 @@ module Impl { ) } + /** DEPRECATED: Use `flowPath` instead. */ + deprecated predicate hasFlowPath = flowPath/2; + private predicate flowsTo(PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink) { flowsource.isSource() and flowsource.getNodeEx().asNode() = source and @@ -3653,17 +3653,26 @@ module Impl { /** * Holds if data can flow from `source` to `sink`. */ - predicate hasFlow(Node source, Node sink) { flowsTo(_, _, source, sink) } + predicate flow(Node source, Node sink) { flowsTo(_, _, source, sink) } + + /** DEPRECATED: Use `flow` instead. */ + deprecated predicate hasFlow = flow/2; /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + predicate flowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + + /** DEPRECATED: Use `flowTo` instead. */ + deprecated predicate hasFlowTo = flowTo/1; /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate flowToExpr(DataFlowExpr sink) { flowTo(exprNode(sink)) } + + /** DEPRECATED: Use `flowToExpr` instead. */ + deprecated predicate hasFlowToExpr = flowToExpr/1; private predicate finalStats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples @@ -4574,7 +4583,7 @@ module Impl { * * To use this in a `path-problem` query, import the module `PartialPathGraph`. */ - predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { + predicate partialFlow(PartialPathNode source, PartialPathNode node, int dist) { partialFlow(source, node) and dist = node.getSourceDistance() } @@ -4594,7 +4603,7 @@ module Impl { * Note that reverse flow has slightly lower precision than the corresponding * forward flow, as reverse flow disregards type pruning among other features. */ - predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { + predicate partialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { revPartialFlow(node, sink) and dist = node.getSinkDistance() } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll index e6bdc74cceb..be70086a93a 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index e6bdc74cceb..be70086a93a 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index e6bdc74cceb..be70086a93a 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index e6bdc74cceb..be70086a93a 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll index d09fdcfca3e..e6fce328326 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -140,10 +140,8 @@ private module LambdaFlow { } pragma[nomagic] - private TReturnPositionSimple viableReturnPosLambda( - DataFlowCall call, DataFlowCallOption lastCall, ReturnKind kind - ) { - result = TReturnPositionSimple0(viableCallableLambda(call, lastCall), kind) + private TReturnPositionSimple viableReturnPosLambda(DataFlowCall call, ReturnKind kind) { + result = TReturnPositionSimple0(viableCallableLambda(call, _), kind) } private predicate viableReturnPosOutNonLambda( @@ -155,11 +153,12 @@ private module LambdaFlow { ) } + pragma[nomagic] private predicate viableReturnPosOutLambda( - DataFlowCall call, DataFlowCallOption lastCall, TReturnPositionSimple pos, OutNode out + DataFlowCall call, TReturnPositionSimple pos, OutNode out ) { exists(ReturnKind kind | - pos = viableReturnPosLambda(call, lastCall, kind) and + pos = viableReturnPosLambda(call, kind) and out = getAnOutNode(call, kind) ) } @@ -188,6 +187,7 @@ private module LambdaFlow { else any() } + pragma[assume_small_delta] pragma[nomagic] predicate revLambdaFlow0( DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn, @@ -274,6 +274,7 @@ private module LambdaFlow { ) } + pragma[assume_small_delta] pragma[nomagic] predicate revLambdaFlowOut( DataFlowCall lambdaCall, LambdaCallKind kind, TReturnPositionSimple pos, DataFlowType t, @@ -285,7 +286,7 @@ private module LambdaFlow { or // non-linear recursion revLambdaFlowOutLambdaCall(lambdaCall, kind, out, t, toJump, call, lastCall) and - viableReturnPosOutLambda(call, _, pos, out) + viableReturnPosOutLambda(call, pos, out) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index e6bdc74cceb..be70086a93a 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index f54e3b9a9cb..6f2da96f27f 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -3,6 +3,7 @@ private import DataFlowUtil private import DataFlowDispatch private import FlowVar private import DataFlowImplConsistency +private import codeql.util.Unit /** Gets the callable in which this node occurs. */ DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() } @@ -264,15 +265,6 @@ int accessPathLimit() { result = 5 } */ predicate forceHighPrecision(Content c) { none() } -/** The unit type. */ -private newtype TUnit = TMkUnit() - -/** The trivial type with a single element. */ -class Unit extends TUnit { - /** Gets a textual representation of this element. */ - string toString() { result = "unit" } -} - /** Holds if `n` should be hidden from path explanations. */ predicate nodeIsHidden(Node n) { none() } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTracking.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTracking.qll index 7f96fe5e6fb..872ac8d4cb8 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTracking.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTracking.qll @@ -33,9 +33,9 @@ private module AddTaintDefaults imp } /** - * Constructs a standard taint tracking computation. + * Constructs a global taint tracking computation. */ -module Make implements DataFlow::DataFlowSig { +module Global implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import DataFlowInternal::DefaultState import Config @@ -48,10 +48,15 @@ module Make implements DataFlow::DataFlowSig { import DataFlowInternal::Impl } +/** DEPRECATED: Use `Global` instead. */ +deprecated module Make implements DataFlow::GlobalFlowSig { + import Global +} + /** - * Constructs a taint tracking computation using flow state. + * Constructs a global taint tracking computation using flow state. */ -module MakeWithState implements DataFlow::DataFlowSig { +module GlobalWithState implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import Config } @@ -62,3 +67,8 @@ module MakeWithState implements DataFlow::DataF import DataFlowInternal::Impl } + +/** DEPRECATED: Use `GlobalWithState` instead. */ +deprecated module MakeWithState implements DataFlow::GlobalFlowSig { + import GlobalWithState +} diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlow.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlow.qll index 617362ab4f0..865d7b4d6ce 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlow.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlow.qll @@ -2,7 +2,7 @@ * Provides an implementation of global (interprocedural) data flow. This file * re-exports the local (intraprocedural) data flow analysis from * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Make` and `MakeWithState` modules. + * through the `Global` and `GlobalWithState` modules. */ private import DataFlowImplCommon @@ -73,10 +73,10 @@ signature module ConfigSig { */ default FlowFeature getAFeature() { none() } - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ default predicate sourceGrouping(Node source, string sourceGroup) { none() } - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ default predicate sinkGrouping(Node sink, string sinkGroup) { none() } /** @@ -166,10 +166,10 @@ signature module StateConfigSig { */ default FlowFeature getAFeature() { none() } - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ default predicate sourceGrouping(Node source, string sourceGroup) { none() } - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ default predicate sinkGrouping(Node sink, string sinkGroup) { none() } /** @@ -182,15 +182,15 @@ signature module StateConfigSig { } /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * Gets the exploration limit for `partialFlow` and `partialFlowRev` * measured in approximate number of interprocedural steps. */ signature int explorationLimitSig(); /** - * The output of a data flow computation. + * The output of a global data flow computation. */ -signature module DataFlowSig { +signature module GlobalFlowSig { /** * A `Node` augmented with a call context (except for sinks) and an access path. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. @@ -203,28 +203,28 @@ signature module DataFlowSig { * The corresponding paths are generated from the end-points and the graph * included in the module `PathGraph`. */ - predicate hasFlowPath(PathNode source, PathNode sink); + predicate flowPath(PathNode source, PathNode sink); /** * Holds if data can flow from `source` to `sink`. */ - predicate hasFlow(Node source, Node sink); + predicate flow(Node source, Node sink); /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowTo(Node sink); + predicate flowTo(Node sink); /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowToExpr(DataFlowExpr sink); + predicate flowToExpr(DataFlowExpr sink); } /** - * Constructs a standard data flow computation. + * Constructs a global data flow computation. */ -module Make implements DataFlowSig { +module Global implements GlobalFlowSig { private module C implements FullStateConfigSig { import DefaultState import Config @@ -233,10 +233,15 @@ module Make implements DataFlowSig { import Impl } +/** DEPRECATED: Use `Global` instead. */ +deprecated module Make implements GlobalFlowSig { + import Global +} + /** - * Constructs a data flow computation using flow state. + * Constructs a global data flow computation using flow state. */ -module MakeWithState implements DataFlowSig { +module GlobalWithState implements GlobalFlowSig { private module C implements FullStateConfigSig { import Config } @@ -244,6 +249,11 @@ module MakeWithState implements DataFlowSig { import Impl } +/** DEPRECATED: Use `GlobalWithState` instead. */ +deprecated module MakeWithState implements GlobalFlowSig { + import GlobalWithState +} + signature class PathNodeSig { /** Gets a textual representation of this element. */ string toString(); diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index c47b0308855..6ea97954bdf 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -8,6 +8,7 @@ private import DataFlowImplCommon private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommonPublic +private import codeql.util.Unit import DataFlow /** @@ -91,10 +92,10 @@ signature module FullStateConfigSig { */ FlowFeature getAFeature(); - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ predicate sourceGrouping(Node source, string sourceGroup); - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ predicate sinkGrouping(Node sink, string sinkGroup); /** @@ -445,11 +446,7 @@ module Impl { } private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } + class Ap = Unit; private class Cc = boolean; @@ -3633,7 +3630,7 @@ module Impl { * The corresponding paths are generated from the end-points and the graph * included in the module `PathGraph`. */ - predicate hasFlowPath(PathNode source, PathNode sink) { + predicate flowPath(PathNode source, PathNode sink) { exists(PathNodeImpl flowsource, PathNodeImpl flowsink | source = flowsource and sink = flowsink | @@ -3643,6 +3640,9 @@ module Impl { ) } + /** DEPRECATED: Use `flowPath` instead. */ + deprecated predicate hasFlowPath = flowPath/2; + private predicate flowsTo(PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink) { flowsource.isSource() and flowsource.getNodeEx().asNode() = source and @@ -3653,17 +3653,26 @@ module Impl { /** * Holds if data can flow from `source` to `sink`. */ - predicate hasFlow(Node source, Node sink) { flowsTo(_, _, source, sink) } + predicate flow(Node source, Node sink) { flowsTo(_, _, source, sink) } + + /** DEPRECATED: Use `flow` instead. */ + deprecated predicate hasFlow = flow/2; /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + predicate flowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + + /** DEPRECATED: Use `flowTo` instead. */ + deprecated predicate hasFlowTo = flowTo/1; /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate flowToExpr(DataFlowExpr sink) { flowTo(exprNode(sink)) } + + /** DEPRECATED: Use `flowToExpr` instead. */ + deprecated predicate hasFlowToExpr = flowToExpr/1; private predicate finalStats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples @@ -4574,7 +4583,7 @@ module Impl { * * To use this in a `path-problem` query, import the module `PartialPathGraph`. */ - predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { + predicate partialFlow(PartialPathNode source, PartialPathNode node, int dist) { partialFlow(source, node) and dist = node.getSourceDistance() } @@ -4594,7 +4603,7 @@ module Impl { * Note that reverse flow has slightly lower precision than the corresponding * forward flow, as reverse flow disregards type pruning among other features. */ - predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { + predicate partialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { revPartialFlow(node, sink) and dist = node.getSinkDistance() } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll index e6bdc74cceb..be70086a93a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index e6bdc74cceb..be70086a93a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index e6bdc74cceb..be70086a93a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index e6bdc74cceb..be70086a93a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll index d09fdcfca3e..e6fce328326 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll @@ -140,10 +140,8 @@ private module LambdaFlow { } pragma[nomagic] - private TReturnPositionSimple viableReturnPosLambda( - DataFlowCall call, DataFlowCallOption lastCall, ReturnKind kind - ) { - result = TReturnPositionSimple0(viableCallableLambda(call, lastCall), kind) + private TReturnPositionSimple viableReturnPosLambda(DataFlowCall call, ReturnKind kind) { + result = TReturnPositionSimple0(viableCallableLambda(call, _), kind) } private predicate viableReturnPosOutNonLambda( @@ -155,11 +153,12 @@ private module LambdaFlow { ) } + pragma[nomagic] private predicate viableReturnPosOutLambda( - DataFlowCall call, DataFlowCallOption lastCall, TReturnPositionSimple pos, OutNode out + DataFlowCall call, TReturnPositionSimple pos, OutNode out ) { exists(ReturnKind kind | - pos = viableReturnPosLambda(call, lastCall, kind) and + pos = viableReturnPosLambda(call, kind) and out = getAnOutNode(call, kind) ) } @@ -188,6 +187,7 @@ private module LambdaFlow { else any() } + pragma[assume_small_delta] pragma[nomagic] predicate revLambdaFlow0( DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn, @@ -274,6 +274,7 @@ private module LambdaFlow { ) } + pragma[assume_small_delta] pragma[nomagic] predicate revLambdaFlowOut( DataFlowCall lambdaCall, LambdaCallKind kind, TReturnPositionSimple pos, DataFlowType t, @@ -285,7 +286,7 @@ private module LambdaFlow { or // non-linear recursion revLambdaFlowOutLambdaCall(lambdaCall, kind, out, t, toJump, call, lastCall) and - viableReturnPosOutLambda(call, _, pos, out) + viableReturnPosOutLambda(call, pos, out) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 9d69856e20b..30fdf102b6b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -6,6 +6,7 @@ private import DataFlowImplConsistency private import semmle.code.cpp.ir.internal.IRCppLanguage private import SsaInternals as Ssa private import DataFlowImplCommon as DataFlowImplCommon +private import codeql.util.Unit cached private module Cached { @@ -799,15 +800,6 @@ int accessPathLimit() { result = 5 } */ predicate forceHighPrecision(Content c) { none() } -/** The unit type. */ -private newtype TUnit = TMkUnit() - -/** The trivial type with a single element. */ -class Unit extends TUnit { - /** Gets a textual representation of this element. */ - string toString() { result = "unit" } -} - /** Holds if `n` should be hidden from path explanations. */ predicate nodeIsHidden(Node n) { n instanceof OperandNode and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DefaultTaintTrackingImpl.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DefaultTaintTrackingImpl.qll index 2c288b6d3da..e21a83fcb54 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DefaultTaintTrackingImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DefaultTaintTrackingImpl.qll @@ -103,7 +103,7 @@ private module DefaultTaintTrackingConfig implements DataFlow::ConfigSig { } } -private module DefaultTaintTrackingFlow = TaintTracking::Make; +private module DefaultTaintTrackingFlow = TaintTracking::Global; private module ToGlobalVarTaintTrackingConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source = getNodeForSource(_) } @@ -121,13 +121,13 @@ private module ToGlobalVarTaintTrackingConfig implements DataFlow::ConfigSig { predicate isBarrierIn(DataFlow::Node node) { nodeIsBarrierIn(node) } } -private module ToGlobalVarTaintTrackingFlow = TaintTracking::Make; +private module ToGlobalVarTaintTrackingFlow = TaintTracking::Global; private module FromGlobalVarTaintTrackingConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { // This set of sources should be reasonably small, which is good for // performance since the set of sinks is very large. - ToGlobalVarTaintTrackingFlow::hasFlowTo(source) + ToGlobalVarTaintTrackingFlow::flowTo(source) } predicate isSink(DataFlow::Node sink) { exists(adjustedSink(sink)) } @@ -145,7 +145,7 @@ private module FromGlobalVarTaintTrackingConfig implements DataFlow::ConfigSig { } private module FromGlobalVarTaintTrackingFlow = - TaintTracking::Make; + TaintTracking::Global; private predicate readsVariable(LoadInstruction load, Variable var) { load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var @@ -331,7 +331,7 @@ private import Cached cached predicate tainted(Expr source, Element tainted) { exists(DataFlow::Node sink | - DefaultTaintTrackingFlow::hasFlow(getNodeForSource(source), sink) and + DefaultTaintTrackingFlow::flow(getNodeForSource(source), sink) and tainted = adjustedSink(sink) ) } @@ -360,8 +360,8 @@ predicate taintedIncludingGlobalVars(Expr source, Element tainted, string global DataFlow::VariableNode variableNode, GlobalOrNamespaceVariable global, DataFlow::Node sink | global = variableNode.getVariable() and - ToGlobalVarTaintTrackingFlow::hasFlow(getNodeForSource(source), variableNode) and - FromGlobalVarTaintTrackingFlow::hasFlow(variableNode, sink) and + ToGlobalVarTaintTrackingFlow::flow(getNodeForSource(source), variableNode) and + FromGlobalVarTaintTrackingFlow::flow(variableNode, sink) and tainted = adjustedSink(sink) and global = globalVarFromId(globalVar) ) @@ -450,7 +450,7 @@ module TaintedWithPath { predicate isBarrierIn(DataFlow::Node node) { nodeIsBarrierIn(node) } } - private module AdjustedFlow = TaintTracking::Make; + private module AdjustedFlow = TaintTracking::Global; /* * A sink `Element` may map to multiple `DataFlowX::PathNode`s via (the @@ -472,7 +472,7 @@ module TaintedWithPath { // that makes it easiest to deal with the case where source = sink. TEndpointPathNode(Element e) { exists(DataFlow::Node sourceNode, DataFlow::Node sinkNode | - AdjustedFlow::hasFlow(sourceNode, sinkNode) + AdjustedFlow::flow(sourceNode, sinkNode) | sourceNode = getNodeForExpr(e) and exists(TaintTrackingConfiguration ttCfg | ttCfg.isSource(e)) @@ -634,7 +634,7 @@ module TaintedWithPath { exists(DataFlow::Node flowSource, DataFlow::Node flowSink | source = sourceNode.(InitialPathNode).inner() and flowSource = getNodeForExpr(source) and - AdjustedFlow::hasFlow(flowSource, flowSink) and + AdjustedFlow::flow(flowSource, flowSink) and tainted = adjustedSink(flowSink) and tainted = sinkNode.(FinalPathNode).inner() ) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTracking.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTracking.qll index 7f96fe5e6fb..872ac8d4cb8 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTracking.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTracking.qll @@ -33,9 +33,9 @@ private module AddTaintDefaults imp } /** - * Constructs a standard taint tracking computation. + * Constructs a global taint tracking computation. */ -module Make implements DataFlow::DataFlowSig { +module Global implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import DataFlowInternal::DefaultState import Config @@ -48,10 +48,15 @@ module Make implements DataFlow::DataFlowSig { import DataFlowInternal::Impl } +/** DEPRECATED: Use `Global` instead. */ +deprecated module Make implements DataFlow::GlobalFlowSig { + import Global +} + /** - * Constructs a taint tracking computation using flow state. + * Constructs a global taint tracking computation using flow state. */ -module MakeWithState implements DataFlow::DataFlowSig { +module GlobalWithState implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import Config } @@ -62,3 +67,8 @@ module MakeWithState implements DataFlow::DataF import DataFlowInternal::Impl } + +/** DEPRECATED: Use `GlobalWithState` instead. */ +deprecated module MakeWithState implements DataFlow::GlobalFlowSig { + import GlobalWithState +} diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll index da4183ca25c..f0d8e5d3d35 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll @@ -1105,3 +1105,49 @@ class TranslatedAsmStmt extends TranslatedStmt { ) } } + +class TranslatedVlaDimensionStmt extends TranslatedStmt { + override VlaDimensionStmt stmt; + + override TranslatedExpr getChild(int id) { + id = 0 and + result = getTranslatedExpr(stmt.getDimensionExpr().getFullyConverted()) + } + + override Instruction getFirstInstruction() { result = this.getChild(0).getFirstInstruction() } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { + none() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = this.getChild(0) and + result = this.getParent().getChildSuccessor(this) + } +} + +class TranslatedVlaDeclarationStmt extends TranslatedStmt { + override VlaDeclStmt stmt; + + override TranslatedExpr getChild(int id) { none() } + + override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { + // TODO: This needs a new kind of instruction that represents initialization of a VLA. + // For now we just emit a `NoOp` instruction so that the CFG isn't incomplete. + tag = OnlyInstructionTag() and + opcode instanceof Opcode::NoOp and + resultType = getVoidType() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + tag = OnlyInstructionTag() and + result = this.getParent().getChildSuccessor(this) and + kind instanceof GotoEdge + } + + override Instruction getChildSuccessor(TranslatedElement child) { none() } +} diff --git a/cpp/ql/lib/semmle/code/cpp/security/BufferAccess.qll b/cpp/ql/lib/semmle/code/cpp/security/BufferAccess.qll index e52babcfe2e..b8c5d67dc05 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/BufferAccess.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/BufferAccess.qll @@ -29,7 +29,23 @@ abstract class BufferAccess extends Expr { */ abstract Expr getBuffer(string bufferDesc, int accessType); - abstract int getSize(); + /** + * Gets the expression that represents the size of the buffer access. The + * actual size is typically the value of this expression multiplied by the + * result of `getSizeMult()`, in bytes. + */ + Expr getSizeExpr() { none() } + + /** + * Gets a constant multiplier for the buffer access size given by + * `getSizeExpr`, in bytes. + */ + int getSizeMult() { none() } + + /** + * Gets the buffer access size in bytes. + */ + int getSize() { result = this.getSizeExpr().getValue().toInt() * this.getSizeMult() } } /** @@ -63,10 +79,10 @@ class MemcpyBA extends BufferAccess { accessType = 1 } - override int getSize() { - result = - this.(FunctionCall).getArgument(2).getValue().toInt() * - getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) + override Expr getSizeExpr() { result = this.(FunctionCall).getArgument(2) } + + override int getSizeMult() { + result = getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) } } @@ -89,10 +105,10 @@ class BCopyBA extends BufferAccess { accessType = 1 } - override int getSize() { - result = - this.(FunctionCall).getArgument(2).getValue().toInt() * - getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) + override Expr getSizeExpr() { result = this.(FunctionCall).getArgument(2) } + + override int getSizeMult() { + result = getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) } } @@ -115,10 +131,10 @@ class StrncpyBA extends BufferAccess { accessType = 2 } - override int getSize() { - result = - this.(FunctionCall).getArgument(2).getValue().toInt() * - getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) + override Expr getSizeExpr() { result = this.(FunctionCall).getArgument(2) } + + override int getSizeMult() { + result = getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) } } @@ -141,10 +157,10 @@ class MemccpyBA extends BufferAccess { accessType = 2 } - override int getSize() { - result = - this.(FunctionCall).getArgument(3).getValue().toInt() * - getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) + override Expr getSizeExpr() { result = this.(FunctionCall).getArgument(3) } + + override int getSizeMult() { + result = getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) } } @@ -172,10 +188,10 @@ class MemcmpBA extends BufferAccess { accessType = 2 } - override int getSize() { - result = - this.(FunctionCall).getArgument(2).getValue().toInt() * - getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) + override Expr getSizeExpr() { result = this.(FunctionCall).getArgument(2) } + + override int getSizeMult() { + result = getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) } } @@ -199,10 +215,10 @@ class SwabBA extends BufferAccess { accessType = 1 } - override int getSize() { - result = - this.(FunctionCall).getArgument(2).getValue().toInt() * - getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) + override Expr getSizeExpr() { result = this.(FunctionCall).getArgument(2) } + + override int getSizeMult() { + result = getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) } } @@ -222,10 +238,10 @@ class MemsetBA extends BufferAccess { accessType = 1 } - override int getSize() { - result = - this.(FunctionCall).getArgument(2).getValue().toInt() * - getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) + override Expr getSizeExpr() { result = this.(FunctionCall).getArgument(2) } + + override int getSizeMult() { + result = getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) } } @@ -244,7 +260,9 @@ class ZeroMemoryBA extends BufferAccess { accessType = 1 } - override int getSize() { result = this.(FunctionCall).getArgument(1).getValue().toInt() } + override Expr getSizeExpr() { result = this.(FunctionCall).getArgument(1) } + + override int getSizeMult() { result = 1 } } /** @@ -263,10 +281,10 @@ class MemchrBA extends BufferAccess { accessType = 2 } - override int getSize() { - result = - this.(FunctionCall).getArgument(2).getValue().toInt() * - getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) + override Expr getSizeExpr() { result = this.(FunctionCall).getArgument(2) } + + override int getSizeMult() { + result = getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) } } @@ -285,11 +303,9 @@ class FreadBA extends BufferAccess { accessType = 2 } - override int getSize() { - result = - this.(FunctionCall).getArgument(1).getValue().toInt() * - this.(FunctionCall).getArgument(2).getValue().toInt() - } + override Expr getSizeExpr() { result = this.(FunctionCall).getArgument(1) } + + override int getSizeMult() { result = this.(FunctionCall).getArgument(2).getValue().toInt() } } /** @@ -318,11 +334,13 @@ class ArrayExprBA extends BufferAccess { accessType = 3 } + override Expr getSizeExpr() { result = this.(ArrayExpr).getArrayOffset() } + override int getSize() { // byte size of the buffer that would be required to support this // access - result = - (1 + this.(ArrayExpr).getArrayOffset().getValue().toInt()) * - this.(ArrayExpr).getType().getSize() + result = (1 + this.getSizeExpr().getValue().toInt()) * this.getSizeMult() } + + override int getSizeMult() { result = this.(ArrayExpr).getType().getSize() } } diff --git a/cpp/ql/lib/semmle/code/cpp/security/boostorg/asio/protocols.qll b/cpp/ql/lib/semmle/code/cpp/security/boostorg/asio/protocols.qll index 6a0841e13e2..8668ecf078c 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/boostorg/asio/protocols.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/boostorg/asio/protocols.qll @@ -394,12 +394,12 @@ module BoostorgAsio { * Constructs a standard data flow computation for protocol values to the first argument * of a context constructor. */ - module SslContextCallMake { + module SslContextCallGlobal { private module C implements DataFlow::ConfigSig { import Config } - import DataFlow::Make + import DataFlow::Global } /** @@ -428,7 +428,7 @@ module BoostorgAsio { } } - module SslContextCallFlow = SslContextCallMake; + module SslContextCallFlow = SslContextCallGlobal; /** * A banned protocol value that flows to the first argument of a context constructor. @@ -458,7 +458,8 @@ module BoostorgAsio { } } - module SslContextCallBannedProtocolFlow = SslContextCallMake; + module SslContextCallBannedProtocolFlow = + SslContextCallGlobal; /** * A TLS 1.2 protocol value that flows to the first argument of a context constructor. @@ -488,7 +489,7 @@ module BoostorgAsio { } } - module SslContextCallTls12ProtocolFlow = SslContextCallMake; + module SslContextCallTls12ProtocolFlow = SslContextCallGlobal; /** * A TLS 1.3 protocol value that flows to the first argument of a context constructor. @@ -518,7 +519,7 @@ module BoostorgAsio { } } - module SslContextCallTls13ProtocolFlow = SslContextCallMake; + module SslContextCallTls13ProtocolFlow = SslContextCallGlobal; /** * A generic TLS protocol value that flows to the first argument of a context constructor. @@ -548,7 +549,7 @@ module BoostorgAsio { } } - module SslContextCallTlsProtocolFlow = SslContextCallMake; + module SslContextCallTlsProtocolFlow = SslContextCallGlobal; /** * A context constructor call that flows to a call to `SetOptions()`. @@ -596,7 +597,7 @@ module BoostorgAsio { } } - module SslContextFlowsToSetOptionFlow = DataFlow::Make; + module SslContextFlowsToSetOptionFlow = DataFlow::Global; /** * An option value that flows to the first parameter of a call to `SetOptions()`. @@ -640,5 +641,5 @@ module BoostorgAsio { } } - module SslOptionFlow = DataFlow::Make; + module SslOptionFlow = DataFlow::Global; } diff --git a/cpp/ql/src/Critical/OverflowDestination.ql b/cpp/ql/src/Critical/OverflowDestination.ql index 39ce527e08a..4cfaaf8981b 100644 --- a/cpp/ql/src/Critical/OverflowDestination.ql +++ b/cpp/ql/src/Critical/OverflowDestination.ql @@ -84,11 +84,11 @@ module OverflowDestinationConfig implements DataFlow::ConfigSig { } } -module OverflowDestination = TaintTracking::Make; +module OverflowDestination = TaintTracking::Global; from FunctionCall fc, OverflowDestination::PathNode source, OverflowDestination::PathNode sink where - OverflowDestination::hasFlowPath(source, sink) and + OverflowDestination::flowPath(source, sink) and sourceSized(fc, sink.getNode().asIndirectConvertedExpr()) select fc, source, sink, "To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size." diff --git a/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql b/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql index 03f622855ab..79a5d530c21 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql +++ b/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql @@ -80,9 +80,9 @@ predicate introducesNewField(Class derived, Class base) { ) } -module CastToPointerArithFlow = DataFlow::MakeWithState; +module CastToPointerArithFlow = DataFlow::GlobalWithState; from CastToPointerArithFlow::PathNode source, CastToPointerArithFlow::PathNode sink -where CastToPointerArithFlow::hasFlowPath(source, sink) +where CastToPointerArithFlow::flowPath(source, sink) select sink, source, sink, "This pointer arithmetic may be done with the wrong type because of $@.", source, "this cast" diff --git a/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql b/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql index 2b2e9f6bf8b..65454332ab1 100644 --- a/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql +++ b/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql @@ -146,13 +146,13 @@ module NonConstFlowConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node node) { isBarrierNode(node) } } -module NonConstFlow = TaintTracking::Make; +module NonConstFlow = TaintTracking::Global; from FormattingFunctionCall call, Expr formatString where call.getArgument(call.getFormatParameterIndex()) = formatString and exists(DataFlow::Node sink | - NonConstFlow::hasFlowTo(sink) and + NonConstFlow::flowTo(sink) and isSinkImpl(sink, formatString) ) select formatString, diff --git a/cpp/ql/src/Likely Bugs/Leap Year/Adding365DaysPerYear.ql b/cpp/ql/src/Likely Bugs/Leap Year/Adding365DaysPerYear.ql index fe6581340de..71aa97c0ae5 100644 --- a/cpp/ql/src/Likely Bugs/Leap Year/Adding365DaysPerYear.ql +++ b/cpp/ql/src/Likely Bugs/Leap Year/Adding365DaysPerYear.ql @@ -16,7 +16,7 @@ import LeapYear from Expr source, Expr sink where - PossibleYearArithmeticOperationCheckFlow::hasFlow(DataFlow::exprNode(source), + PossibleYearArithmeticOperationCheckFlow::flow(DataFlow::exprNode(source), DataFlow::exprNode(sink)) select sink, "An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios.", diff --git a/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll b/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll index a838f4c6a0d..7a375e7b107 100644 --- a/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll +++ b/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll @@ -231,7 +231,7 @@ private module LeapYearCheckConfig implements DataFlow::ConfigSig { } } -module LeapYearCheckFlow = DataFlow::Make; +module LeapYearCheckFlow = DataFlow::Global; /** * Data flow configuration for finding an operation with hardcoded 365 that will flow into @@ -284,7 +284,7 @@ private module FiletimeYearArithmeticOperationCheckConfig implements DataFlow::C } module FiletimeYearArithmeticOperationCheckFlow = - DataFlow::Make; + DataFlow::Global; /** * Taint configuration for finding an operation with hardcoded 365 that will flow into any known date/time field. @@ -372,4 +372,4 @@ private module PossibleYearArithmeticOperationCheckConfig implements DataFlow::C } module PossibleYearArithmeticOperationCheckFlow = - TaintTracking::Make; + TaintTracking::Global; diff --git a/cpp/ql/src/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification.ql b/cpp/ql/src/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification.ql index f85270d523e..03570b3611c 100644 --- a/cpp/ql/src/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification.ql +++ b/cpp/ql/src/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification.ql @@ -31,16 +31,14 @@ where // If there is a data flow from the variable that was modified to a function that seems to check for leap year exists(VariableAccess source, ChecksForLeapYearFunctionCall fc | source = var.getAnAccess() and - LeapYearCheckFlow::hasFlow(DataFlow::exprNode(source), - DataFlow::exprNode(fc.getAnArgument())) + LeapYearCheckFlow::flow(DataFlow::exprNode(source), DataFlow::exprNode(fc.getAnArgument())) ) or // If there is a data flow from the field that was modified to a function that seems to check for leap year exists(VariableAccess vacheck, YearFieldAccess yfacheck, ChecksForLeapYearFunctionCall fc | vacheck = var.getAnAccess() and yfacheck.getQualifier() = vacheck and - LeapYearCheckFlow::hasFlow(DataFlow::exprNode(yfacheck), - DataFlow::exprNode(fc.getAnArgument())) + LeapYearCheckFlow::flow(DataFlow::exprNode(yfacheck), DataFlow::exprNode(fc.getAnArgument())) ) or // If there is a successor or predecessor that sets the month = 1 diff --git a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.ql b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.ql index c23eda355c4..38ecd4183ff 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.ql @@ -12,5 +12,5 @@ import cpp import NtohlArrayNoBound from DataFlow::Node source, DataFlow::Node sink -where NetworkToBufferSizeFlow::hasFlow(source, sink) +where NetworkToBufferSizeFlow::flow(source, sink) select sink, "Unchecked use of data from network function $@.", source, source.toString() diff --git a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll index e3b095d74dd..1bd90084c67 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll +++ b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll @@ -161,4 +161,4 @@ private module NetworkToBufferSizeConfig implements DataFlow::ConfigSig { } } -module NetworkToBufferSizeFlow = DataFlow::Make; +module NetworkToBufferSizeFlow = DataFlow::Global; diff --git a/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql b/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql index e7baf96615e..61989db1c6e 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql @@ -25,17 +25,17 @@ module ExistsAnyFlowConfig implements DataFlow::ConfigSig { } } -module ExistsAnyFlow = DataFlow::Make; +module ExistsAnyFlow = DataFlow::Global; bindingset[flag] predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) { exists(VariableAccess contextSetOptions | - ExistsAnyFlow::hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and + ExistsAnyFlow::flow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions | contextSetOptions = fcSetOptions.getQualifier() and forall(Expr optionArgument, Expr optionArgumentSource | optionArgument = fcSetOptions.getArgument(0) and - BoostorgAsio::SslOptionFlow::hasFlow(DataFlow::exprNode(optionArgumentSource), + BoostorgAsio::SslOptionFlow::flow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument)) | optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag @@ -49,7 +49,7 @@ predicate isOptionNotSet(ConstructorCall cc, int flag) { not isOptionSet(cc, fla from Expr protocolSource, Expr protocolSink, ConstructorCall cc, Expr e, string msg where - BoostorgAsio::SslContextCallTlsProtocolFlow::hasFlow(DataFlow::exprNode(protocolSource), + BoostorgAsio::SslContextCallTlsProtocolFlow::flow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and cc.getArgument(0) = protocolSink and ( diff --git a/cpp/ql/src/Likely Bugs/Protocols/UseOfDeprecatedHardcodedProtocol.ql b/cpp/ql/src/Likely Bugs/Protocols/UseOfDeprecatedHardcodedProtocol.ql index 140cf8e2ccf..4df70695179 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/UseOfDeprecatedHardcodedProtocol.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/UseOfDeprecatedHardcodedProtocol.ql @@ -14,12 +14,12 @@ import semmle.code.cpp.security.boostorg.asio.protocols from Expr protocolSource, Expr protocolSink, ConstructorCall cc where - BoostorgAsio::SslContextCallFlow::hasFlow(DataFlow::exprNode(protocolSource), + BoostorgAsio::SslContextCallFlow::flow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and - not BoostorgAsio::SslContextCallTlsProtocolFlow::hasFlow(DataFlow::exprNode(protocolSource), + not BoostorgAsio::SslContextCallTlsProtocolFlow::flow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and cc.getArgument(0) = protocolSink and - BoostorgAsio::SslContextCallBannedProtocolFlow::hasFlow(DataFlow::exprNode(protocolSource), + BoostorgAsio::SslContextCallBannedProtocolFlow::flow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) select protocolSink, "Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@.", cc, "boost::asio::ssl::context::context", protocolSource, protocolSource.toString(), diff --git a/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll b/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll index 6d6f17daf0e..70247bdf4a4 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll +++ b/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll @@ -10,10 +10,10 @@ import ExternalAPIsSpecific /** A node representing untrusted data being passed to an external API. */ class UntrustedExternalApiDataNode extends ExternalApiDataNode { - UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::hasFlow(_, this) } + UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::flow(_, this) } /** Gets a source of untrusted data which is passed to this external API data node. */ - DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::hasFlow(result, this) } + DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::flow(result, this) } } /** DEPRECATED: Alias for UntrustedExternalApiDataNode */ diff --git a/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll b/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll index d2ab4f0309f..2505f718bc6 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll +++ b/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll @@ -73,4 +73,4 @@ private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } } -module UntrustedDataToExternalApiFlow = TaintTracking::Make; +module UntrustedDataToExternalApiFlow = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql b/cpp/ql/src/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql index d16ce6376dd..432f47f6735 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql +++ b/cpp/ql/src/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql @@ -16,7 +16,7 @@ import semmle.code.cpp.security.FlowSources import UntrustedDataToExternalApiFlow::PathGraph from UntrustedDataToExternalApiFlow::PathNode source, UntrustedDataToExternalApiFlow::PathNode sink -where UntrustedDataToExternalApiFlow::hasFlowPath(source, sink) +where UntrustedDataToExternalApiFlow::flowPath(source, sink) select sink, source, sink, "Call to " + sink.getNode().(ExternalApiDataNode).getExternalFunction().toString() + " with untrusted data from $@.", source, source.getNode().(RemoteFlowSource).getSourceType() diff --git a/cpp/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql b/cpp/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql index a00accd4d29..1cfd0a7132f 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql +++ b/cpp/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql @@ -15,7 +15,7 @@ import ExternalAPIs import UntrustedDataToExternalApiFlow::PathGraph from UntrustedDataToExternalApiFlow::PathNode source, UntrustedDataToExternalApiFlow::PathNode sink -where UntrustedDataToExternalApiFlow::hasFlowPath(source, sink) +where UntrustedDataToExternalApiFlow::flowPath(source, sink) select sink, source, sink, "Call to " + sink.getNode().(ExternalApiDataNode).getExternalFunction().toString() + " with untrusted data from $@.", source, source.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIs.qll b/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIs.qll index 6d6f17daf0e..70247bdf4a4 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIs.qll +++ b/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIs.qll @@ -10,10 +10,10 @@ import ExternalAPIsSpecific /** A node representing untrusted data being passed to an external API. */ class UntrustedExternalApiDataNode extends ExternalApiDataNode { - UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::hasFlow(_, this) } + UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::flow(_, this) } /** Gets a source of untrusted data which is passed to this external API data node. */ - DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::hasFlow(result, this) } + DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::flow(result, this) } } /** DEPRECATED: Alias for UntrustedExternalApiDataNode */ diff --git a/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll b/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll index 4dd077f24ce..93da5497a22 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll +++ b/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll @@ -63,4 +63,4 @@ private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } } -module UntrustedDataToExternalApiFlow = TaintTracking::Make; +module UntrustedDataToExternalApiFlow = TaintTracking::Global; diff --git a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql index 89d8f975680..4e626d0bc77 100644 --- a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql +++ b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql @@ -90,7 +90,7 @@ module TaintedPathConfig implements DataFlow::ConfigSig { } } -module TaintedPath = TaintTracking::Make; +module TaintedPath = TaintTracking::Global; from FileFunction fileFunction, Expr taintedArg, FlowSource taintSource, @@ -98,7 +98,7 @@ from where taintedArg = sinkNode.getNode().asIndirectArgument() and fileFunction.outermostWrapperFunctionCall(taintedArg, callChain) and - TaintedPath::hasFlowPath(sourceNode, sinkNode) and + TaintedPath::flowPath(sourceNode, sinkNode) and taintSource = sourceNode.getNode() select taintedArg, sourceNode, sinkNode, "This argument to a file access function is derived from $@ and then passed to " + callChain + ".", diff --git a/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql b/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql index c7e01e0b983..cc4b748e5dc 100644 --- a/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql @@ -76,7 +76,7 @@ class ExecState extends TExecState { DataFlow::Node getOutgoingNode() { result = outgoing } /** Holds if this is a possible `ExecState` for `sink`. */ - predicate isFeasibleForSink(DataFlow::Node sink) { ExecState::hasFlow(outgoing, sink) } + predicate isFeasibleForSink(DataFlow::Node sink) { ExecState::flow(outgoing, sink) } string toString() { result = "ExecState" } } @@ -109,7 +109,7 @@ module ExecStateConfig implements DataFlow::ConfigSig { } } -module ExecState = TaintTracking::Make; +module ExecState = TaintTracking::Global; module ExecTaintConfig implements DataFlow::StateConfigSig { class FlowState = TState; @@ -141,13 +141,13 @@ module ExecTaintConfig implements DataFlow::StateConfigSig { } } -module ExecTaint = TaintTracking::MakeWithState; +module ExecTaint = TaintTracking::GlobalWithState; from ExecTaint::PathNode sourceNode, ExecTaint::PathNode sinkNode, string taintCause, string callChain, DataFlow::Node concatResult, Expr command where - ExecTaint::hasFlowPath(sourceNode, sinkNode) and + ExecTaint::flowPath(sourceNode, sinkNode) and taintCause = sourceNode.getNode().(FlowSource).getSourceType() and isSinkImpl(sinkNode.getNode(), command, callChain) and concatResult = sinkNode.getState().(ExecState).getOutgoingNode() diff --git a/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql b/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql index 598e242b0ef..107be7bddfd 100644 --- a/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql +++ b/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql @@ -114,13 +114,13 @@ module ImproperArrayIndexValidationConfig implements DataFlow::ConfigSig { } } -module ImproperArrayIndexValidation = TaintTracking::Make; +module ImproperArrayIndexValidation = TaintTracking::Global; from ImproperArrayIndexValidation::PathNode source, ImproperArrayIndexValidation::PathNode sink, string sourceType where - ImproperArrayIndexValidation::hasFlowPath(source, sink) and + ImproperArrayIndexValidation::flowPath(source, sink) and isFlowSource(source.getNode(), sourceType) select sink.getNode(), source, sink, "An array indexing expression depends on $@ that might be outside the bounds of the array.", diff --git a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql index a4d37eb4875..54c3b013471 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql @@ -122,7 +122,7 @@ module UncontrolledArithConfig implements DataFlow::ConfigSig { } } -module UncontrolledArith = TaintTracking::Make; +module UncontrolledArith = TaintTracking::Global; /** Gets the expression that corresponds to `node`, if any. */ Expr getExpr(DataFlow::Node node) { result = [node.asExpr(), node.asDefiningArgument()] } @@ -131,7 +131,7 @@ from UncontrolledArith::PathNode source, UncontrolledArith::PathNode sink, VariableAccess va, string effect where - UncontrolledArith::hasFlowPath(source, sink) and + UncontrolledArith::flowPath(source, sink) and sink.getNode().asExpr() = va and missingGuard(va, effect) select sink.getNode(), source, sink, diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql index 4d242890528..740e4ad9e8e 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql @@ -95,14 +95,14 @@ module TaintedAllocationSizeConfig implements DataFlow::ConfigSig { } } -module TaintedAllocationSize = TaintTracking::Make; +module TaintedAllocationSize = TaintTracking::Global; from Expr alloc, TaintedAllocationSize::PathNode source, TaintedAllocationSize::PathNode sink, string taintCause where isFlowSource(source.getNode(), taintCause) and - TaintedAllocationSize::hasFlowPath(source, sink) and + TaintedAllocationSize::flowPath(source, sink) and allocSink(alloc, sink.getNode()) select alloc, source, sink, "This allocation size is derived from $@ and might overflow.", source.getNode(), "user input (" + taintCause + ")" diff --git a/cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql b/cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql index 34d211a53ae..5eab70c5cc9 100644 --- a/cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql +++ b/cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql @@ -33,14 +33,14 @@ module VerifyResultConfig implements DataFlow::ConfigSig { } } -module VerifyResult = DataFlow::Make; +module VerifyResult = DataFlow::Global; from DataFlow::Node source, DataFlow::Node sink1, DataFlow::Node sink2, GuardCondition guard, Expr c1, Expr c2, boolean testIsTrue where - VerifyResult::hasFlow(source, sink1) and - VerifyResult::hasFlow(source, sink2) and + VerifyResult::flow(source, sink1) and + VerifyResult::flow(source, sink2) and guard.comparesEq(sink1.asExpr(), c1, 0, false, testIsTrue) and // (value != c1) => testIsTrue guard.comparesEq(sink2.asExpr(), c2, 0, false, testIsTrue) and // (value != c2) => testIsTrue c1.getValue().toInt() = 0 and diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql index d7bb69582d7..f2754c5811f 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql @@ -49,7 +49,7 @@ module ToBufferConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) } } -module ToBufferFlow = TaintTracking::Make; +module ToBufferFlow = TaintTracking::Global; predicate isSinkImpl(DataFlow::Node sink, SensitiveBufferWrite w) { w.getASource() = sink.asIndirectExpr() @@ -59,7 +59,7 @@ from SensitiveBufferWrite w, ToBufferFlow::PathNode sourceNode, ToBufferFlow::PathNode sinkNode, FlowSource source where - ToBufferFlow::hasFlowPath(sourceNode, sinkNode) and + ToBufferFlow::flowPath(sourceNode, sinkNode) and sourceNode.getNode() = source and isSinkImpl(sinkNode.getNode(), w) select w, sourceNode, sinkNode, diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql index 3c1a78b14c5..c04ceae7ada 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql @@ -33,7 +33,7 @@ module FromSensitiveConfig implements DataFlow::ConfigSig { } } -module FromSensitiveFlow = TaintTracking::Make; +module FromSensitiveFlow = TaintTracking::Global; predicate isSinkImpl(DataFlow::Node sink, FileWrite w, Expr dest) { exists(Expr e | @@ -81,7 +81,7 @@ from SensitiveExpr source, FromSensitiveFlow::PathNode sourceNode, FromSensitiveFlow::PathNode midNode, FileWrite w, Expr dest where - FromSensitiveFlow::hasFlowPath(sourceNode, midNode) and + FromSensitiveFlow::flowPath(sourceNode, midNode) and isSourceImpl(sourceNode.getNode(), source) and isSinkImpl(midNode.getNode(), w, dest) select w, sourceNode, midNode, diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql index a0fb6bd2dac..fa0d2ffd82a 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -250,13 +250,13 @@ module FromSensitiveConfig implements DataFlow::ConfigSig { } } -module FromSensitiveFlow = TaintTracking::Make; +module FromSensitiveFlow = TaintTracking::Global; /** * A taint flow configuration for flow from a sensitive expression to an encryption operation. */ module ToEncryptionConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { FromSensitiveFlow::hasFlow(source, _) } + predicate isSource(DataFlow::Node source) { FromSensitiveFlow::flow(source, _) } predicate isSink(DataFlow::Node sink) { isSinkEncrypt(sink, _) } @@ -271,7 +271,7 @@ module ToEncryptionConfig implements DataFlow::ConfigSig { } } -module ToEncryptionFlow = TaintTracking::Make; +module ToEncryptionFlow = TaintTracking::Global; /** * A taint flow configuration for flow from an encryption operation to a network operation. @@ -279,25 +279,25 @@ module ToEncryptionFlow = TaintTracking::Make; module FromEncryptionConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { isSinkEncrypt(source, _) } - predicate isSink(DataFlow::Node sink) { FromSensitiveFlow::hasFlowTo(sink) } + predicate isSink(DataFlow::Node sink) { FromSensitiveFlow::flowTo(sink) } predicate isBarrier(DataFlow::Node node) { node.asExpr().getUnspecifiedType() instanceof IntegralType } } -module FromEncryptionFlow = TaintTracking::Make; +module FromEncryptionFlow = TaintTracking::Global; from FromSensitiveFlow::PathNode source, FromSensitiveFlow::PathNode sink, NetworkSendRecv networkSendRecv, string msg where // flow from sensitive -> network data - FromSensitiveFlow::hasFlowPath(source, sink) and + FromSensitiveFlow::flowPath(source, sink) and isSinkSendRecv(sink.getNode(), networkSendRecv) and // no flow from sensitive -> evidence of encryption - not ToEncryptionFlow::hasFlow(source.getNode(), _) and - not FromEncryptionFlow::hasFlowTo(sink.getNode()) and + not ToEncryptionFlow::flow(source.getNode(), _) and + not FromEncryptionFlow::flowTo(sink.getNode()) and // construct result if networkSendRecv instanceof NetworkSend then diff --git a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql index 797302be5a4..0c060befeff 100644 --- a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql +++ b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql @@ -125,13 +125,13 @@ module FromSensitiveConfig implements DataFlow::ConfigSig { } } -module FromSensitiveFlow = TaintTracking::Make; +module FromSensitiveFlow = TaintTracking::Global; from SensitiveExpr sensitive, FromSensitiveFlow::PathNode source, FromSensitiveFlow::PathNode sink, SqliteFunctionCall sqliteCall where - FromSensitiveFlow::hasFlowPath(source, sink) and + FromSensitiveFlow::flowPath(source, sink) and isSourceImpl(source.getNode(), sensitive) and isSinkImpl(sink.getNode(), sqliteCall, _) select sqliteCall, source, sink, diff --git a/cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql b/cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql index ceddfbf9f40..423ed57dd98 100644 --- a/cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql +++ b/cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql @@ -89,10 +89,10 @@ module HttpStringToUrlOpenConfig implements DataFlow::ConfigSig { } } -module HttpStringToUrlOpen = TaintTracking::Make; +module HttpStringToUrlOpen = TaintTracking::Global; from HttpStringToUrlOpen::PathNode source, HttpStringToUrlOpen::PathNode sink, HttpStringLiteral str where - HttpStringToUrlOpen::hasFlowPath(source, sink) and + HttpStringToUrlOpen::flowPath(source, sink) and str = source.getNode().asIndirectExpr() select str, source, sink, "This URL may be constructed with the HTTP protocol." diff --git a/cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql b/cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql index f899889a59b..3cc10b7ad19 100644 --- a/cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql +++ b/cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql @@ -46,13 +46,13 @@ module KeyStrengthFlowConfig implements DataFlow::ConfigSig { } } -module KeyStrengthFlow = DataFlow::Make; +module KeyStrengthFlow = DataFlow::Global; from KeyStrengthFlow::PathNode source, KeyStrengthFlow::PathNode sink, FunctionCall fc, int param, string name, int minimumBits, int bits where - KeyStrengthFlow::hasFlowPath(source, sink) and + KeyStrengthFlow::flowPath(source, sink) and sink.getNode().asExpr() = fc.getArgument(param) and fc.getTarget().hasGlobalName(name) and minimumBits = getMinimumKeyStrength(name, param) and diff --git a/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql b/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql index e6dd4e7046e..2703f819b54 100644 --- a/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql +++ b/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql @@ -64,7 +64,7 @@ module NullAppNameCreateProcessFunctionConfig implements DataFlow::ConfigSig { } } -module NullAppNameCreateProcessFunction = DataFlow::Make; +module NullAppNameCreateProcessFunction = DataFlow::Global; /** * Dataflow that detects a call to CreateProcess with an unquoted commandLine argument @@ -85,7 +85,7 @@ module QuotedCommandInCreateProcessFunctionConfig implements DataFlow::ConfigSig } module QuotedCommandInCreateProcessFunction = - DataFlow::Make; + DataFlow::Global; bindingset[s] predicate isQuotedOrNoSpaceApplicationNameOnCmd(string s) { @@ -98,12 +98,12 @@ from CreateProcessFunctionCall call, string msg1, string msg2 where exists(Expr appName | appName = call.getArgument(call.getApplicationNameArgumentId()) and - NullAppNameCreateProcessFunction::hasFlowToExpr(appName) and + NullAppNameCreateProcessFunction::flowToExpr(appName) and msg1 = call.toString() + " with lpApplicationName == NULL (" + appName + ")" ) and exists(Expr cmd | cmd = call.getArgument(call.getCommandLineArgumentId()) and - QuotedCommandInCreateProcessFunction::hasFlowToExpr(cmd) and + QuotedCommandInCreateProcessFunction::flowToExpr(cmd) and msg2 = " and with an unquoted lpCommandLine (" + cmd + ") introduces a security vulnerability if the path contains spaces." diff --git a/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql b/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql index 7e76cf76c12..74a5e1ba4e0 100644 --- a/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql +++ b/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql @@ -30,15 +30,15 @@ module ExposedSystemDataConfig implements DataFlow::ConfigSig { } } -module ExposedSystemData = TaintTracking::Make; +module ExposedSystemData = TaintTracking::Global; from ExposedSystemData::PathNode source, ExposedSystemData::PathNode sink where - ExposedSystemData::hasFlowPath(source, sink) and + ExposedSystemData::flowPath(source, sink) and not exists( DataFlow::Node alt // remove duplicate results on conversions | - ExposedSystemData::hasFlow(source.getNode(), alt) and + ExposedSystemData::flow(source.getNode(), alt) and alt.asConvertedExpr() = sink.getNode().asIndirectExpr() and alt != sink.getNode() ) diff --git a/cpp/ql/src/Security/CWE/CWE-497/PotentiallyExposedSystemData.ql b/cpp/ql/src/Security/CWE/CWE-497/PotentiallyExposedSystemData.ql index a06314e3c97..9fa4f538378 100644 --- a/cpp/ql/src/Security/CWE/CWE-497/PotentiallyExposedSystemData.ql +++ b/cpp/ql/src/Security/CWE/CWE-497/PotentiallyExposedSystemData.ql @@ -51,9 +51,9 @@ module PotentiallyExposedSystemDataConfig implements DataFlow::ConfigSig { } } -module PotentiallyExposedSystemData = TaintTracking::Make; +module PotentiallyExposedSystemData = TaintTracking::Global; from PotentiallyExposedSystemData::PathNode source, PotentiallyExposedSystemData::PathNode sink -where PotentiallyExposedSystemData::hasFlowPath(source, sink) +where PotentiallyExposedSystemData::flowPath(source, sink) select sink, source, sink, "This operation potentially exposes sensitive system data from $@.", source, source.getNode().toString() diff --git a/cpp/ql/src/Security/CWE/CWE-611/XXE.ql b/cpp/ql/src/Security/CWE/CWE-611/XXE.ql index 1b611a42b8d..6b73e50c963 100644 --- a/cpp/ql/src/Security/CWE/CWE-611/XXE.ql +++ b/cpp/ql/src/Security/CWE/CWE-611/XXE.ql @@ -45,9 +45,9 @@ module XxeConfig implements DataFlow::StateConfigSig { } } -module XxeFlow = DataFlow::MakeWithState; +module XxeFlow = DataFlow::GlobalWithState; from XxeFlow::PathNode source, XxeFlow::PathNode sink -where XxeFlow::hasFlowPath(source, sink) +where XxeFlow::flowPath(source, sink) select sink, source, sink, "This $@ is not configured to prevent an XML external entity (XXE) attack.", source, "XML parser" diff --git a/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql b/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql index 8f36ab50aa8..5ed30e19bb3 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql +++ b/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql @@ -39,7 +39,7 @@ module NullDaclConfig implements DataFlow::ConfigSig { } } -module NullDaclFlow = DataFlow::Make; +module NullDaclFlow = DataFlow::Global; /** * Dataflow that detects a call to SetSecurityDescriptorDacl with a pDacl @@ -70,7 +70,7 @@ module NonNullDaclConfig implements DataFlow::ConfigSig { } } -module NonNullDaclFlow = DataFlow::Make; +module NonNullDaclFlow = DataFlow::Global; from SetSecurityDescriptorDaclFunctionCall call, string message where @@ -88,7 +88,7 @@ where " that is set to NULL will result in an unprotected object." | var = call.getArgument(2) and - NullDaclFlow::hasFlowToExpr(var) and - not NonNullDaclFlow::hasFlowToExpr(var) + NullDaclFlow::flowToExpr(var) and + not NonNullDaclFlow::flowToExpr(var) ) select call, message diff --git a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql index 5e0d1d7b5bb..5f6bf7d7166 100644 --- a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql +++ b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql @@ -24,7 +24,7 @@ import DataFlow::PathGraph pragma[nomagic] Instruction getABoundIn(SemBound b, IRFunction func) { - result = b.getExpr(0) and + getSemanticExpr(result) = b.getExpr(0) and result.getEnclosingIRFunction() = func } @@ -62,11 +62,16 @@ predicate hasSize(AllocationExpr alloc, DataFlow::Node n, string state) { predicate isSinkPairImpl( CallInstruction c, DataFlow::Node bufSink, DataFlow::Node sizeSink, int delta, Expr eBuf ) { - exists(int bufIndex, int sizeIndex, Instruction sizeInstr, Instruction bufInstr | + exists( + int bufIndex, int sizeIndex, Instruction sizeInstr, Instruction bufInstr, ArrayFunction func + | bufInstr = bufSink.asInstruction() and c.getArgument(bufIndex) = bufInstr and sizeInstr = sizeSink.asInstruction() and - c.getStaticCallTarget().(ArrayFunction).hasArrayWithVariableSize(bufIndex, sizeIndex) and + c.getStaticCallTarget() = func and + pragma[only_bind_into](func) + .hasArrayWithVariableSize(pragma[only_bind_into](bufIndex), + pragma[only_bind_into](sizeIndex)) and bounded(c.getArgument(sizeIndex), sizeInstr, delta) and eBuf = bufInstr.getUnconvertedResultExpression() ) @@ -110,7 +115,7 @@ class StringSizeConfiguration extends ProductFlow::Configuration { state1 = s1.toString() and state2 = s2.toString() and add.hasOperands(node1.asOperand(), op) and - semBounded(op.getDef(), any(SemZeroBound zero), delta, true, _) and + semBounded(getSemanticExpr(op.getDef()), any(SemZeroBound zero), delta, true, _) and node2.asInstruction() = add and s1 = s2 + delta ) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-078/WordexpTainted.ql b/cpp/ql/src/experimental/Security/CWE/CWE-078/WordexpTainted.ql index 7b72b2684e6..cf346cb812e 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-078/WordexpTainted.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-078/WordexpTainted.ql @@ -50,9 +50,9 @@ module WordexpTaintConfig implements DataFlow::ConfigSig { } } -module WordexpTaint = TaintTracking::Make; +module WordexpTaint = TaintTracking::Global; from WordexpTaint::PathNode sourceNode, WordexpTaint::PathNode sinkNode -where WordexpTaint::hasFlowPath(sourceNode, sinkNode) +where WordexpTaint::flowPath(sourceNode, sinkNode) select sinkNode.getNode(), sourceNode, sinkNode, "Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection." diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql b/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql index 71958eaad91..00cf017297f 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql @@ -32,10 +32,10 @@ module MultToAllocConfig implements DataFlow::ConfigSig { } } -module MultToAlloc = DataFlow::Make; +module MultToAlloc = DataFlow::Global; from MultToAlloc::PathNode source, MultToAlloc::PathNode sink -where MultToAlloc::hasFlowPath(source, sink) +where MultToAlloc::flowPath(source, sink) select sink, source, sink, "Potentially overflowing value from $@ is used in the size of this allocation.", source, "multiplication" diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql b/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql index 35cce4a30da..66346b7aea7 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql @@ -19,7 +19,7 @@ import PointerArithmeticToDerefFlow::PathGraph pragma[nomagic] Instruction getABoundIn(SemBound b, IRFunction func) { - result = b.getExpr(0) and + getSemanticExpr(result) = b.getExpr(0) and result.getEnclosingIRFunction() = func } @@ -43,7 +43,8 @@ module FieldAddressToPointerArithmeticConfig implements DataFlow::ConfigSig { } } -module FieldAddressToPointerArithmeticFlow = DataFlow::Make; +module FieldAddressToPointerArithmeticFlow = + DataFlow::Global; predicate isFieldAddressSource(Field f, DataFlow::Node source) { source.asInstruction().(FieldAddressInstruction).getField() = f @@ -70,7 +71,7 @@ predicate isInvalidPointerDerefSink(DataFlow::Node sink, Instruction i, string o predicate isConstantSizeOverflowSource(Field f, PointerAddInstruction pai, int delta) { exists(int size, int bound, DataFlow::Node source, DataFlow::InstructionNode sink | - FieldAddressToPointerArithmeticFlow::hasFlow(source, sink) and + FieldAddressToPointerArithmeticFlow::flow(source, sink) and isFieldAddressSource(f, source) and pai.getLeft() = sink.asInstruction() and f.getUnspecifiedType().(ArrayType).getArraySize() = size and @@ -90,13 +91,13 @@ module PointerArithmeticToDerefConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _) } } -module PointerArithmeticToDerefFlow = DataFlow::Make; +module PointerArithmeticToDerefFlow = DataFlow::Global; from Field f, PointerArithmeticToDerefFlow::PathNode source, PointerArithmeticToDerefFlow::PathNode sink, Instruction deref, string operation, int delta where - PointerArithmeticToDerefFlow::hasFlowPath(source, sink) and + PointerArithmeticToDerefFlow::flowPath(source, sink) and isInvalidPointerDerefSink(sink.getNode(), deref, operation) and isConstantSizeOverflowSource(f, source.getNode().asInstruction(), delta) select source, source, sink, diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql index 9cadcb505d0..4f1fdb5d08a 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql @@ -24,7 +24,7 @@ import semmle.code.cpp.ir.IR pragma[nomagic] Instruction getABoundIn(SemBound b, IRFunction func) { - result = b.getExpr(0) and + getSemanticExpr(result) = b.getExpr(0) and result.getEnclosingIRFunction() = func } @@ -209,7 +209,7 @@ module InvalidPointerToDerefConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _) } } -module InvalidPointerToDerefFlow = DataFlow::Make; +module InvalidPointerToDerefFlow = DataFlow::Global; /** * Holds if `pai` is a pointer-arithmetic operation and `source` is a dataflow node with a @@ -241,7 +241,7 @@ newtype TMergedPathNode = // pointer, but we want to raise an alert at the dereference. TPathNodeSink(Instruction i) { exists(DataFlow::Node n | - InvalidPointerToDerefFlow::hasFlow(_, n) and + InvalidPointerToDerefFlow::flow(_, n) and isInvalidPointerDerefSink(n, i, _) ) } @@ -349,7 +349,7 @@ predicate hasFlowPath( | conf1.hasFlowPath(source1.asPathNode1(), _, sink1, _) and joinOn1(pai, sink1, source3) and - InvalidPointerToDerefFlow::hasFlowPath(source3, sink3) and + InvalidPointerToDerefFlow::flowPath(source3, sink3) and joinOn2(sink3, sink.asSinkNode(), operation) ) } diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql b/cpp/ql/src/experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql index c09277f38f2..2355c276b60 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql @@ -16,7 +16,7 @@ import experimental.semmle.code.cpp.security.PrivateCleartextWrite::PrivateClear import WriteFlow::PathGraph from WriteFlow::PathNode source, WriteFlow::PathNode sink -where WriteFlow::hasFlowPath(source, sink) +where WriteFlow::flowPath(source, sink) select sink.getNode(), source, sink, "This write into the external location '" + sink.getNode() + "' may contain unencrypted data from $@.", source, "this source of private data." diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise2.ql b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise2.ql index 3fbc4fc10fd..a27e6382916 100644 --- a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise2.ql +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise2.ql @@ -12,11 +12,11 @@ module LiteralToGethostbynameConfig implements DataFlow::ConfigSig { } } -module LiteralToGethostbynameFlow = DataFlow::Make; +module LiteralToGethostbynameFlow = DataFlow::Global; from StringLiteral sl, FunctionCall fc, DataFlow::Node source, DataFlow::Node sink where source.asIndirectExpr(1) = sl and sink.asIndirectExpr(1) = fc.getArgument(0) and - LiteralToGethostbynameFlow::hasFlow(source, sink) + LiteralToGethostbynameFlow::flow(source, sink) select sl, fc diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise4.ql b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise4.ql index fc73440cd7b..09d580234fb 100644 --- a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise4.ql +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise4.ql @@ -16,11 +16,11 @@ module GetenvToGethostbynameConfig implements DataFlow::ConfigSig { } } -module GetenvToGethostbynameFlow = DataFlow::Make; +module GetenvToGethostbynameFlow = DataFlow::Global; from Expr getenv, FunctionCall fc, DataFlow::Node source, DataFlow::Node sink where source.asIndirectExpr(1) = getenv and sink.asIndirectExpr(1) = fc.getArgument(0) and - GetenvToGethostbynameFlow::hasFlow(source, sink) + GetenvToGethostbynameFlow::flow(source, sink) select getenv, fc diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-getenv.ql b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-getenv.ql index 7d810156e7d..917193b2994 100644 --- a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-getenv.ql +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-getenv.ql @@ -17,11 +17,11 @@ module EnvironmentToFileConfig implements DataFlow::ConfigSig { } } -module EnvironmentToFileFlow = DataFlow::Make; +module EnvironmentToFileFlow = DataFlow::Global; from Expr getenv, Expr fopen, DataFlow::Node source, DataFlow::Node sink where source.asIndirectExpr(1) = getenv and sink.asIndirectExpr(1) = fopen and - EnvironmentToFileFlow::hasFlow(source, sink) + EnvironmentToFileFlow::flow(source, sink) select fopen, "This 'fopen' uses data from $@.", getenv, "call to 'getenv'" diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/index-flow-from-ntohl.ql b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/index-flow-from-ntohl.ql index a81c3a71d75..15cc379131a 100644 --- a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/index-flow-from-ntohl.ql +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/index-flow-from-ntohl.ql @@ -30,9 +30,9 @@ module NetworkToBufferSizeConfig implements DataFlow::ConfigSig { } } -module NetworkToBufferSizeFlow = TaintTracking::Make; +module NetworkToBufferSizeFlow = TaintTracking::Global; from DataFlow::Node ntohl, DataFlow::Node offset -where NetworkToBufferSizeFlow::hasFlow(ntohl, offset) +where NetworkToBufferSizeFlow::flow(ntohl, offset) select offset, "This array offset may be influenced by $@.", ntohl, "converted data from the network" diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/StrlenLiteralRange.expected b/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/StrlenLiteralRange.expected new file mode 100644 index 00000000000..f714ac312ea --- /dev/null +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/StrlenLiteralRange.expected @@ -0,0 +1,2 @@ +| test.cpp:4:3:4:8 | call to strlen | 7.0 | 7.0 | +| test.cpp:5:3:5:8 | call to strlen | 1.8446744073709552E19 | 0.0 | diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/StrlenLiteralRange.ql b/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/StrlenLiteralRange.ql new file mode 100644 index 00000000000..c77b2078610 --- /dev/null +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/StrlenLiteralRange.ql @@ -0,0 +1,6 @@ +import cpp +import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis +import experimental.semmle.code.cpp.rangeanalysis.extensions.StrlenLiteralRangeExpr + +from FunctionCall fc +select fc, upperBound(fc), lowerBound(fc) diff --git a/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/test.cpp b/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/test.cpp new file mode 100644 index 00000000000..02626c00f8f --- /dev/null +++ b/cpp/ql/test/experimental/library-tests/rangeanalysis/strlenliteral/test.cpp @@ -0,0 +1,6 @@ +unsigned long strlen(const char *); + +void func(const char *s) { + strlen("literal"); + strlen(s); +} diff --git a/cpp/ql/test/library-tests/CPP-205/elements.expected b/cpp/ql/test/library-tests/CPP-205/elements.expected index f64b9d4e08b..76104232401 100644 --- a/cpp/ql/test/library-tests/CPP-205/elements.expected +++ b/cpp/ql/test/library-tests/CPP-205/elements.expected @@ -1,35 +1,21 @@ -| CPP-205.cpp:0:0:0:0 | CPP-205.cpp | | -| CPP-205.cpp:1:20:1:20 | T | | -| CPP-205.cpp:1:20:1:20 | definition of T | | -| CPP-205.cpp:2:5:2:5 | definition of fn | function declaration entry for int fn(int) | -| CPP-205.cpp:2:5:2:5 | fn | function int fn(int) | -| CPP-205.cpp:2:5:2:6 | definition of fn | function declaration entry for int fn(T) | -| CPP-205.cpp:2:5:2:6 | fn | function int fn(T) | -| CPP-205.cpp:2:10:2:12 | definition of out | parameter declaration entry for int fn(T) | -| CPP-205.cpp:2:10:2:12 | definition of out | parameter declaration entry for int fn(int) | -| CPP-205.cpp:2:10:2:12 | out | parameter for int fn(T) | -| CPP-205.cpp:2:10:2:12 | out | parameter for int fn(int) | -| CPP-205.cpp:2:15:5:1 | { ... } | | -| CPP-205.cpp:2:15:5:1 | { ... } | | -| CPP-205.cpp:3:3:3:33 | declaration | | -| CPP-205.cpp:3:3:3:33 | declaration | | -| CPP-205.cpp:3:15:3:15 | declaration of y | | -| CPP-205.cpp:3:15:3:15 | y | | -| CPP-205.cpp:3:17:3:31 | 5 | | -| CPP-205.cpp:4:3:4:11 | return ... | | -| CPP-205.cpp:4:3:4:11 | return ... | | -| CPP-205.cpp:4:10:4:10 | 0 | | -| CPP-205.cpp:4:10:4:10 | 0 | | +| CPP-205.cpp:2:5:2:5 | definition of fn | function declaration entry for int fn(int), isFromTemplateInstantiation(fn) | +| CPP-205.cpp:2:5:2:5 | fn | function int fn(int), isFromTemplateInstantiation(fn) | +| CPP-205.cpp:2:5:2:6 | definition of fn | function declaration entry for int fn(T), isFromUninstantiatedTemplate(fn) | +| CPP-205.cpp:2:5:2:6 | fn | function int fn(T), isFromUninstantiatedTemplate(fn) | +| CPP-205.cpp:2:10:2:12 | definition of out | isFromTemplateInstantiation(fn), parameter declaration entry for int fn(int) | +| CPP-205.cpp:2:10:2:12 | definition of out | isFromUninstantiatedTemplate(fn), parameter declaration entry for int fn(T) | +| CPP-205.cpp:2:10:2:12 | out | isFromTemplateInstantiation(fn), parameter for int fn(int) | +| CPP-205.cpp:2:10:2:12 | out | isFromUninstantiatedTemplate(fn), parameter for int fn(T) | +| CPP-205.cpp:2:15:5:1 | { ... } | isFromTemplateInstantiation(fn) | +| CPP-205.cpp:2:15:5:1 | { ... } | isFromUninstantiatedTemplate(fn) | +| CPP-205.cpp:3:3:3:33 | declaration | isFromTemplateInstantiation(fn) | +| CPP-205.cpp:3:3:3:33 | declaration | isFromUninstantiatedTemplate(fn) | +| CPP-205.cpp:3:15:3:15 | declaration of y | isFromUninstantiatedTemplate(fn) | +| CPP-205.cpp:3:15:3:15 | y | isFromUninstantiatedTemplate(fn) | +| CPP-205.cpp:3:17:3:31 | 5 | isFromTemplateInstantiation(fn) | +| CPP-205.cpp:4:3:4:11 | return ... | isFromTemplateInstantiation(fn) | +| CPP-205.cpp:4:3:4:11 | return ... | isFromUninstantiatedTemplate(fn) | +| CPP-205.cpp:4:10:4:10 | 0 | isFromTemplateInstantiation(fn) | +| CPP-205.cpp:4:10:4:10 | 0 | isFromUninstantiatedTemplate(fn) | | CPP-205.cpp:7:5:7:8 | definition of main | function declaration entry for int main() | | CPP-205.cpp:7:5:7:8 | main | function int main() | -| CPP-205.cpp:7:12:9:1 | { ... } | | -| CPP-205.cpp:8:3:8:15 | return ... | | -| CPP-205.cpp:8:10:8:11 | call to fn | | -| CPP-205.cpp:8:13:8:13 | 0 | | -| file://:0:0:0:0 | (unnamed parameter 0) | parameter for __va_list_tag& __va_list_tag::operator=(__va_list_tag const&) | -| file://:0:0:0:0 | (unnamed parameter 0) | parameter for __va_list_tag& __va_list_tag::operator=(__va_list_tag&&) | -| file://:0:0:0:0 | __super | | -| file://:0:0:0:0 | __va_list_tag | | -| file://:0:0:0:0 | operator= | function __va_list_tag& __va_list_tag::operator=(__va_list_tag const&) | -| file://:0:0:0:0 | operator= | function __va_list_tag& __va_list_tag::operator=(__va_list_tag&&) | -| file://:0:0:0:0 | y | | diff --git a/cpp/ql/test/library-tests/CPP-205/elements.ql b/cpp/ql/test/library-tests/CPP-205/elements.ql index 9388a799dbc..b1ead8bb00e 100644 --- a/cpp/ql/test/library-tests/CPP-205/elements.ql +++ b/cpp/ql/test/library-tests/CPP-205/elements.ql @@ -14,10 +14,20 @@ string describe(Element e) { result = "parameter declaration entry for " + getIdentityString(e.(ParameterDeclarationEntry).getFunctionDeclarationEntry().getFunction()) + or + exists(Element template | + e.isFromTemplateInstantiation(template) and + result = "isFromTemplateInstantiation(" + template.toString() + ")" + ) + or + exists(Element template | + e.isFromUninstantiatedTemplate(template) and + result = "isFromUninstantiatedTemplate(" + template.toString() + ")" + ) } from Element e where - not e.getLocation() instanceof UnknownLocation and + e.getLocation().getFile().getBaseName() != "" and not e instanceof Folder -select e, concat(describe(e), ", ") +select e, strictconcat(describe(e), ", ") diff --git a/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/standardFlow.ql b/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/standardFlow.ql index 1497702db76..d929b6557a4 100644 --- a/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/standardFlow.ql +++ b/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/standardFlow.ql @@ -14,8 +14,8 @@ module TestConfig implements DataFlow::ConfigSig { } } -module TestFlow = DataFlow::Make; +module TestFlow = DataFlow::Global; from DataFlow::Node sink, DataFlow::Node source -where TestFlow::hasFlow(source, sink) +where TestFlow::flow(source, sink) select sink, source diff --git a/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/withAdditionalFlow.ql b/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/withAdditionalFlow.ql index c46d2cddf88..49e98db06ae 100644 --- a/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/withAdditionalFlow.ql +++ b/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/withAdditionalFlow.ql @@ -25,8 +25,8 @@ module TestConfig implements DataFlow::ConfigSig { } } -module TestFlow = DataFlow::Make; +module TestFlow = DataFlow::Global; from DataFlow::Node sink, DataFlow::Node source -where TestFlow::hasFlow(source, sink) +where TestFlow::flow(source, sink) select sink, source diff --git a/cpp/ql/test/library-tests/dataflow/crement/from0.ql b/cpp/ql/test/library-tests/dataflow/crement/from0.ql index 90bf8401fba..d395920c030 100644 --- a/cpp/ql/test/library-tests/dataflow/crement/from0.ql +++ b/cpp/ql/test/library-tests/dataflow/crement/from0.ql @@ -7,8 +7,8 @@ module Cfg implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof VariableAccess } } -module Flow = DataFlow::Make; +module Flow = DataFlow::Global; from Expr sink -where Flow::hasFlowToExpr(sink) +where Flow::flowToExpr(sink) select sink diff --git a/cpp/ql/test/library-tests/ir/modulus-analysis/ModulusAnalysis.ql b/cpp/ql/test/library-tests/ir/modulus-analysis/ModulusAnalysis.ql index bae958e1076..e7c56c240df 100644 --- a/cpp/ql/test/library-tests/ir/modulus-analysis/ModulusAnalysis.ql +++ b/cpp/ql/test/library-tests/ir/modulus-analysis/ModulusAnalysis.ql @@ -5,6 +5,7 @@ import experimental.semmle.code.cpp.semantic.analysis.RangeUtils import experimental.semmle.code.cpp.semantic.analysis.FloatDelta import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysisSpecific import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysisImpl +import experimental.semmle.code.cpp.semantic.SemanticExprSpecific import semmle.code.cpp.ir.IR as IR import TestUtilities.InlineExpectationsTest @@ -18,7 +19,7 @@ class ModulusAnalysisTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { exists(SemExpr e, IR::CallInstruction call | - call.getArgument(0) = e and + getSemanticExpr(call.getArgument(0)) = e and call.getStaticCallTarget().hasName("mod") and tag = "mod" and element = e.toString() and diff --git a/cpp/ql/test/library-tests/ir/range-analysis/RangeAnalysis.ql b/cpp/ql/test/library-tests/ir/range-analysis/RangeAnalysis.ql index d3e44c868cf..9cae7bf9e72 100644 --- a/cpp/ql/test/library-tests/ir/range-analysis/RangeAnalysis.ql +++ b/cpp/ql/test/library-tests/ir/range-analysis/RangeAnalysis.ql @@ -12,7 +12,7 @@ class RangeAnalysisTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { exists(SemExpr e, IR::CallInstruction call | - call.getArgument(0) = e and + getSemanticExpr(call.getArgument(0)) = e and call.getStaticCallTarget().hasName("range") and tag = "range" and element = e.toString() and @@ -29,7 +29,7 @@ private string getDirectionString(boolean d) { } bindingset[value] -private string getOffsetString(int value) { +private string getOffsetString(float value) { if value >= 0 then result = "+" + value.toString() else result = value.toString() } @@ -37,7 +37,7 @@ bindingset[s] string quote(string s) { if s.matches("% %") then result = "\"" + s + "\"" else result = s } bindingset[delta] -private string getBoundString(SemBound b, int delta) { +private string getBoundString(SemBound b, float delta) { b instanceof SemZeroBound and result = delta.toString() or result = @@ -51,7 +51,7 @@ private string getBoundString(SemBound b, int delta) { } private string getARangeString(SemExpr e) { - exists(SemBound b, int delta, boolean upper | + exists(SemBound b, float delta, boolean upper | semBounded(e, b, delta, upper, _) and if semBounded(e, b, delta, upper.booleanNot(), _) then delta != 0 and result = "==" + getBoundString(b, delta) diff --git a/cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp b/cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp index 60e8bd2b4bf..f35b5dfe90c 100644 --- a/cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp +++ b/cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp @@ -18,20 +18,20 @@ int test2(struct List* p) { int count = 0; for (; p; p = p->next) { count = (count+1) % 10; - range(count); // $ range=<=9 + range(count); // $ range=<=9 range=>=-9 range=<=count:p+1 } - range(count); // $ range=<=9 + range(count); // $ range=>=-9 range=<=9 return count; } int test3(struct List* p) { int count = 0; for (; p; p = p->next) { - range(count++); // $ range=<=9 + range(count++); // $ range=>=-9 range=<=9 count = count % 10; - range(count); // $ range=<=9 + range(count); // $ range=<=9 range=>=-9 range="<=... +++0" range=<=count:p+1 } - range(count); // $ range=<=9 + range(count); // $ range=>=-9 range=<=9 return count; } @@ -42,11 +42,11 @@ int test4() { range(i); // $ range=<=1 MISSING: range=>=0 range(total); total += i; - range(total); + range(total); // $ range=<=i+1 range=<=i+1 range=>=0 range=>=i+0 } - range(total); + range(total); // $ range=>=0 range(i); // $ range===2 - range(total + i); // $ MISSING:range=>=i+1 + range(total + i); // $ range===i+2 range=>=2 range=>=i+0 return total + i; } @@ -54,14 +54,14 @@ int test5() { int i = 0; int total = 0; for (i = 0; i < 2; i++) { - range(i); // $ range=<=1 MISSING:range=>=0 - range(total); + range(i); // $ range=<=1 range=>=0 + range(total); // $ range=>=0 total += i; - range(total); + range(total); // $ range=<=i+1 range=>=0 range=>=i+0 } - range(total); + range(total); // $ range=>=0 range(i); // $ range===2 - range(total + i); // $ MISSING:range=>=i+1 + range(total + i); // $ range===i+2 range=>=2 range=>=i+0 return total + i; } @@ -69,10 +69,10 @@ int test6() { int i = 0; int total = 0; for (i = 0; i+2 < 4; i = i+1) { - range(i); // $ range=<=1 MISSING:range=>=0 - range(total); + range(i); // $ range=<=1 range=>=0 + range(total); // $ range=>=0 total += i; - range(total); + range(total); // $ range=<=i+1 range=>=0 range=>=i+0 } return total + i; } @@ -149,7 +149,7 @@ int test11(char *p) { range(*p); } if (c == ':') { - range(c); + range(c); // $ range===58 c = *p; range(*p); if (c != '\0') { @@ -233,9 +233,9 @@ int test_unary(int a) { range(b); // $ range=<=11 range=>=3 int c = -a; range(c); // $ range=<=-3 range=>=-11 - range(b+c); // $ range=<=10 range="<=+ ...:a-1" range=">=- ...+1" range=>=-10 + range(b+c); // $ range=<=8 range=>=-8 total += b+c; - range(total); + range(total); // $ range=<=8 range=>=-8 } if (0 <= a && a <= 11) { range(a); // $ range=<=11 range=>=0 @@ -245,7 +245,7 @@ int test_unary(int a) { range(c); range(b+c); // $ range=<=11 range="<=+ ...:a+0" MISSING:range=">=- ...+0" total += b+c; - range(total); + range(total); // $ range=<=0+11 range=<=19 range=>=0-11 range=>=-19 } if (-7 <= a && a <= 11) { range(a); // $ range=<=11 range=>=-7 @@ -253,9 +253,9 @@ int test_unary(int a) { range(b); // $ range=<=11 range=>=-7 int c = -a; range(c); // $ range=<=7 range=>=-11 - range(b+c); + range(b+c); // $ range=<=18 range=>=-18 total += b+c; - range(total); + range(total); // $ range="<=- ...+18" range=">=- ...-18" range=<=0+29 range=<=37 range=>=0-29 range=>=-37 } if (-7 <= a && a <= 1) { range(a); // $ range=<=1 range=>=-7 @@ -263,9 +263,9 @@ int test_unary(int a) { range(b); // $ range=<=1 range=>=-7 int c = -a; range(c); // $ range=<=7 range=>=-1 - range(b+c); + range(b+c); // $ range=<=8 range=>=-8 total += b+c; - range(total); + range(total); // $ range="<=- ...+8" range="<=- ...+26" range=">=- ...-8" range=">=- ...-26" range=<=0+37 range=<=45 range=>=0-37 range=>=-45 } if (-7 <= a && a <= 0) { range(a); // $ range=<=0 range=>=-7 @@ -275,7 +275,7 @@ int test_unary(int a) { range(c); range(b+c); // $ range=">=+ ...:a+0" range=>=-7 MISSING:range="<=- ...+0" total += b+c; - range(total); + range(total); // $ range="<=- ...+7" range="<=- ...+15" range="<=- ...+33" range=">=- ...-7" range=">=- ...-15" range=">=- ...-33" range=<=0+44 range=<=52 range=>=0-44 range=>=-52 } if (-7 <= a && a <= -2) { range(a); // $ range=<=-2 range=>=-7 @@ -283,10 +283,12 @@ int test_unary(int a) { range(b); // $ range=<=-2 range=>=-7 int c = -a; range(c); // $ range=<=7 range=>=2 - range(b+c); // $ range="<=- ...-1" range=">=+ ...:a+1" range=>=-6 range=<=6 - range(c); + range(b+c); // $ range=<=5 range=>=-5 + total += b+c; + range(total); // $ range="<=- ...+5" range="<=- ...+12" range="<=- ...+20" range="<=- ...+38" range=">=- ...-5" range=">=- ...-12" range=">=- ...-20" range=">=- ...-38" range=<=0+49 range=<=57 range=>=0-49 range=>=-57 } - range(total); + range(total); // $ range="<=- ...+5" range="<=- ...+12" range="<=- ...+20" range="<=- ...+38" range=">=- ...-5" range=">=- ...-12" range=">=- ...-20" range=">=- ...-38" range=<=0+49 range=<=57 range=>=0-49 range=>=-57 + return total; } @@ -298,17 +300,17 @@ int test_mult01(int a, int b) { range(a); // $ range=<=11 range=>=3 range(b); // $ range=<=23 range=>=5 int r = a*b; // 15 .. 253 - range(r); + range(r); // $ range=<=253 range=>=15 total += r; - range(total); // $ range=>=1 + range(total); // $ range=<=253 range=>=15 } if (3 <= a && a <= 11 && 0 <= b && b <= 23) { range(a); // $ range=<=11 range=>=3 range(b); // $ range=<=23 range=>=0 int r = a*b; // 0 .. 253 - range(r); + range(r); // $ range=<=253 range=>=0 total += r; - range(total); // $ range=>=0 range=>=3+0 + range(total); // $ range=<=3+253 range=<=506 range=>=0 range=>=3+0 } if (3 <= a && a <= 11 && -13 <= b && b <= 23) { range(a); // $ range=<=11 range=>=3 @@ -316,25 +318,25 @@ int test_mult01(int a, int b) { int r = a*b; // -143 .. 253 range(r); total += r; - range(total); + range(total); // $ MISSING: range=">=... * ...+0" } if (3 <= a && a <= 11 && -13 <= b && b <= 0) { range(a); // $ range=<=11 range=>=3 range(b); // $ range=<=0 range=>=-13 int r = a*b; // -143 .. 0 - range(r); + range(r); // $ range=<=0 range=>=-143 total += r; - range(total); // $ MISSING:range=<=3+0 + range(total); // $ range=<=3+0 range=>=3-143 } if (3 <= a && a <= 11 && -13 <= b && b <= -7) { range(a); // $ range=<=11 range=>=3 range(b); // $ range=<=-7 range=>=-13 int r = a*b; // -143 .. -21 - range(r); + range(r); // $ range=<=-21 range=>=-143 total += r; - range(total); // $ MISSING:range=<=3-1 + range(total); // $ range=<=3-21 range=>=3-143 range=>=3-286 } - range(total); // $ MISSING:range=<=3+0 + range(total); // $ range=<=3+0 range=>=3-143 range=>=3-286 return total; } @@ -346,17 +348,17 @@ int test_mult02(int a, int b) { range(a); // $ range=<=11 range=>=0 range(b); // $ range=<=23 range=>=5 int r = a*b; // 0 .. 253 - range(r); + range(r); // $ range=<=253 range=>=0 total += r; - range(total); // $ range=>=0 + range(total); // $ range=>=0 range=<=253 } if (0 <= a && a <= 11 && 0 <= b && b <= 23) { range(a); // $ range=<=11 range=>=0 range(b); // $ range=<=23 range=>=0 int r = a*b; // 0 .. 253 - range(r); + range(r); // $ range=<=253 range=>=0 total += r; - range(total); // $ range=>=0 range=>=0+0 + range(total); // $ range=>=0 range=>=0+0 range=<=0+253 range=<=506 } if (0 <= a && a <= 11 && -13 <= b && b <= 23) { range(a); // $ range=<=11 range=>=0 @@ -364,25 +366,25 @@ int test_mult02(int a, int b) { int r = a*b; // -143 .. 253 range(r); total += r; - range(total); + range(total); // $ MISSING: range=">=... * ...+0" } if (0 <= a && a <= 11 && -13 <= b && b <= 0) { range(a); // $ range=<=11 range=>=0 range(b); // $ range=<=0 range=>=-13 int r = a*b; // -143 .. 0 - range(r); + range(r); // $ range=<=0 range=>=-143 total += r; - range(total); // $ MISSING:range=<=0+0 + range(total); // $ range=<=0+0 range=>=0-143 } if (0 <= a && a <= 11 && -13 <= b && b <= -7) { range(a); // $ range=<=11 range=>=0 range(b); // $ range=<=-7 range=>=-13 int r = a*b; // -143 .. 0 - range(r); + range(r); // $ range=<=0 range=>=-143 total += r; - range(total); // $ MISSING:range=<=0+0 + range(total); // $ range=<=0+0 range=>=0-143 range=>=0-286 } - range(total); // $ MISSING:range=<=0+0 + range(total); // $ range=<=0+0 range=>=0-143 range=>=0-286 return total; } @@ -443,15 +445,15 @@ int test_mult04(int a, int b) { range(b); // $ range=<=23 range=>=5 int r = a*b; // -391 .. 0 total += r; - range(total); // $ range=<=0 + range(total); // $ range=<=0 range=>=-391 } if (-17 <= a && a <= 0 && 0 <= b && b <= 23) { range(a); // $ range=<=0 range=>=-17 range(b); // $ range=<=23 range=>=0 int r = a*b; // -391 .. 0 - range(r); + range(r); // $ range=<=0 range=>=-391 total += r; - range(total); // $ range="<=- ...+0" range=<=0 + range(total); // $ range="<=- ...+0" range=<=0 range=">=- ...-391" range=>=-782 } if (-17 <= a && a <= 0 && -13 <= b && b <= 23) { range(a); // $ range=<=0 range=>=-17 @@ -459,25 +461,25 @@ int test_mult04(int a, int b) { int r = a*b; // -391 .. 221 range(r); total += r; - range(total); + range(total); // $ MISSING: range="<=... * ...+0" } if (-17 <= a && a <= 0 && -13 <= b && b <= 0) { range(a); // $ range=<=0 range=>=-17 range(b); // $ range=<=0 range=>=-13 int r = a*b; // 0 .. 221 - range(r); + range(r); // $ range=<=221 range=>=0 total += r; - range(total); // $ MISSING:range=">=- ...+0" + range(total); // $ range="<=- ...+221" range=">=- ...+0" } if (-17 <= a && a <= 0 && -13 <= b && b <= -7) { range(a); // $ range=<=0 range=>=-17 range(b); // $ range=<=-7 range=>=-13 int r = a*b; // 0 .. 221 - range(r); + range(r); // $ range=<=221 range=>=0 total += r; - range(total); // $ MISSING:range=">=- ...+0" + range(total); // $ range=">=- ...+0" range="<=- ...+221" range="<=- ...+442" } - range(total); // $ MISSING:range=">=- ...+0" + range(total); // $ range=">=- ...+0" range="<=- ...+221" range="<=- ...+442" return total; } @@ -489,17 +491,17 @@ int test_mult05(int a, int b) { range(a); // $ range=<=-2 range=>=-17 range(b); // $ range=<=23 range=>=5 int r = a*b; // -391 .. -10 - range(r); + range(r); // $ range=<=-10 range=>=-391 total += r; - range(total); // $ range=<=-1 + range(total); // $ range=<=-10 range=>=-391 } if (-17 <= a && a <= -2 && 0 <= b && b <= 23) { range(a); // $ range=<=-2 range=>=-17 range(b); // $ range=<=23 range=>=0 int r = a*b; // -391 .. 0 - range(r); + range(r); // $ range=<=0 range=>=-391 total += r; - range(total); // $ range="<=- ...+0" range=<=0 + range(total); // $ range="<=- ...+0" range=<=0 range=">=- ...-391" range=>=-782 } if (-17 <= a && a <= -2 && -13 <= b && b <= 23) { range(a); // $ range=<=-2 range=>=-17 @@ -507,25 +509,25 @@ int test_mult05(int a, int b) { int r = a*b; // -391 .. 221 range(r); total += r; - range(total); + range(total); // $ MISSING: range="<=... * ...+0" } if (-17 <= a && a <= -2 && -13 <= b && b <= 0) { range(a); // $ range=<=-2 range=>=-17 range(b); // $ range=<=0 range=>=-13 int r = a*b; // 0 .. 221 - range(r); + range(r); // $ range=<=221 range=>=0 total += r; - range(total); // $ MISSING:range=">=- ...+0" + range(total); // $ range="<=- ...+221" range=">=- ...+0" } if (-17 <= a && a <= -2 && -13 <= b && b <= -7) { range(a); // $ range=<=-2 range=>=-17 range(b); // $ range=<=-7 range=>=-13 int r = a*b; // 14 .. 221 - range(r); + range(r); // $ range=<=221 range=>=14 total += r; - range(total); // $ MISSING:range=">=- ...+1" + range(total); // $ range="<=- ...+221" range="<=- ...+442" range=">=- ...+14" } - range(total); // $ MISSING:range=">=- ...+0" + range(total); // $ range=">=- ...+0" range="<=- ...+221" range="<=- ...+442" return total; } @@ -596,7 +598,7 @@ unsigned int test_ternary01(unsigned int x) { (range(x), 500); // $ range=<=299 range(y8); // y8 <= 300 } - range(y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8); // $ MISSING:range=">=... = ...:... ? ... : ...+0" MISSING:range=">=call to range+0" + range(y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8); // $ MISSING: range=">=... = ...:... ? ... : ...+0" range=">=call to range+0" return y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8; } @@ -626,7 +628,7 @@ unsigned int test_ternary02(unsigned int x) { (range(x), 5); // $ range=>=300 range(y5); // y6 >= 0 } - range(y1 + y2 + y3 + y4 + y5); // $ MISSING:range=">=... = ...:... ? ... : ...+0" MISSING:range=">=call to range+0" + range(y1 + y2 + y3 + y4 + y5); // $ MISSING: range=">=... = ...:... ? ... : ...+0" range=">=call to range+0" return y1 + y2 + y3 + y4 + y5; } @@ -644,8 +646,8 @@ unsigned int test_comma01(unsigned int x) { y += 3, range(y), // $ MISSING:range="==++ ...:... = ...+4" MISSING:range="==... +++3" range="==... ? ... : ...+5" y); - range(y2); // $ MISSING:range="==++ ...:... = ...+4" MISSING:range="==... +++3" MISSING:range="==... ? ... : ...+5" - range(y1 + y2); // $ MISSING:range=">=++ ...:... = ...+5" MISSING:range=">=... +++4" MISSING:range=">=... += ...:... = ...+1" MISSING:range=">=... ? ... : ...+6" + range(y2); // $ range="==++ ...:... = ...+4" range="==... +++3" range="==... ? ... : ...+5" + range(y1 + y2); // $ MISSING: range=">=++ ...:... = ...+5" range=">=... +++4" range=">=... += ...:... = ...+1" range=">=... ? ... : ...+6" return y1 + y2; } @@ -683,7 +685,7 @@ int test_unsigned_mult01(unsigned int a, unsigned b) { int r = a*b; // 15 .. 253 range(r); total += r; - range(total); // $ range=>=1 + range(total); // $ MISSING: range=>=1 } if (3 <= a && a <= 11 && 0 <= b && b <= 23) { range(a); // $ range=<=11 range=>=3 @@ -691,7 +693,7 @@ int test_unsigned_mult01(unsigned int a, unsigned b) { int r = a*b; // 0 .. 253 range(r); total += r; - range(total); // $ range=">=(unsigned int)...+0" range=>=0 + range(total); // $ MISSING: range=">=(unsigned int)...+0" range=>=0 } if (3 <= a && a <= 11 && 13 <= b && b <= 23) { range(a); // $ range=<=11 range=>=3 @@ -699,9 +701,9 @@ int test_unsigned_mult01(unsigned int a, unsigned b) { int r = a*b; // 39 .. 253 range(r); total += r; - range(total); // $ range=">=(unsigned int)...+1" range=>=1 + range(total); // $ MISSING: range=">=(unsigned int)...+1" range=>=1 } - range(total); // $ range=">=(unsigned int)...+0" range=>=0 + range(total); // $ MISSING: range=">=(unsigned int)...+0" range=>=0 return total; } @@ -713,23 +715,23 @@ int test_unsigned_mult02(unsigned b) { int r = 11*b; // 55 .. 253 range(r); total += r; - range(total); // $ range=>=1 + range(total); // $ MISSING: range=>=1 } if (0 <= b && b <= 23) { range(b); // $ range=<=23 range=>=0 int r = 11*b; // 0 .. 253 range(r); total += r; - range(total); // $ range=">=(unsigned int)...+0" range=>=0 + range(total); // $ MISSING: range=">=(unsigned int)...+0" range=>=0 } if (13 <= b && b <= 23) { range(b); // $ range=<=23 range=>=13 int r = 11*b; // 143 .. 253 range(r); total += r; - range(total); // $ range=">=(unsigned int)...+1" range=>=1 + range(total); // $ MISSING: range=">=(unsigned int)...+1" range=>=1 } - range(total); // $ range=">=(unsigned int)...+0" range=>=0 + range(total); // $ MISSING: range=">=(unsigned int)...+0" range=>=0 return total; } @@ -739,7 +741,7 @@ unsigned long mult_rounding() { range(y); // $ range===1000000003 range(x); // $ range===1000000003 xy = x * y; - range(xy); + range(xy); // $ range===1000000006000000000 return xy; // BUG: upper bound should be >= 1000000006000000009UL } @@ -759,13 +761,13 @@ unsigned long mult_lower_bound(unsigned int ui, unsigned long ul) { range(ui); // $ range=>=10 range((unsigned long)ui); // $ range=>=10 unsigned long result = (unsigned long)ui * ui; - range(result); + range(result); // $ range=>=100 range=>=100 return result; // BUG: upper bound should be >= 18446744065119617025 } if (ul >= 10) { range(ul); // $ range=>=10 unsigned long result = ul * ul; - range(result); + range(result); // $ range=>=100 return result; // BUG: lower bound should be 0 (overflow is possible) } return 0; @@ -775,7 +777,7 @@ unsigned long mul_assign(unsigned int ui) { if (ui <= 10 && ui >= 2) { range(ui); // $ range=<=10 range=>=2 ui *= ui + 0; - range(ui); + range(ui); // $ range=<=100 range=>=4 return ui; // 4 .. 100 } @@ -788,7 +790,7 @@ unsigned long mul_assign(unsigned int ui) { range(ulconst); // $ range===10 ulconst *= 4; range(ulconst); // $ range===40 - range(uiconst + ulconst); // $ range=">=... *= ...+1" range=">=... + ...+0" range=>=41 + range(uiconst + ulconst); // $ range===80 return uiconst + ulconst; // 40 .. 40 for both } @@ -811,7 +813,7 @@ int mul_by_constant(int i, int j) { range(i); // $ range===-1 range((int)0xffFFffFF); // $ range===-1 i = i * (int)0xffFFffFF; // fully converted literal is -1 - range(i); // 1 .. 1 + range(i); // $ range===1 } i = i * -1; range( i); // -2^31 .. 2^31-1 @@ -854,18 +856,18 @@ int notequal_type_endpoint(unsigned n) { void notequal_refinement(short n) { if (n < 0) { - range(n); + range(n); // $ range=<=-1 return; } if (n == 0) { range(n); // 0 .. 0 } else { - range(n); // 1 .. + range(n); // $ range=>=1 } if (n) { - range(n); // 1 .. + range(n); // $ range=>=1 } else { range(n); // 0 .. 0 } @@ -881,16 +883,16 @@ void notequal_refinement(short n) { void notequal_variations(short n, float f) { if (n != 0) { if (n >= 0) { - range(n); // 1 .. [BUG: we can't handle `!=` coming first] + range(n); // $ range=>=1 } } if (n >= 5) { if (2 * n - 10 == 0) { // Same as `n == 10/2` (modulo overflow) - range(n); + range(n); // $ range=>=5 MISSING: range===5 return; } - range(n); // 6 .. + range(n); // $ range=>=5 MISSING: range=>=6 } if (n != -32768 && n != -32767) { @@ -898,8 +900,12 @@ void notequal_variations(short n, float f) { } if (n >= 0) { - n ? (range(n), n) : (range(n), n); // ? 1.. : 0..0 - !n ? (range(n), n) : (range(n), n); // ? 0..0 : 1.. + n ? + (range(n), n) // $ range=>=1 + : (range(n), n); // $ MISSING: range===0 + !n ? + (range(n), n) // $ MISSING: range===0 + : (range(n), n); // $ range=>=1 } } @@ -915,7 +921,7 @@ void two_bounds_from_one_test(short ss, unsigned short us) { } if (ss < 0x8001) { // Lower bound removed in `getDefLowerBounds` - range(ss); // -32768 .. 32767 + range(ss); // $ range=<=32768 MISSING: range=>=-32768 } if ((short)us >= 0) { @@ -940,7 +946,7 @@ void widen_recursive_expr() { for (s = 0; s < 10; s++) { range(s); // $ range=<=9 MISSING:range=>=0 int result = s + s; - range(result); // 0 .. 18 + range(result); // $ range=<=18 range=<=s+9 range=>=0 range=>=s+0 } } @@ -958,7 +964,22 @@ void guard_bound_out_of_range(void) { void test_mod(int s) { int s2 = s % 5; - range(s2); // $ range=<=4 // -4 .. 4 + range(s2); // $ range=>=-4 range=<=4 +} + +void test_mod_neg(int s) { + int s2 = s % -5; + range(s2); // $ range=>=-4 range=<=4 +} + +void test_mod_ternary(int s, bool b) { + int s2 = s % (b ? 5 : 500); + range(s2); // $ range=>=-499 range=<=499 range="<=... ? ... : ...-1" +} + +void test_mod_ternary2(int s, bool b1, bool b2) { + int s2 = s % (b1 ? (b2 ? 5 : -5000) : -500000); + range(s2); // $ range=>=-499999 range=<=499999 } void exit(int); diff --git a/cpp/ql/test/library-tests/ir/range-analysis/test.cpp b/cpp/ql/test/library-tests/ir/range-analysis/test.cpp index 5290fffc8fd..f8587c42d67 100644 --- a/cpp/ql/test/library-tests/ir/range-analysis/test.cpp +++ b/cpp/ql/test/library-tests/ir/range-analysis/test.cpp @@ -7,7 +7,7 @@ } if (y - 2 == x && y > 300) { - range(x + y); // $ range=>=300 range=>=x+1 range=>=y-1 + range(x + y); // $ range=<=802 range=>=600 return x + y; } diff --git a/cpp/ql/test/library-tests/ir/sign-analysis/SignAnalysis.ql b/cpp/ql/test/library-tests/ir/sign-analysis/SignAnalysis.ql index d4f499fdc61..7b78b077a9b 100644 --- a/cpp/ql/test/library-tests/ir/sign-analysis/SignAnalysis.ql +++ b/cpp/ql/test/library-tests/ir/sign-analysis/SignAnalysis.ql @@ -4,6 +4,7 @@ import experimental.semmle.code.cpp.semantic.Semantic import experimental.semmle.code.cpp.semantic.analysis.RangeUtils import experimental.semmle.code.cpp.semantic.analysis.FloatDelta import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysisSpecific +import experimental.semmle.code.cpp.semantic.SemanticExprSpecific import semmle.code.cpp.ir.IR as IR import TestUtilities.InlineExpectationsTest @@ -16,7 +17,7 @@ class SignAnalysisTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { exists(SemExpr e, IR::CallInstruction call | - call.getArgument(0) = e and + getSemanticExpr(call.getArgument(0)) = e and call.getStaticCallTarget().hasName("sign") and tag = "sign" and element = e.toString() and diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 147c10b7c7f..7f76af075a7 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -1814,3 +1814,81 @@ ssa.cpp: # 383| Block 5 # 383| v383_17(void) = Unreached : + +# 401| void vla(int, int, int, bool) +# 401| Block 0 +# 401| v401_1(void) = EnterFunction : +# 401| m401_2(unknown) = AliasedDefinition : +# 401| m401_3(unknown) = InitializeNonLocal : +# 401| m401_4(unknown) = Chi : total:m401_2, partial:m401_3 +# 401| r401_5(glval) = VariableAddress[n1] : +# 401| m401_6(int) = InitializeParameter[n1] : &:r401_5 +# 401| r401_7(glval) = VariableAddress[n2] : +# 401| m401_8(int) = InitializeParameter[n2] : &:r401_7 +# 401| r401_9(glval) = VariableAddress[n3] : +# 401| m401_10(int) = InitializeParameter[n3] : &:r401_9 +# 401| r401_11(glval) = VariableAddress[b1] : +# 401| m401_12(bool) = InitializeParameter[b1] : &:r401_11 +# 402| r402_1(glval) = VariableAddress[b] : +# 402| m402_2(int[]) = Uninitialized[b] : &:r402_1 +# 402| r402_3(glval) = VariableAddress[n1] : +# 402| r402_4(int) = Load[n1] : &:r402_3, m401_6 +# 402| v402_5(void) = NoOp : +# 403| r403_1(glval) = VariableAddress[c] : +# 403| m403_2(int[][]) = Uninitialized[c] : &:r403_1 +# 403| m403_3(unknown) = Chi : total:m401_4, partial:m403_2 +# 403| r403_4(glval) = VariableAddress[n1] : +# 403| r403_5(int) = Load[n1] : &:r403_4, m401_6 +# 403| r403_6(glval) = VariableAddress[n2] : +# 403| r403_7(int) = Load[n2] : &:r403_6, m401_8 +# 403| v403_8(void) = NoOp : +# 405| r405_1(int) = Constant[0] : +# 405| r405_2(glval) = VariableAddress[b] : +# 405| r405_3(int *) = Convert : r405_2 +# 405| r405_4(glval) = CopyValue : r405_3 +# 405| m405_5(int) = Store[?] : &:r405_4, r405_1 +# 405| m405_6(int[]) = Chi : total:m402_2, partial:m405_5 +# 406| r406_1(int) = Constant[1] : +# 406| r406_2(glval) = VariableAddress[b] : +# 406| r406_3(int *) = Convert : r406_2 +# 406| r406_4(int) = Constant[0] : +# 406| r406_5(glval) = PointerAdd[4] : r406_3, r406_4 +# 406| m406_6(int) = Store[?] : &:r406_5, r406_1 +# 406| m406_7(int[]) = Chi : total:m405_6, partial:m406_6 +# 408| r408_1(int) = Constant[0] : +# 408| r408_2(glval) = VariableAddress[c] : +# 408| r408_3(int(*)[]) = Convert : r408_2 +# 408| r408_4(int) = Constant[1] : +# 408| r408_5(int(*)[]) = PointerAdd : r408_3, r408_4 +# 408| r408_6(glval) = CopyValue : r408_5 +# 408| r408_7(int *) = Convert : r408_6 +# 408| r408_8(glval) = CopyValue : r408_7 +# 408| m408_9(int) = Store[?] : &:r408_8, r408_1 +# 408| m408_10(unknown) = Chi : total:m403_3, partial:m408_9 +# 410| r410_1(glval) = VariableAddress[b1] : +# 410| r410_2(bool) = Load[b1] : &:r410_1, m401_12 +# 410| v410_3(void) = ConditionalBranch : r410_2 +#-----| False -> Block 2 +#-----| True -> Block 1 + +# 411| Block 1 +# 411| r411_1(glval) = VariableAddress[b] : +# 411| m411_2(int[]) = Uninitialized[b] : &:r411_1 +# 411| r411_3(glval) = VariableAddress[n1] : +# 411| r411_4(int) = Load[n1] : &:r411_3, m401_6 +# 411| v411_5(void) = NoOp : +#-----| Goto -> Block 3 + +# 413| Block 2 +# 413| r413_1(glval) = VariableAddress[b] : +# 413| m413_2(int[]) = Uninitialized[b] : &:r413_1 +# 413| r413_3(glval) = VariableAddress[n2] : +# 413| r413_4(int) = Load[n2] : &:r413_3, m401_8 +# 413| v413_5(void) = NoOp : +#-----| Goto -> Block 3 + +# 415| Block 3 +# 415| v415_1(void) = NoOp : +# 401| v401_13(void) = ReturnVoid : +# 401| v401_14(void) = AliasedUse : ~m408_10 +# 401| v401_15(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected index 396b7532d68..1ad86dc0da0 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected @@ -1804,3 +1804,80 @@ ssa.cpp: # 383| Block 5 # 383| v383_17(void) = Unreached : + +# 401| void vla(int, int, int, bool) +# 401| Block 0 +# 401| v401_1(void) = EnterFunction : +# 401| m401_2(unknown) = AliasedDefinition : +# 401| m401_3(unknown) = InitializeNonLocal : +# 401| m401_4(unknown) = Chi : total:m401_2, partial:m401_3 +# 401| r401_5(glval) = VariableAddress[n1] : +# 401| m401_6(int) = InitializeParameter[n1] : &:r401_5 +# 401| r401_7(glval) = VariableAddress[n2] : +# 401| m401_8(int) = InitializeParameter[n2] : &:r401_7 +# 401| r401_9(glval) = VariableAddress[n3] : +# 401| m401_10(int) = InitializeParameter[n3] : &:r401_9 +# 401| r401_11(glval) = VariableAddress[b1] : +# 401| m401_12(bool) = InitializeParameter[b1] : &:r401_11 +# 402| r402_1(glval) = VariableAddress[b] : +# 402| m402_2(int[]) = Uninitialized[b] : &:r402_1 +# 402| r402_3(glval) = VariableAddress[n1] : +# 402| r402_4(int) = Load[n1] : &:r402_3, m401_6 +# 402| v402_5(void) = NoOp : +# 403| r403_1(glval) = VariableAddress[c] : +# 403| m403_2(int[][]) = Uninitialized[c] : &:r403_1 +# 403| r403_3(glval) = VariableAddress[n1] : +# 403| r403_4(int) = Load[n1] : &:r403_3, m401_6 +# 403| r403_5(glval) = VariableAddress[n2] : +# 403| r403_6(int) = Load[n2] : &:r403_5, m401_8 +# 403| v403_7(void) = NoOp : +# 405| r405_1(int) = Constant[0] : +# 405| r405_2(glval) = VariableAddress[b] : +# 405| r405_3(int *) = Convert : r405_2 +# 405| r405_4(glval) = CopyValue : r405_3 +# 405| m405_5(int) = Store[?] : &:r405_4, r405_1 +# 405| m405_6(int[]) = Chi : total:m402_2, partial:m405_5 +# 406| r406_1(int) = Constant[1] : +# 406| r406_2(glval) = VariableAddress[b] : +# 406| r406_3(int *) = Convert : r406_2 +# 406| r406_4(int) = Constant[0] : +# 406| r406_5(glval) = PointerAdd[4] : r406_3, r406_4 +# 406| m406_6(int) = Store[?] : &:r406_5, r406_1 +# 406| m406_7(int[]) = Chi : total:m405_6, partial:m406_6 +# 408| r408_1(int) = Constant[0] : +# 408| r408_2(glval) = VariableAddress[c] : +# 408| r408_3(int(*)[]) = Convert : r408_2 +# 408| r408_4(int) = Constant[1] : +# 408| r408_5(int(*)[]) = PointerAdd : r408_3, r408_4 +# 408| r408_6(glval) = CopyValue : r408_5 +# 408| r408_7(int *) = Convert : r408_6 +# 408| r408_8(glval) = CopyValue : r408_7 +# 408| m408_9(int) = Store[?] : &:r408_8, r408_1 +# 408| m408_10(unknown) = Chi : total:m401_4, partial:m408_9 +# 410| r410_1(glval) = VariableAddress[b1] : +# 410| r410_2(bool) = Load[b1] : &:r410_1, m401_12 +# 410| v410_3(void) = ConditionalBranch : r410_2 +#-----| False -> Block 2 +#-----| True -> Block 1 + +# 411| Block 1 +# 411| r411_1(glval) = VariableAddress[b] : +# 411| m411_2(int[]) = Uninitialized[b] : &:r411_1 +# 411| r411_3(glval) = VariableAddress[n1] : +# 411| r411_4(int) = Load[n1] : &:r411_3, m401_6 +# 411| v411_5(void) = NoOp : +#-----| Goto -> Block 3 + +# 413| Block 2 +# 413| r413_1(glval) = VariableAddress[b] : +# 413| m413_2(int[]) = Uninitialized[b] : &:r413_1 +# 413| r413_3(glval) = VariableAddress[n2] : +# 413| r413_4(int) = Load[n2] : &:r413_3, m401_8 +# 413| v413_5(void) = NoOp : +#-----| Goto -> Block 3 + +# 415| Block 3 +# 415| v415_1(void) = NoOp : +# 401| v401_13(void) = ReturnVoid : +# 401| v401_14(void) = AliasedUse : ~m408_10 +# 401| v401_15(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp index ec8ea81e9e4..98c33c3eddf 100644 --- a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp +++ b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp @@ -396,4 +396,20 @@ int FusedBlockPhiOperand(int x, int y, int z, bool b1) { } return ret; +} + +void vla(int n1, int n2, int n3, bool b1) { + int b[n1]; + int c[n1][n2]; + + *b = 0; + b[0] = 1; + + **(c + 1) = 0; + + if(b1) { + int b[n1]; + } else { + int b[n2]; + } } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 3fc07bf6950..03de47a1ab0 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -1695,3 +1695,76 @@ ssa.cpp: # 383| v383_13(void) = ReturnValue : &:r383_12, m398_5 # 383| v383_14(void) = AliasedUse : ~m? # 383| v383_15(void) = ExitFunction : + +# 401| void vla(int, int, int, bool) +# 401| Block 0 +# 401| v401_1(void) = EnterFunction : +# 401| mu401_2(unknown) = AliasedDefinition : +# 401| mu401_3(unknown) = InitializeNonLocal : +# 401| r401_4(glval) = VariableAddress[n1] : +# 401| m401_5(int) = InitializeParameter[n1] : &:r401_4 +# 401| r401_6(glval) = VariableAddress[n2] : +# 401| m401_7(int) = InitializeParameter[n2] : &:r401_6 +# 401| r401_8(glval) = VariableAddress[n3] : +# 401| m401_9(int) = InitializeParameter[n3] : &:r401_8 +# 401| r401_10(glval) = VariableAddress[b1] : +# 401| m401_11(bool) = InitializeParameter[b1] : &:r401_10 +# 402| r402_1(glval) = VariableAddress[b] : +# 402| mu402_2(int[]) = Uninitialized[b] : &:r402_1 +# 402| r402_3(glval) = VariableAddress[n1] : +# 402| r402_4(int) = Load[n1] : &:r402_3, m401_5 +# 402| v402_5(void) = NoOp : +# 403| r403_1(glval) = VariableAddress[c] : +# 403| mu403_2(int[][]) = Uninitialized[c] : &:r403_1 +# 403| r403_3(glval) = VariableAddress[n1] : +# 403| r403_4(int) = Load[n1] : &:r403_3, m401_5 +# 403| r403_5(glval) = VariableAddress[n2] : +# 403| r403_6(int) = Load[n2] : &:r403_5, m401_7 +# 403| v403_7(void) = NoOp : +# 405| r405_1(int) = Constant[0] : +# 405| r405_2(glval) = VariableAddress[b] : +# 405| r405_3(int *) = Convert : r405_2 +# 405| r405_4(glval) = CopyValue : r405_3 +# 405| mu405_5(int) = Store[?] : &:r405_4, r405_1 +# 406| r406_1(int) = Constant[1] : +# 406| r406_2(glval) = VariableAddress[b] : +# 406| r406_3(int *) = Convert : r406_2 +# 406| r406_4(int) = Constant[0] : +# 406| r406_5(glval) = PointerAdd[4] : r406_3, r406_4 +# 406| mu406_6(int) = Store[?] : &:r406_5, r406_1 +# 408| r408_1(int) = Constant[0] : +# 408| r408_2(glval) = VariableAddress[c] : +# 408| r408_3(int(*)[]) = Convert : r408_2 +# 408| r408_4(int) = Constant[1] : +# 408| r408_5(int(*)[]) = PointerAdd : r408_3, r408_4 +# 408| r408_6(glval) = CopyValue : r408_5 +# 408| r408_7(int *) = Convert : r408_6 +# 408| r408_8(glval) = CopyValue : r408_7 +# 408| mu408_9(int) = Store[?] : &:r408_8, r408_1 +# 410| r410_1(glval) = VariableAddress[b1] : +# 410| r410_2(bool) = Load[b1] : &:r410_1, m401_11 +# 410| v410_3(void) = ConditionalBranch : r410_2 +#-----| False -> Block 2 +#-----| True -> Block 1 + +# 411| Block 1 +# 411| r411_1(glval) = VariableAddress[b] : +# 411| m411_2(int[]) = Uninitialized[b] : &:r411_1 +# 411| r411_3(glval) = VariableAddress[n1] : +# 411| r411_4(int) = Load[n1] : &:r411_3, m401_5 +# 411| v411_5(void) = NoOp : +#-----| Goto -> Block 3 + +# 413| Block 2 +# 413| r413_1(glval) = VariableAddress[b] : +# 413| m413_2(int[]) = Uninitialized[b] : &:r413_1 +# 413| r413_3(glval) = VariableAddress[n2] : +# 413| r413_4(int) = Load[n2] : &:r413_3, m401_7 +# 413| v413_5(void) = NoOp : +#-----| Goto -> Block 3 + +# 415| Block 3 +# 415| v415_1(void) = NoOp : +# 401| v401_12(void) = ReturnVoid : +# 401| v401_13(void) = AliasedUse : ~m? +# 401| v401_14(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected index 3fc07bf6950..03de47a1ab0 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected @@ -1695,3 +1695,76 @@ ssa.cpp: # 383| v383_13(void) = ReturnValue : &:r383_12, m398_5 # 383| v383_14(void) = AliasedUse : ~m? # 383| v383_15(void) = ExitFunction : + +# 401| void vla(int, int, int, bool) +# 401| Block 0 +# 401| v401_1(void) = EnterFunction : +# 401| mu401_2(unknown) = AliasedDefinition : +# 401| mu401_3(unknown) = InitializeNonLocal : +# 401| r401_4(glval) = VariableAddress[n1] : +# 401| m401_5(int) = InitializeParameter[n1] : &:r401_4 +# 401| r401_6(glval) = VariableAddress[n2] : +# 401| m401_7(int) = InitializeParameter[n2] : &:r401_6 +# 401| r401_8(glval) = VariableAddress[n3] : +# 401| m401_9(int) = InitializeParameter[n3] : &:r401_8 +# 401| r401_10(glval) = VariableAddress[b1] : +# 401| m401_11(bool) = InitializeParameter[b1] : &:r401_10 +# 402| r402_1(glval) = VariableAddress[b] : +# 402| mu402_2(int[]) = Uninitialized[b] : &:r402_1 +# 402| r402_3(glval) = VariableAddress[n1] : +# 402| r402_4(int) = Load[n1] : &:r402_3, m401_5 +# 402| v402_5(void) = NoOp : +# 403| r403_1(glval) = VariableAddress[c] : +# 403| mu403_2(int[][]) = Uninitialized[c] : &:r403_1 +# 403| r403_3(glval) = VariableAddress[n1] : +# 403| r403_4(int) = Load[n1] : &:r403_3, m401_5 +# 403| r403_5(glval) = VariableAddress[n2] : +# 403| r403_6(int) = Load[n2] : &:r403_5, m401_7 +# 403| v403_7(void) = NoOp : +# 405| r405_1(int) = Constant[0] : +# 405| r405_2(glval) = VariableAddress[b] : +# 405| r405_3(int *) = Convert : r405_2 +# 405| r405_4(glval) = CopyValue : r405_3 +# 405| mu405_5(int) = Store[?] : &:r405_4, r405_1 +# 406| r406_1(int) = Constant[1] : +# 406| r406_2(glval) = VariableAddress[b] : +# 406| r406_3(int *) = Convert : r406_2 +# 406| r406_4(int) = Constant[0] : +# 406| r406_5(glval) = PointerAdd[4] : r406_3, r406_4 +# 406| mu406_6(int) = Store[?] : &:r406_5, r406_1 +# 408| r408_1(int) = Constant[0] : +# 408| r408_2(glval) = VariableAddress[c] : +# 408| r408_3(int(*)[]) = Convert : r408_2 +# 408| r408_4(int) = Constant[1] : +# 408| r408_5(int(*)[]) = PointerAdd : r408_3, r408_4 +# 408| r408_6(glval) = CopyValue : r408_5 +# 408| r408_7(int *) = Convert : r408_6 +# 408| r408_8(glval) = CopyValue : r408_7 +# 408| mu408_9(int) = Store[?] : &:r408_8, r408_1 +# 410| r410_1(glval) = VariableAddress[b1] : +# 410| r410_2(bool) = Load[b1] : &:r410_1, m401_11 +# 410| v410_3(void) = ConditionalBranch : r410_2 +#-----| False -> Block 2 +#-----| True -> Block 1 + +# 411| Block 1 +# 411| r411_1(glval) = VariableAddress[b] : +# 411| m411_2(int[]) = Uninitialized[b] : &:r411_1 +# 411| r411_3(glval) = VariableAddress[n1] : +# 411| r411_4(int) = Load[n1] : &:r411_3, m401_5 +# 411| v411_5(void) = NoOp : +#-----| Goto -> Block 3 + +# 413| Block 2 +# 413| r413_1(glval) = VariableAddress[b] : +# 413| m413_2(int[]) = Uninitialized[b] : &:r413_1 +# 413| r413_3(glval) = VariableAddress[n2] : +# 413| r413_4(int) = Load[n2] : &:r413_3, m401_7 +# 413| v413_5(void) = NoOp : +#-----| Goto -> Block 3 + +# 415| Block 3 +# 415| v415_1(void) = NoOp : +# 401| v401_12(void) = ReturnVoid : +# 401| v401_13(void) = AliasedUse : ~m? +# 401| v401_14(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/lambdas/captures/elements.expected b/cpp/ql/test/library-tests/lambdas/captures/elements.expected index 04b6192bdba..83592696f8f 100644 --- a/cpp/ql/test/library-tests/lambdas/captures/elements.expected +++ b/cpp/ql/test/library-tests/lambdas/captures/elements.expected @@ -1,26 +1,9 @@ -| captures.cpp:0:0:0:0 | captures.cpp | -| captures.cpp:1:8:1:8 | declaration of operator= | -| captures.cpp:1:8:1:8 | declaration of operator= | -| captures.cpp:1:8:1:8 | operator= | -| captures.cpp:1:8:1:8 | operator= | -| captures.cpp:1:8:1:10 | definition of foo | -| captures.cpp:1:8:1:10 | foo | -| captures.cpp:2:8:2:8 | a | -| captures.cpp:2:8:2:8 | definition of a | -| captures.cpp:2:14:2:14 | definition of x | -| captures.cpp:2:14:2:14 | x | -| captures.cpp:2:17:6:3 | { ... } | | captures.cpp:3:5:3:5 | (unnamed constructor) | | captures.cpp:3:5:3:5 | (unnamed constructor) | | captures.cpp:3:5:3:5 | (unnamed constructor) | -| captures.cpp:3:5:3:5 | declaration of (unnamed constructor) | -| captures.cpp:3:5:3:5 | declaration of (unnamed constructor) | -| captures.cpp:3:5:3:5 | definition of (unnamed constructor) | -| captures.cpp:3:5:3:5 | definition of operator= | | captures.cpp:3:5:3:5 | operator= | | captures.cpp:3:5:5:5 | [...](...){...} | | captures.cpp:3:5:5:5 | {...} | -| captures.cpp:3:5:5:6 | ExprStmt | | captures.cpp:3:6:3:6 | definition of x | | captures.cpp:3:6:3:6 | x | | captures.cpp:3:6:3:6 | x | @@ -29,7 +12,6 @@ | captures.cpp:3:9:3:9 | definition of (captured this) | | captures.cpp:3:9:3:12 | (captured this) | | captures.cpp:3:9:3:12 | this | -| captures.cpp:3:15:3:15 | definition of operator() | | captures.cpp:3:15:3:15 | operator() | | captures.cpp:3:15:5:5 | { ... } | | captures.cpp:4:7:4:7 | (captured this) | @@ -41,26 +23,14 @@ | captures.cpp:4:9:4:13 | x | | captures.cpp:4:13:4:13 | 1 | | captures.cpp:5:5:5:5 | return ... | -| captures.cpp:6:3:6:3 | return ... | -| captures.cpp:8:8:8:8 | b | -| captures.cpp:8:8:8:8 | definition of b | -| captures.cpp:8:14:8:14 | definition of x | -| captures.cpp:8:14:8:14 | x | -| captures.cpp:8:17:12:3 | { ... } | | captures.cpp:9:5:9:5 | (unnamed constructor) | | captures.cpp:9:5:9:5 | (unnamed constructor) | | captures.cpp:9:5:9:5 | (unnamed constructor) | -| captures.cpp:9:5:9:5 | declaration of (unnamed constructor) | -| captures.cpp:9:5:9:5 | declaration of (unnamed constructor) | -| captures.cpp:9:5:9:5 | definition of (unnamed constructor) | -| captures.cpp:9:5:9:5 | definition of operator= | | captures.cpp:9:5:9:5 | operator= | | captures.cpp:9:5:11:5 | [...](...){...} | | captures.cpp:9:5:11:5 | this | | captures.cpp:9:5:11:5 | x | | captures.cpp:9:5:11:5 | {...} | -| captures.cpp:9:5:11:6 | ExprStmt | -| captures.cpp:9:9:9:9 | definition of operator() | | captures.cpp:9:9:9:9 | operator() | | captures.cpp:9:9:11:5 | { ... } | | captures.cpp:10:7:10:7 | (captured this) | @@ -78,48 +48,23 @@ | captures.cpp:10:9:10:13 | x | | captures.cpp:10:13:10:13 | 1 | | captures.cpp:11:5:11:5 | return ... | -| captures.cpp:12:3:12:3 | return ... | -| captures.cpp:14:15:14:15 | c | -| captures.cpp:14:15:14:15 | definition of c | -| captures.cpp:14:21:14:21 | definition of x | -| captures.cpp:14:21:14:21 | x | -| captures.cpp:14:24:18:3 | { ... } | | captures.cpp:15:5:15:5 | (unnamed constructor) | | captures.cpp:15:5:15:5 | (unnamed constructor) | | captures.cpp:15:5:15:5 | (unnamed constructor) | -| captures.cpp:15:5:15:5 | declaration of (unnamed constructor) | -| captures.cpp:15:5:15:5 | declaration of (unnamed constructor) | -| captures.cpp:15:5:15:5 | definition of (unnamed constructor) | -| captures.cpp:15:5:15:5 | definition of operator= | | captures.cpp:15:5:15:5 | operator= | | captures.cpp:15:5:17:5 | [...](...){...} | | captures.cpp:15:5:17:5 | {...} | -| captures.cpp:15:5:17:6 | ExprStmt | | captures.cpp:15:6:15:6 | definition of x | | captures.cpp:15:6:15:6 | x | | captures.cpp:15:6:15:6 | x | | captures.cpp:15:6:15:6 | x | -| captures.cpp:15:9:15:9 | definition of operator() | | captures.cpp:15:9:15:9 | operator() | | captures.cpp:15:9:17:5 | { ... } | | captures.cpp:16:7:16:7 | call to c | | captures.cpp:16:7:16:11 | ExprStmt | | captures.cpp:16:9:16:9 | 0 | -| captures.cpp:16:13:16:49 | // `x` is unused, but still captured. | | captures.cpp:17:5:17:5 | return ... | -| captures.cpp:18:3:18:3 | return ... | -| captures.cpp:21:5:21:5 | d | -| captures.cpp:21:5:21:5 | definition of d | -| captures.cpp:21:11:21:11 | definition of x | -| captures.cpp:21:11:21:11 | x | -| captures.cpp:21:18:21:18 | definition of y | -| captures.cpp:21:18:21:18 | y | -| captures.cpp:21:21:27:1 | { ... } | -| captures.cpp:22:3:24:4 | declaration | -| captures.cpp:22:8:22:15 | definition of myLambda | -| captures.cpp:22:8:22:15 | myLambda | | captures.cpp:22:18:24:3 | [...](...){...} | -| captures.cpp:22:18:24:3 | initializer for myLambda | | captures.cpp:22:18:24:3 | y | | captures.cpp:22:18:24:3 | {...} | | captures.cpp:22:19:22:19 | (reference dereference) | @@ -131,10 +76,6 @@ | captures.cpp:22:19:22:19 | (unnamed parameter 0) | | captures.cpp:22:19:22:19 | constructor init of field x | | captures.cpp:22:19:22:19 | constructor init of field y | -| captures.cpp:22:19:22:19 | declaration of (unnamed constructor) | -| captures.cpp:22:19:22:19 | definition of (unnamed constructor) | -| captures.cpp:22:19:22:19 | definition of (unnamed constructor) | -| captures.cpp:22:19:22:19 | definition of operator= | | captures.cpp:22:19:22:19 | operator= | | captures.cpp:22:19:22:19 | return ... | | captures.cpp:22:19:22:19 | x | @@ -144,9 +85,7 @@ | captures.cpp:22:23:22:23 | x | | captures.cpp:22:23:22:23 | x | | captures.cpp:22:23:22:23 | x | -| captures.cpp:22:25:22:25 | definition of operator() | | captures.cpp:22:25:22:25 | operator() | -| captures.cpp:22:30:22:30 | definition of z | | captures.cpp:22:30:22:30 | z | | captures.cpp:22:40:24:3 | { ... } | | captures.cpp:23:5:23:21 | return ... | @@ -161,30 +100,7 @@ | captures.cpp:23:16:23:16 | y | | captures.cpp:23:16:23:16 | y | | captures.cpp:23:20:23:20 | z | -| captures.cpp:26:3:26:24 | return ... | -| captures.cpp:26:10:26:17 | (const lambda [] type at line 22, col. 19)... | -| captures.cpp:26:10:26:17 | myLambda | -| captures.cpp:26:18:26:18 | call to operator() | -| captures.cpp:26:19:26:22 | 1000 | -| end_pos.cpp:0:0:0:0 | end_pos.cpp | -| end_pos.cpp:2:1:2:14 | #define OPEN { | -| end_pos.cpp:3:6:3:10 | definition of igFun | -| end_pos.cpp:3:6:3:10 | igFun | -| end_pos.cpp:3:14:12:1 | { ... } | -| end_pos.cpp:4:5:4:8 | OPEN | -| end_pos.cpp:4:5:5:5 | { ... } | -| end_pos.cpp:6:5:6:15 | declaration | -| end_pos.cpp:6:9:6:10 | definition of ii | -| end_pos.cpp:6:9:6:10 | ii | -| end_pos.cpp:6:13:6:14 | 0 | -| end_pos.cpp:6:13:6:14 | initializer for ii | -| end_pos.cpp:7:5:7:69 | // EDG used to not give the initialization for this ii capture an | -| end_pos.cpp:8:5:8:20 | // end location: | -| end_pos.cpp:9:5:11:6 | declaration | -| end_pos.cpp:9:10:9:11 | definition of fp | -| end_pos.cpp:9:10:9:11 | fp | | end_pos.cpp:9:14:11:5 | [...](...){...} | -| end_pos.cpp:9:14:11:5 | initializer for fp | | end_pos.cpp:9:14:11:5 | {...} | | end_pos.cpp:9:15:9:15 | (reference dereference) | | end_pos.cpp:9:15:9:15 | (unnamed constructor) | @@ -192,10 +108,6 @@ | end_pos.cpp:9:15:9:15 | (unnamed constructor) | | end_pos.cpp:9:15:9:15 | (unnamed parameter 0) | | end_pos.cpp:9:15:9:15 | constructor init of field ii | -| end_pos.cpp:9:15:9:15 | declaration of (unnamed constructor) | -| end_pos.cpp:9:15:9:15 | definition of (unnamed constructor) | -| end_pos.cpp:9:15:9:15 | definition of (unnamed constructor) | -| end_pos.cpp:9:15:9:15 | definition of operator= | | end_pos.cpp:9:15:9:15 | ii | | end_pos.cpp:9:15:9:15 | operator= | | end_pos.cpp:9:15:9:15 | return ... | @@ -205,14 +117,10 @@ | end_pos.cpp:9:17:9:18 | (reference to) | | end_pos.cpp:9:17:9:18 | ii | | end_pos.cpp:9:17:9:18 | ii | -| end_pos.cpp:9:20:9:20 | definition of operator() | | end_pos.cpp:9:20:9:20 | operator() | | end_pos.cpp:9:27:11:5 | { ... } | | end_pos.cpp:10:9:10:17 | return ... | | end_pos.cpp:10:16:10:16 | 1 | -| end_pos.cpp:12:1:12:1 | return ... | -| file://:0:0:0:0 | | -| file://:0:0:0:0 | (global namespace) | | file://:0:0:0:0 | (reference to) | | file://:0:0:0:0 | (unnamed parameter 0) | | file://:0:0:0:0 | (unnamed parameter 0) | @@ -229,90 +137,8 @@ | file://:0:0:0:0 | (unnamed parameter 0) | | file://:0:0:0:0 | (unnamed parameter 0) | | file://:0:0:0:0 | (unnamed parameter 0) | -| file://:0:0:0:0 | (unnamed parameter 0) | -| file://:0:0:0:0 | (unnamed parameter 0) | -| file://:0:0:0:0 | (unnamed parameter 0) | -| file://:0:0:0:0 | (unnamed parameter 0) | -| file://:0:0:0:0 | ..()(..) | -| file://:0:0:0:0 | ..()(..) | -| file://:0:0:0:0 | ..(*)(..) | -| file://:0:0:0:0 | ..(*)(..) | -| file://:0:0:0:0 | ..(*)(..) | -| file://:0:0:0:0 | ..(..) | -| file://:0:0:0:0 | __super | -| file://:0:0:0:0 | __va_list_tag | -| file://:0:0:0:0 | __va_list_tag & | -| file://:0:0:0:0 | __va_list_tag && | -| file://:0:0:0:0 | auto | -| file://:0:0:0:0 | const __va_list_tag | -| file://:0:0:0:0 | const __va_list_tag & | -| file://:0:0:0:0 | const foo | -| file://:0:0:0:0 | const foo & | -| file://:0:0:0:0 | const lambda [] type at line 3, col. 5 | -| file://:0:0:0:0 | const lambda [] type at line 3, col. 5 & | -| file://:0:0:0:0 | const lambda [] type at line 3, col. 5 * | -| file://:0:0:0:0 | const lambda [] type at line 9, col. 5 | -| file://:0:0:0:0 | const lambda [] type at line 9, col. 5 & | -| file://:0:0:0:0 | const lambda [] type at line 9, col. 5 * | -| file://:0:0:0:0 | const lambda [] type at line 9, col. 15 | -| file://:0:0:0:0 | const lambda [] type at line 9, col. 15 & | -| file://:0:0:0:0 | const lambda [] type at line 9, col. 15 * | -| file://:0:0:0:0 | const lambda [] type at line 15, col. 5 | -| file://:0:0:0:0 | const lambda [] type at line 15, col. 5 & | -| file://:0:0:0:0 | const lambda [] type at line 15, col. 5 * | -| file://:0:0:0:0 | const lambda [] type at line 22, col. 19 | -| file://:0:0:0:0 | const lambda [] type at line 22, col. 19 & | -| file://:0:0:0:0 | const lambda [] type at line 22, col. 19 * | -| file://:0:0:0:0 | declaration of 1st parameter | -| file://:0:0:0:0 | declaration of 1st parameter | -| file://:0:0:0:0 | declaration of 1st parameter | -| file://:0:0:0:0 | declaration of 1st parameter | -| file://:0:0:0:0 | declaration of 1st parameter | -| file://:0:0:0:0 | declaration of 1st parameter | -| file://:0:0:0:0 | declaration of 1st parameter | -| file://:0:0:0:0 | declaration of 1st parameter | -| file://:0:0:0:0 | declaration of 1st parameter | -| file://:0:0:0:0 | declaration of 1st parameter | -| file://:0:0:0:0 | declaration of 1st parameter | -| file://:0:0:0:0 | declaration of 1st parameter | -| file://:0:0:0:0 | declaration of 1st parameter | -| file://:0:0:0:0 | declaration of 1st parameter | -| file://:0:0:0:0 | declaration of 1st parameter | -| file://:0:0:0:0 | declaration of 1st parameter | -| file://:0:0:0:0 | declaration of 1st parameter | | file://:0:0:0:0 | decltype([...](...){...}) | | file://:0:0:0:0 | decltype([...](...){...}) | | file://:0:0:0:0 | decltype([...](...){...}) | | file://:0:0:0:0 | decltype([...](...){...}) | | file://:0:0:0:0 | decltype([...](...){...}) | -| file://:0:0:0:0 | definition of fp_offset | -| file://:0:0:0:0 | definition of gp_offset | -| file://:0:0:0:0 | definition of overflow_arg_area | -| file://:0:0:0:0 | definition of reg_save_area | -| file://:0:0:0:0 | foo & | -| file://:0:0:0:0 | foo && | -| file://:0:0:0:0 | foo * | -| file://:0:0:0:0 | foo *const | -| file://:0:0:0:0 | fp_offset | -| file://:0:0:0:0 | gp_offset | -| file://:0:0:0:0 | int & | -| file://:0:0:0:0 | lambda [] type at line 3, col. 5 & | -| file://:0:0:0:0 | lambda [] type at line 3, col. 5 && | -| file://:0:0:0:0 | lambda [] type at line 3, col. 5 * | -| file://:0:0:0:0 | lambda [] type at line 9, col. 5 & | -| file://:0:0:0:0 | lambda [] type at line 9, col. 5 && | -| file://:0:0:0:0 | lambda [] type at line 9, col. 5 * | -| file://:0:0:0:0 | lambda [] type at line 9, col. 15 & | -| file://:0:0:0:0 | lambda [] type at line 9, col. 15 && | -| file://:0:0:0:0 | lambda [] type at line 9, col. 15 * | -| file://:0:0:0:0 | lambda [] type at line 15, col. 5 & | -| file://:0:0:0:0 | lambda [] type at line 15, col. 5 && | -| file://:0:0:0:0 | lambda [] type at line 15, col. 5 * | -| file://:0:0:0:0 | lambda [] type at line 22, col. 19 & | -| file://:0:0:0:0 | lambda [] type at line 22, col. 19 && | -| file://:0:0:0:0 | lambda [] type at line 22, col. 19 * | -| file://:0:0:0:0 | operator= | -| file://:0:0:0:0 | operator= | -| file://:0:0:0:0 | overflow_arg_area | -| file://:0:0:0:0 | reg_save_area | -| file://:0:0:0:0 | void * | diff --git a/cpp/ql/test/library-tests/lambdas/captures/elements.ql b/cpp/ql/test/library-tests/lambdas/captures/elements.ql index b7a1275f388..ed93ddc6cbb 100644 --- a/cpp/ql/test/library-tests/lambdas/captures/elements.ql +++ b/cpp/ql/test/library-tests/lambdas/captures/elements.ql @@ -1,8 +1,13 @@ import cpp +predicate interesting(Element e) { + e instanceof LambdaCapture or + e instanceof LambdaExpression or + e = any(LambdaExpression le).getLambdaFunction() or + e = any(LambdaExpression le).getInitializer() or + e instanceof Closure +} + from Element e -where - not e instanceof BuiltInType and - not e instanceof Specifier and - not e instanceof Folder +where interesting(e.getEnclosingElement*()) select e diff --git a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_consistency.expected index 63b6f72905b..d94b3df0bb3 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_consistency.expected @@ -12,12 +12,9 @@ instructionWithoutSuccessor | condition_decls.cpp:26:23:26:24 | Chi: call to BoxedInt | Instruction 'Chi: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:25:6:25:21 | void switch_decl_bind(int) | void switch_decl_bind(int) | | condition_decls.cpp:41:22:41:23 | Chi: call to BoxedInt | Instruction 'Chi: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) | | condition_decls.cpp:48:52:48:53 | Chi: call to BoxedInt | Instruction 'Chi: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) | -| misc.c:171:10:171:13 | Uninitialized: definition of str2 | Instruction 'Uninitialized: definition of str2' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | | ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | | ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | | stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) | -| vla.c:5:9:5:14 | Uninitialized: definition of matrix | Instruction 'Uninitialized: definition of matrix' has no successors in function '$@'. | vla.c:3:12:3:12 | int f(int, char**) | int f(int, char**) | -| vla.c:11:6:11:16 | Chi: vla_typedef | Instruction 'Chi: vla_typedef' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected index a498c7e4b23..6fa6c863aeb 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected @@ -23,29 +23,11 @@ instructionWithoutSuccessor | file://:0:0:0:0 | CompareNE: (bool)... | Instruction 'CompareNE: (bool)...' has no successors in function '$@'. | condition_decls.cpp:15:6:15:17 | void if_decl_bind(int) | void if_decl_bind(int) | | file://:0:0:0:0 | CompareNE: (bool)... | Instruction 'CompareNE: (bool)...' has no successors in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) | | file://:0:0:0:0 | CompareNE: (bool)... | Instruction 'CompareNE: (bool)...' has no successors in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) | -| misc.c:171:10:171:13 | Uninitialized: definition of str2 | Instruction 'Uninitialized: definition of str2' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | -| misc.c:171:15:171:31 | Add: ... + ... | Instruction 'Add: ... + ...' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | -| misc.c:173:14:173:26 | Mul: ... * ... | Instruction 'Mul: ... * ...' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | -| misc.c:173:37:173:39 | Store: array to pointer conversion | Instruction 'Store: array to pointer conversion' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | -| misc.c:174:17:174:22 | CallSideEffect: call to getInt | Instruction 'CallSideEffect: call to getInt' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | -| misc.c:174:30:174:35 | CallSideEffect: call to getInt | Instruction 'CallSideEffect: call to getInt' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | -| misc.c:174:55:174:60 | Store: (char ****)... | Instruction 'Store: (char ****)...' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | | ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | | ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | | stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) | | stmt_expr.cpp:29:11:32:11 | CopyValue: (statement expression) | Instruction 'CopyValue: (statement expression)' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) | | stmt_in_type.cpp:5:53:5:53 | Constant: 1 | Instruction 'Constant: 1' has no successors in function '$@'. | stmt_in_type.cpp:2:6:2:12 | void cpp_fun() | void cpp_fun() | -| vla.c:5:9:5:14 | Uninitialized: definition of matrix | Instruction 'Uninitialized: definition of matrix' has no successors in function '$@'. | vla.c:3:12:3:12 | int f(int, char**) | int f(int, char**) | -| vla.c:5:16:5:19 | Load: argc | Instruction 'Load: argc' has no successors in function '$@'. | vla.c:3:12:3:12 | int f(int, char**) | int f(int, char**) | -| vla.c:5:27:5:33 | BufferReadSideEffect: (const char *)... | Instruction 'BufferReadSideEffect: (const char *)...' has no successors in function '$@'. | vla.c:3:12:3:12 | int f(int, char**) | int f(int, char**) | -| vla.c:11:6:11:16 | InitializeNonLocal: vla_typedef | Instruction 'InitializeNonLocal: vla_typedef' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | -| vla.c:12:33:12:44 | Add: ... + ... | Instruction 'Add: ... + ...' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | -| vla.c:12:50:12:62 | Mul: ... * ... | Instruction 'Mul: ... * ...' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | -| vla.c:13:12:13:14 | Uninitialized: definition of var | Instruction 'Uninitialized: definition of var' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | -| vla.c:14:36:14:47 | Add: ... + ... | Instruction 'Add: ... + ...' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | -| vla.c:14:53:14:65 | Mul: ... * ... | Instruction 'Mul: ... * ...' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | -| vla.c:14:74:14:79 | CallSideEffect: call to getInt | Instruction 'CallSideEffect: call to getInt' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | -| vla.c:14:92:14:94 | Store: (char *)... | Instruction 'Store: (char *)...' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction @@ -65,7 +47,6 @@ useNotDominatedByDefinition | ms_try_except.cpp:19:17:19:21 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | | static_init_templates.cpp:15:1:15:18 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | static_init_templates.cpp:15:1:15:18 | void MyClass::MyClass() | void MyClass::MyClass() | | try_catch.cpp:21:9:21:9 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | try_catch.cpp:19:6:19:23 | void throw_from_nonstmt(int) | void throw_from_nonstmt(int) | -| vla.c:3:31:3:34 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | vla.c:3:12:3:12 | int f(int, char**) | int f(int, char**) | switchInstructionWithoutDefaultEdge notMarkedAsConflated wronglyMarkedAsConflated diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_consistency.expected index 4e67089ba0a..6706c66c0a2 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_consistency.expected @@ -12,12 +12,9 @@ instructionWithoutSuccessor | condition_decls.cpp:26:23:26:24 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:25:6:25:21 | void switch_decl_bind(int) | void switch_decl_bind(int) | | condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) | | condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) | -| misc.c:171:10:171:13 | Uninitialized: definition of str2 | Instruction 'Uninitialized: definition of str2' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | | ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | | ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | | stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) | -| vla.c:5:9:5:14 | Uninitialized: definition of matrix | Instruction 'Uninitialized: definition of matrix' has no successors in function '$@'. | vla.c:3:12:3:12 | int f(int, char**) | int f(int, char**) | -| vla.c:11:6:11:16 | InitializeNonLocal: vla_typedef | Instruction 'InitializeNonLocal: vla_typedef' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction diff --git a/cpp/ql/test/library-tests/templates/extern/declarations.expected b/cpp/ql/test/library-tests/templates/extern/declarations.expected new file mode 100644 index 00000000000..5809f4c87a8 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/extern/declarations.expected @@ -0,0 +1,3 @@ +| extern.cpp:1:20:1:20 | T | +| extern.cpp:2:5:2:5 | f | +| extern.cpp:2:7:2:7 | (unnamed parameter 0) | diff --git a/cpp/ql/test/library-tests/templates/extern/declarations.ql b/cpp/ql/test/library-tests/templates/extern/declarations.ql new file mode 100644 index 00000000000..82739e8cca2 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/extern/declarations.ql @@ -0,0 +1,5 @@ +import cpp + +from Declaration d +where d.getLocation().getFile().getBaseName() != "" +select d diff --git a/cpp/ql/test/library-tests/templates/extern/elements.expected b/cpp/ql/test/library-tests/templates/extern/elements.expected deleted file mode 100644 index 4006eb88484..00000000000 --- a/cpp/ql/test/library-tests/templates/extern/elements.expected +++ /dev/null @@ -1,8 +0,0 @@ -| extern.cpp:0:0:0:0 | extern.cpp | -| extern.cpp:1:20:1:20 | T | -| extern.cpp:1:20:1:20 | definition of T | -| extern.cpp:2:5:2:5 | declaration of f | -| extern.cpp:2:5:2:5 | f | -| extern.cpp:2:7:2:7 | (unnamed parameter 0) | -| extern.cpp:2:7:2:7 | declaration of 1st parameter | -| extern.cpp:4:1:4:58 | // Currently we don't have an element for this declaration | diff --git a/cpp/ql/test/library-tests/templates/extern/elements.ql b/cpp/ql/test/library-tests/templates/extern/elements.ql deleted file mode 100644 index be15ddcd4f4..00000000000 --- a/cpp/ql/test/library-tests/templates/extern/elements.ql +++ /dev/null @@ -1,8 +0,0 @@ -import cpp - -from Element e -where - exists(e.getLocation()) and - not e.getLocation() instanceof UnknownLocation and - not e instanceof Folder -select e diff --git a/csharp/ql/lib/change-notes/2023-03-23-dataflow-renaming.md b/csharp/ql/lib/change-notes/2023-03-23-dataflow-renaming.md new file mode 100644 index 00000000000..54df71fae46 --- /dev/null +++ b/csharp/ql/lib/change-notes/2023-03-23-dataflow-renaming.md @@ -0,0 +1,6 @@ +--- +category: deprecated +--- +* The recently introduced new data flow and taint tracking APIs have had a + number of module and predicate renamings. The old APIs remain in place for + now. diff --git a/csharp/ql/lib/change-notes/2023-03-28-dataflow-rm-footgun.md b/csharp/ql/lib/change-notes/2023-03-28-dataflow-rm-footgun.md new file mode 100644 index 00000000000..82dc0a1d893 --- /dev/null +++ b/csharp/ql/lib/change-notes/2023-03-28-dataflow-rm-footgun.md @@ -0,0 +1,4 @@ +--- +category: fix +--- +* Fixed some accidental predicate visibility in the backwards-compatible wrapper for data flow configurations. In particular `DataFlow::hasFlowPath`, `DataFlow::hasFlow`, `DataFlow::hasFlowTo`, and `DataFlow::hasFlowToExpr` were accidentally exposed in a single version. diff --git a/csharp/ql/lib/semmle/code/asp/WebConfig.qll b/csharp/ql/lib/semmle/code/asp/WebConfig.qll index 34fa9cf3972..49e42fce5c1 100644 --- a/csharp/ql/lib/semmle/code/asp/WebConfig.qll +++ b/csharp/ql/lib/semmle/code/asp/WebConfig.qll @@ -11,6 +11,13 @@ class WebConfigXml extends XmlFile { WebConfigXml() { this.getName().matches("%Web.config") } } +/** + * A `Web.config` transformation file. + */ +class WebConfigReleaseTransformXml extends XmlFile { + WebConfigReleaseTransformXml() { this.getName().matches("%Web.Release.config") } +} + /** DEPRECATED: Alias for WebConfigXml */ deprecated class WebConfigXML = WebConfigXml; @@ -19,6 +26,11 @@ class ConfigurationXmlElement extends XmlElement { ConfigurationXmlElement() { this.getName().toLowerCase() = "configuration" } } +/** A `` tag in an ASP.NET configuration file. */ +class CompilationXmlElement extends XmlElement { + CompilationXmlElement() { this.getName().toLowerCase() = "compilation" } +} + /** DEPRECATED: Alias for ConfigurationXmlElement */ deprecated class ConfigurationXMLElement = ConfigurationXmlElement; @@ -149,3 +161,15 @@ class HttpCookiesElement extends XmlElement { /** DEPRECATED: Alias for isRequireSsl */ deprecated predicate isRequireSSL() { this.isRequireSsl() } } + +/** A `Transform` attribute in a Web.config transformation file. */ +class TransformXmlAttribute extends XmlAttribute { + TransformXmlAttribute() { this.getName().toLowerCase() = "transform" } + + /** + * Gets the list of attribute removals in `Transform=RemoveAttributes(list)`. + */ + string getRemoveAttributes() { + result = this.getValue().regexpCapture("RemoveAttributes\\((.*)\\)", 1).splitAt(",") + } +} diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll index 4067ba6e81c..2792c1d180c 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll @@ -160,7 +160,7 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa /** Provides a query predicate to check the MaD models for validation errors. */ module ModelValidation { private string getInvalidModelInput() { - exists(string pred, AccessPath input, string part | + exists(string pred, AccessPath input, AccessPathToken part | sinkModel(_, _, _, _, _, _, input, _, _) and pred = "sink" or summaryModel(_, _, _, _, _, _, input, _, _, _) and pred = "summary" @@ -169,7 +169,8 @@ module ModelValidation { invalidSpecComponent(input, part) and not part = "" and not (part = "Argument" and pred = "sink") and - not parseArg(part, _) + not parseArg(part, _) and + not part.getName() = ["Field", "Property"] or part = input.getToken(_) and parseParam(part, _) @@ -181,7 +182,7 @@ module ModelValidation { } private string getInvalidModelOutput() { - exists(string pred, string output, string part | + exists(string pred, AccessPath output, AccessPathToken part | sourceModel(_, _, _, _, _, _, output, _, _) and pred = "source" or summaryModel(_, _, _, _, _, _, _, output, _, _) and pred = "summary" @@ -189,7 +190,8 @@ module ModelValidation { ( invalidSpecComponent(output, part) and not part = "" and - not (part = ["Argument", "Parameter"] and pred = "source") + not (part = ["Argument", "Parameter"] and pred = "source") and + not part.getName() = ["Field", "Property"] or invalidIndexComponent(output, part) ) and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlow.qll index 617362ab4f0..865d7b4d6ce 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlow.qll @@ -2,7 +2,7 @@ * Provides an implementation of global (interprocedural) data flow. This file * re-exports the local (intraprocedural) data flow analysis from * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Make` and `MakeWithState` modules. + * through the `Global` and `GlobalWithState` modules. */ private import DataFlowImplCommon @@ -73,10 +73,10 @@ signature module ConfigSig { */ default FlowFeature getAFeature() { none() } - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ default predicate sourceGrouping(Node source, string sourceGroup) { none() } - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ default predicate sinkGrouping(Node sink, string sinkGroup) { none() } /** @@ -166,10 +166,10 @@ signature module StateConfigSig { */ default FlowFeature getAFeature() { none() } - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ default predicate sourceGrouping(Node source, string sourceGroup) { none() } - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ default predicate sinkGrouping(Node sink, string sinkGroup) { none() } /** @@ -182,15 +182,15 @@ signature module StateConfigSig { } /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * Gets the exploration limit for `partialFlow` and `partialFlowRev` * measured in approximate number of interprocedural steps. */ signature int explorationLimitSig(); /** - * The output of a data flow computation. + * The output of a global data flow computation. */ -signature module DataFlowSig { +signature module GlobalFlowSig { /** * A `Node` augmented with a call context (except for sinks) and an access path. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. @@ -203,28 +203,28 @@ signature module DataFlowSig { * The corresponding paths are generated from the end-points and the graph * included in the module `PathGraph`. */ - predicate hasFlowPath(PathNode source, PathNode sink); + predicate flowPath(PathNode source, PathNode sink); /** * Holds if data can flow from `source` to `sink`. */ - predicate hasFlow(Node source, Node sink); + predicate flow(Node source, Node sink); /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowTo(Node sink); + predicate flowTo(Node sink); /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowToExpr(DataFlowExpr sink); + predicate flowToExpr(DataFlowExpr sink); } /** - * Constructs a standard data flow computation. + * Constructs a global data flow computation. */ -module Make implements DataFlowSig { +module Global implements GlobalFlowSig { private module C implements FullStateConfigSig { import DefaultState import Config @@ -233,10 +233,15 @@ module Make implements DataFlowSig { import Impl } +/** DEPRECATED: Use `Global` instead. */ +deprecated module Make implements GlobalFlowSig { + import Global +} + /** - * Constructs a data flow computation using flow state. + * Constructs a global data flow computation using flow state. */ -module MakeWithState implements DataFlowSig { +module GlobalWithState implements GlobalFlowSig { private module C implements FullStateConfigSig { import Config } @@ -244,6 +249,11 @@ module MakeWithState implements DataFlowSig { import Impl } +/** DEPRECATED: Use `GlobalWithState` instead. */ +deprecated module MakeWithState implements GlobalFlowSig { + import GlobalWithState +} + signature class PathNodeSig { /** Gets a textual representation of this element. */ string toString(); diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index c47b0308855..6ea97954bdf 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -8,6 +8,7 @@ private import DataFlowImplCommon private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommonPublic +private import codeql.util.Unit import DataFlow /** @@ -91,10 +92,10 @@ signature module FullStateConfigSig { */ FlowFeature getAFeature(); - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ predicate sourceGrouping(Node source, string sourceGroup); - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ predicate sinkGrouping(Node sink, string sinkGroup); /** @@ -445,11 +446,7 @@ module Impl { } private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } + class Ap = Unit; private class Cc = boolean; @@ -3633,7 +3630,7 @@ module Impl { * The corresponding paths are generated from the end-points and the graph * included in the module `PathGraph`. */ - predicate hasFlowPath(PathNode source, PathNode sink) { + predicate flowPath(PathNode source, PathNode sink) { exists(PathNodeImpl flowsource, PathNodeImpl flowsink | source = flowsource and sink = flowsink | @@ -3643,6 +3640,9 @@ module Impl { ) } + /** DEPRECATED: Use `flowPath` instead. */ + deprecated predicate hasFlowPath = flowPath/2; + private predicate flowsTo(PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink) { flowsource.isSource() and flowsource.getNodeEx().asNode() = source and @@ -3653,17 +3653,26 @@ module Impl { /** * Holds if data can flow from `source` to `sink`. */ - predicate hasFlow(Node source, Node sink) { flowsTo(_, _, source, sink) } + predicate flow(Node source, Node sink) { flowsTo(_, _, source, sink) } + + /** DEPRECATED: Use `flow` instead. */ + deprecated predicate hasFlow = flow/2; /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + predicate flowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + + /** DEPRECATED: Use `flowTo` instead. */ + deprecated predicate hasFlowTo = flowTo/1; /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate flowToExpr(DataFlowExpr sink) { flowTo(exprNode(sink)) } + + /** DEPRECATED: Use `flowToExpr` instead. */ + deprecated predicate hasFlowToExpr = flowToExpr/1; private predicate finalStats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples @@ -4574,7 +4583,7 @@ module Impl { * * To use this in a `path-problem` query, import the module `PartialPathGraph`. */ - predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { + predicate partialFlow(PartialPathNode source, PartialPathNode node, int dist) { partialFlow(source, node) and dist = node.getSourceDistance() } @@ -4594,7 +4603,7 @@ module Impl { * Note that reverse flow has slightly lower precision than the corresponding * forward flow, as reverse flow disregards type pruning among other features. */ - predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { + predicate partialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { revPartialFlow(node, sink) and dist = node.getSinkDistance() } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll index e6bdc74cceb..be70086a93a 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index e6bdc74cceb..be70086a93a 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index e6bdc74cceb..be70086a93a 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index e6bdc74cceb..be70086a93a 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index e6bdc74cceb..be70086a93a 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll index d09fdcfca3e..e6fce328326 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -140,10 +140,8 @@ private module LambdaFlow { } pragma[nomagic] - private TReturnPositionSimple viableReturnPosLambda( - DataFlowCall call, DataFlowCallOption lastCall, ReturnKind kind - ) { - result = TReturnPositionSimple0(viableCallableLambda(call, lastCall), kind) + private TReturnPositionSimple viableReturnPosLambda(DataFlowCall call, ReturnKind kind) { + result = TReturnPositionSimple0(viableCallableLambda(call, _), kind) } private predicate viableReturnPosOutNonLambda( @@ -155,11 +153,12 @@ private module LambdaFlow { ) } + pragma[nomagic] private predicate viableReturnPosOutLambda( - DataFlowCall call, DataFlowCallOption lastCall, TReturnPositionSimple pos, OutNode out + DataFlowCall call, TReturnPositionSimple pos, OutNode out ) { exists(ReturnKind kind | - pos = viableReturnPosLambda(call, lastCall, kind) and + pos = viableReturnPosLambda(call, kind) and out = getAnOutNode(call, kind) ) } @@ -188,6 +187,7 @@ private module LambdaFlow { else any() } + pragma[assume_small_delta] pragma[nomagic] predicate revLambdaFlow0( DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn, @@ -274,6 +274,7 @@ private module LambdaFlow { ) } + pragma[assume_small_delta] pragma[nomagic] predicate revLambdaFlowOut( DataFlowCall lambdaCall, LambdaCallKind kind, TReturnPositionSimple pos, DataFlowType t, @@ -285,7 +286,7 @@ private module LambdaFlow { or // non-linear recursion revLambdaFlowOutLambdaCall(lambdaCall, kind, out, t, toJump, call, lastCall) and - viableReturnPosOutLambda(call, _, pos, out) + viableReturnPosOutLambda(call, pos, out) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll index e6bdc74cceb..be70086a93a 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index a7fc72d0c17..2790ff1465e 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -19,6 +19,7 @@ private import semmle.code.csharp.frameworks.system.Collections private import semmle.code.csharp.frameworks.system.threading.Tasks private import semmle.code.cil.Ssa::Ssa as CilSsa private import semmle.code.cil.internal.SsaImpl as CilSsaImpl +private import codeql.util.Unit /** Gets the callable in which this node occurs. */ DataFlowCallable nodeGetEnclosingCallable(NodeImpl n) { result = n.getEnclosingCallableImpl() } @@ -2163,15 +2164,6 @@ int accessPathLimit() { result = 5 } */ predicate forceHighPrecision(Content c) { c instanceof ElementContent } -/** The unit type. */ -private newtype TUnit = TMkUnit() - -/** The trivial type with a single element. */ -class Unit extends TUnit { - /** Gets a textual representation of this element. */ - string toString() { result = "unit" } -} - class LambdaCallKind = Unit; /** Holds if `creation` is an expression that creates a delegate for `c`. */ @@ -2183,7 +2175,7 @@ predicate lambdaCreation(ExprNode creation, LambdaCallKind kind, DataFlowCallabl e.(AddressOfExpr).getOperand().(CallableAccess).getTarget().getUnboundDeclaration() ] ) and - kind = TMkUnit() + exists(kind) } private class LambdaConfiguration extends ControlFlowReachabilityConfiguration { @@ -2214,7 +2206,7 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { or receiver = call.(SummaryCall).getReceiver() ) and - kind = TMkUnit() + exists(kind) } /** Extra data-flow steps needed for lambda flow analysis. */ diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll index 478328d90bf..6665e0e7480 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll @@ -10,6 +10,7 @@ private import FlowSummaryImplSpecific private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommon +private import codeql.util.Unit /** Provides classes and predicates for defining flow summaries. */ module Public { @@ -109,6 +110,7 @@ module Public { } /** Gets the stack obtained by dropping the first `i` elements, if any. */ + pragma[assume_small_delta] SummaryComponentStack drop(int i) { i = 0 and result = this or diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index e44cd40d872..6f0067517f9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -45,10 +45,6 @@ private Sign certainExprSign(Expr e) { private predicate unknownSign(Expr e) { not exists(certainExprSign(e)) and ( - exists(IntegerLiteral lit | lit = e and not exists(lit.getValue().toInt())) - or - exists(LongLiteral lit | lit = e and not exists(lit.getValue().toFloat())) - or exists(CastingExpr cast, Type fromtyp | cast = e and fromtyp = cast.getSourceType() and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTracking.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTracking.qll index 7f96fe5e6fb..872ac8d4cb8 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTracking.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTracking.qll @@ -33,9 +33,9 @@ private module AddTaintDefaults imp } /** - * Constructs a standard taint tracking computation. + * Constructs a global taint tracking computation. */ -module Make implements DataFlow::DataFlowSig { +module Global implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import DataFlowInternal::DefaultState import Config @@ -48,10 +48,15 @@ module Make implements DataFlow::DataFlowSig { import DataFlowInternal::Impl } +/** DEPRECATED: Use `Global` instead. */ +deprecated module Make implements DataFlow::GlobalFlowSig { + import Global +} + /** - * Constructs a taint tracking computation using flow state. + * Constructs a global taint tracking computation using flow state. */ -module MakeWithState implements DataFlow::DataFlowSig { +module GlobalWithState implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import Config } @@ -62,3 +67,8 @@ module MakeWithState implements DataFlow::DataF import DataFlowInternal::Impl } + +/** DEPRECATED: Use `GlobalWithState` instead. */ +deprecated module MakeWithState implements DataFlow::GlobalFlowSig { + import GlobalWithState +} diff --git a/csharp/ql/lib/semmle/code/csharp/security/cryptography/EncryptionKeyDataFlowQuery.qll b/csharp/ql/lib/semmle/code/csharp/security/cryptography/EncryptionKeyDataFlowQuery.qll index b1bd83d143c..0509066fbbc 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/cryptography/EncryptionKeyDataFlowQuery.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/cryptography/EncryptionKeyDataFlowQuery.qll @@ -64,9 +64,11 @@ class SymmetricEncryptionCreateDecryptorSink extends SymmetricEncryptionKeySink } /** + * DEPRECATED: Use `SymmetricKey` instead. + * * Symmetric Key Data Flow configuration. */ -class SymmetricKeyTaintTrackingConfiguration extends TaintTracking::Configuration { +deprecated class SymmetricKeyTaintTrackingConfiguration extends TaintTracking::Configuration { SymmetricKeyTaintTrackingConfiguration() { this = "SymmetricKeyTaintTracking" } /** Holds if the node is a key source. */ @@ -78,3 +80,22 @@ class SymmetricKeyTaintTrackingConfiguration extends TaintTracking::Configuratio /** Holds if the node is a key sanitizer. */ override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer instanceof KeySanitizer } } + +/** + * Symmetric Key Data Flow configuration. + */ +private module SymmetricKeyConfig implements DataFlow::ConfigSig { + /** Holds if the node is a key source. */ + predicate isSource(DataFlow::Node src) { src instanceof KeySource } + + /** Holds if the node is a symmetric encryption key sink. */ + predicate isSink(DataFlow::Node sink) { sink instanceof SymmetricEncryptionKeySink } + + /** Holds if the node is a key sanitizer. */ + predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof KeySanitizer } +} + +/** + * Symmetric Key Data Flow configuration. + */ +module SymmetricKey = TaintTracking::Global; diff --git a/csharp/ql/lib/semmle/code/csharp/security/cryptography/HardcodedSymmetricEncryptionKey.qll b/csharp/ql/lib/semmle/code/csharp/security/cryptography/HardcodedSymmetricEncryptionKey.qll index e937e69919e..9fdc6dc88be 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/cryptography/HardcodedSymmetricEncryptionKey.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/cryptography/HardcodedSymmetricEncryptionKey.qll @@ -62,9 +62,11 @@ module HardcodedSymmetricEncryptionKey { } /** + * DEPRECATED: Use `HardCodedSymmetricEncryption` instead. + * * A taint-tracking configuration for uncontrolled data in path expression vulnerabilities. */ - class TaintTrackingConfiguration extends TaintTracking::Configuration { + deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration { TaintTrackingConfiguration() { this = "HardcodedSymmetricEncryptionKey" } override predicate isSource(DataFlow::Node source) { source instanceof Source } @@ -85,4 +87,32 @@ module HardcodedSymmetricEncryptionKey { ) } } + + /** + * A taint-tracking configuration for uncontrolled data in path expression vulnerabilities. + */ + private module HardCodedSymmetricEncryptionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof Source } + + predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } + + /** + * Since `CryptographicBuffer` uses native code inside, taint tracking doesn't pass through it. + * Need to create an additional custom step. + */ + predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(MethodCall mc, CryptographicBuffer c | + pred.asExpr() = mc.getAnArgument() and + mc.getTarget() = c.getAMethod() and + succ.asExpr() = mc + ) + } + } + + /** + * A taint-tracking module for uncontrolled data in path expression vulnerabilities. + */ + module HardCodedSymmetricEncryption = TaintTracking::Global; } diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/CodeInjectionQuery.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/CodeInjectionQuery.qll index 4061ab8651c..76a9a495637 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/CodeInjectionQuery.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/CodeInjectionQuery.qll @@ -25,9 +25,11 @@ abstract class Sink extends DataFlow::ExprNode { } abstract class Sanitizer extends DataFlow::ExprNode { } /** + * DEPRECATED: Use `CodeInjection` instead. + * * A taint-tracking configuration for user input treated as code vulnerabilities. */ -class TaintTrackingConfiguration extends TaintTracking::Configuration { +deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration { TaintTrackingConfiguration() { this = "CodeInjection" } override predicate isSource(DataFlow::Node source) { source instanceof Source } @@ -37,6 +39,22 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration { override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } +/** + * A taint-tracking configuration for user input treated as code vulnerabilities. + */ +private module CodeInjectionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof Source } + + predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } +} + +/** + * A taint-tracking module for user input treated as code vulnerabilities. + */ +module CodeInjection = TaintTracking::Global; + /** A source of remote user input. */ class RemoteSource extends Source instanceof RemoteFlowSource { } diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/CommandInjectionQuery.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/CommandInjectionQuery.qll index 82798a34743..265cae5f08a 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/CommandInjectionQuery.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/CommandInjectionQuery.qll @@ -23,9 +23,11 @@ abstract class Sink extends DataFlow::ExprNode { } abstract class Sanitizer extends DataFlow::ExprNode { } /** + * DEPRECATED: Use `CommandInjection` instead. + * * A taint-tracking configuration for command injection vulnerabilities. */ -class TaintTrackingConfiguration extends TaintTracking::Configuration { +deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration { TaintTrackingConfiguration() { this = "CommandInjection" } override predicate isSource(DataFlow::Node source) { source instanceof Source } @@ -35,6 +37,32 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration { override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } +/** + * A taint-tracking configuration for command injection vulnerabilities. + */ +module CommandInjectionConfig implements DataFlow::ConfigSig { + /** + * Holds if `source` is a relevant data flow source. + */ + predicate isSource(DataFlow::Node source) { source instanceof Source } + + /** + * Holds if `sink` is a relevant data flow sink. + */ + predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } +} + +/** + * A taint-tracking module for command injection vulnerabilities. + */ +module CommandInjection = TaintTracking::Global; + /** A source of remote user input. */ class RemoteSource extends Source instanceof RemoteFlowSource { } diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/ConditionalBypassQuery.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/ConditionalBypassQuery.qll index e41a868be48..e919684d751 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/ConditionalBypassQuery.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/ConditionalBypassQuery.qll @@ -30,9 +30,11 @@ abstract class Sink extends DataFlow::ExprNode { abstract class Sanitizer extends DataFlow::ExprNode { } /** + * DEPRECATED: Use `ConditionalBypass` instead. + * * A taint-tracking configuration for user-controlled bypass of sensitive method. */ -class Configuration extends TaintTracking::Configuration { +deprecated class Configuration extends TaintTracking::Configuration { Configuration() { this = "UserControlledBypassOfSensitiveMethodConfiguration" } override predicate isSource(DataFlow::Node source) { source instanceof Source } @@ -42,6 +44,22 @@ class Configuration extends TaintTracking::Configuration { override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } +/** + * A taint-tracking configuration for user-controlled bypass of sensitive method. + */ +private module ConditionalBypassConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof Source } + + predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } +} + +/** + * A taint-tracking module for user-controlled bypass of sensitive method. + */ +module ConditionalBypass = TaintTracking::Global; + /** A source of remote user input. */ class RemoteSource extends Source instanceof RemoteFlowSource { } diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/ExposureOfPrivateInformationQuery.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/ExposureOfPrivateInformationQuery.qll index 2bf409899ee..0b53d9d1ca6 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/ExposureOfPrivateInformationQuery.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/ExposureOfPrivateInformationQuery.qll @@ -23,9 +23,11 @@ abstract class Sink extends DataFlow::ExprNode { } abstract class Sanitizer extends DataFlow::ExprNode { } /** + * DEPRECATED: Use `ExposureOfPrivateInformation` instead. + * * A taint-tracking configuration for private information flowing unencrypted to an external location. */ -class TaintTrackingConfiguration extends TaintTracking::Configuration { +deprecated class TaintTrackingConfiguration extends TaintTracking::Configuration { TaintTrackingConfiguration() { this = "ExposureOfPrivateInformation" } override predicate isSource(DataFlow::Node source) { source instanceof Source } @@ -35,6 +37,22 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration { override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } +/** + * A taint-tracking configuration for private information flowing unencrypted to an external location. + */ +private module ExposureOfPrivateInformationConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof Source } + + predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } +} + +/** + * A taint-tracking module for private information flowing unencrypted to an external location. + */ +module ExposureOfPrivateInformation = TaintTracking::Global; + private class PrivateDataSource extends Source { PrivateDataSource() { this.getExpr() instanceof PrivateDataExpr } } diff --git a/csharp/ql/src/Security Features/CWE-011/ASPNetDebug.ql b/csharp/ql/src/Security Features/CWE-011/ASPNetDebug.ql index 1180d4990f8..308f3eeeac2 100644 --- a/csharp/ql/src/Security Features/CWE-011/ASPNetDebug.ql +++ b/csharp/ql/src/Security Features/CWE-011/ASPNetDebug.ql @@ -19,6 +19,17 @@ import semmle.code.asp.WebConfig from SystemWebXmlElement web, XmlAttribute debugAttribute where - debugAttribute = web.getAChild("compilation").getAttribute("debug") and - not debugAttribute.getValue().toLowerCase() = "false" + exists(CompilationXmlElement compilation | compilation.getParent() = web | + debugAttribute = compilation.getAttribute("debug") and + not debugAttribute.getValue().toLowerCase() = "false" + ) and + not exists( + TransformXmlAttribute attribute, CompilationXmlElement compilation, + WebConfigReleaseTransformXml file + | + compilation = attribute.getElement() and + file = compilation.getFile() and + attribute.getRemoveAttributes() = "debug" and + file.getParentContainer() = web.getFile().getParentContainer() + ) select debugAttribute, "The 'debug' flag is set for an ASP.NET configuration file." diff --git a/csharp/ql/src/Security Features/CWE-078/CommandInjection.ql b/csharp/ql/src/Security Features/CWE-078/CommandInjection.ql index 20a7be1c5b0..41eea7f4238 100644 --- a/csharp/ql/src/Security Features/CWE-078/CommandInjection.ql +++ b/csharp/ql/src/Security Features/CWE-078/CommandInjection.ql @@ -15,9 +15,9 @@ import csharp import semmle.code.csharp.security.dataflow.CommandInjectionQuery -import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph +import CommandInjection::PathGraph -from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink -where c.hasFlowPath(source, sink) +from CommandInjection::PathNode source, CommandInjection::PathNode sink +where CommandInjection::flowPath(source, sink) select sink.getNode(), source, sink, "This command line depends on a $@.", source.getNode(), "user-provided value" diff --git a/csharp/ql/src/Security Features/CWE-078/StoredCommandInjection.ql b/csharp/ql/src/Security Features/CWE-078/StoredCommandInjection.ql index 8fa673f50f3..5f728db8473 100644 --- a/csharp/ql/src/Security Features/CWE-078/StoredCommandInjection.ql +++ b/csharp/ql/src/Security Features/CWE-078/StoredCommandInjection.ql @@ -16,13 +16,19 @@ import csharp import semmle.code.csharp.security.dataflow.flowsources.Stored import semmle.code.csharp.security.dataflow.CommandInjectionQuery -import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph +import StoredCommandInjection::PathGraph -class StoredTaintTrackingConfiguration extends TaintTrackingConfiguration { - override predicate isSource(DataFlow::Node source) { source instanceof StoredFlowSource } +module StoredCommandInjectionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof StoredFlowSource } + + predicate isSink = CommandInjectionConfig::isSink/1; + + predicate isBarrier = CommandInjectionConfig::isBarrier/1; } -from StoredTaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink -where c.hasFlowPath(source, sink) +module StoredCommandInjection = TaintTracking::Global; + +from StoredCommandInjection::PathNode source, StoredCommandInjection::PathNode sink +where StoredCommandInjection::flowPath(source, sink) select sink.getNode(), source, sink, "This command line depends on a $@.", source.getNode(), "stored (potentially user-provided) value" diff --git a/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql b/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql index 17e15fee924..060c6739d82 100644 --- a/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql +++ b/csharp/ql/src/Security Features/CWE-094/CodeInjection.ql @@ -15,9 +15,9 @@ import csharp import semmle.code.csharp.security.dataflow.CodeInjectionQuery -import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph +import CodeInjection::PathGraph -from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink -where c.hasFlowPath(source, sink) +from CodeInjection::PathNode source, CodeInjection::PathNode sink +where CodeInjection::flowPath(source, sink) select sink.getNode(), source, sink, "This code compilation depends on a $@.", source.getNode(), "user-provided value" diff --git a/csharp/ql/src/Security Features/CWE-321/HardcodedEncryptionKey.ql b/csharp/ql/src/Security Features/CWE-321/HardcodedEncryptionKey.ql index 8e516f44d4a..c06768cb2bf 100644 --- a/csharp/ql/src/Security Features/CWE-321/HardcodedEncryptionKey.ql +++ b/csharp/ql/src/Security Features/CWE-321/HardcodedEncryptionKey.ql @@ -15,7 +15,7 @@ import csharp import semmle.code.csharp.security.cryptography.EncryptionKeyDataFlowQuery -import DataFlow::PathGraph +import SymmetricKey::PathGraph /** * The creation of a literal byte array. @@ -38,10 +38,10 @@ class StringLiteralSource extends KeySource { } from - SymmetricKeyTaintTrackingConfiguration keyFlow, DataFlow::PathNode source, - DataFlow::PathNode sink, KeySource srcNode, SymmetricEncryptionKeySink sinkNode + SymmetricKey::PathNode source, SymmetricKey::PathNode sink, KeySource srcNode, + SymmetricEncryptionKeySink sinkNode where - keyFlow.hasFlowPath(source, sink) and + SymmetricKey::flowPath(source, sink) and source.getNode() = srcNode and sink.getNode() = sinkNode select sink.getNode(), source, sink, diff --git a/csharp/ql/src/Security Features/CWE-321/HardcodedSymmetricEncryptionKey.ql b/csharp/ql/src/Security Features/CWE-321/HardcodedSymmetricEncryptionKey.ql index 4de91b9a214..099df293c23 100644 --- a/csharp/ql/src/Security Features/CWE-321/HardcodedSymmetricEncryptionKey.ql +++ b/csharp/ql/src/Security Features/CWE-321/HardcodedSymmetricEncryptionKey.ql @@ -15,10 +15,10 @@ import csharp import semmle.code.csharp.security.cryptography.HardcodedSymmetricEncryptionKey::HardcodedSymmetricEncryptionKey -import DataFlow::PathGraph +import HardCodedSymmetricEncryption::PathGraph -from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink -where c.hasFlowPath(source, sink) +from HardCodedSymmetricEncryption::PathNode source, HardCodedSymmetricEncryption::PathNode sink +where HardCodedSymmetricEncryption::flowPath(source, sink) select sink.getNode(), source, sink, "Hard-coded symmetric $@ is used in symmetric algorithm in " + sink.getNode().(Sink).getDescription() + ".", source.getNode(), "key" diff --git a/csharp/ql/src/Security Features/CWE-359/ExposureOfPrivateInformation.ql b/csharp/ql/src/Security Features/CWE-359/ExposureOfPrivateInformation.ql index ac2f945258e..3a8faf9e4c1 100644 --- a/csharp/ql/src/Security Features/CWE-359/ExposureOfPrivateInformation.ql +++ b/csharp/ql/src/Security Features/CWE-359/ExposureOfPrivateInformation.ql @@ -13,10 +13,10 @@ import csharp import semmle.code.csharp.security.dataflow.ExposureOfPrivateInformationQuery -import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph +import ExposureOfPrivateInformation::PathGraph -from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink -where c.hasFlowPath(source, sink) +from ExposureOfPrivateInformation::PathNode source, ExposureOfPrivateInformation::PathNode sink +where ExposureOfPrivateInformation::flowPath(source, sink) select sink.getNode(), source, sink, "Private data returned by $@ is written to an external location.", source.getNode(), source.getNode().toString() diff --git a/csharp/ql/src/Security Features/CWE-807/ConditionalBypass.ql b/csharp/ql/src/Security Features/CWE-807/ConditionalBypass.ql index 5fc59c13c57..cf55572e6c1 100644 --- a/csharp/ql/src/Security Features/CWE-807/ConditionalBypass.ql +++ b/csharp/ql/src/Security Features/CWE-807/ConditionalBypass.ql @@ -15,9 +15,9 @@ import csharp import semmle.code.csharp.security.dataflow.ConditionalBypassQuery -import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph +import ConditionalBypass::PathGraph -from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink -where config.hasFlowPath(source, sink) +from ConditionalBypass::PathNode source, ConditionalBypass::PathNode sink +where ConditionalBypass::flowPath(source, sink) select sink.getNode(), source, sink, "This condition guards a sensitive $@, but a $@ controls it.", sink.getNode().(Sink).getSensitiveMethodCall(), "action", source.getNode(), "user-provided value" diff --git a/csharp/ql/src/change-notes/2023-03-23-cs-web-debug-binary.md b/csharp/ql/src/change-notes/2023-03-23-cs-web-debug-binary.md new file mode 100644 index 00000000000..d87479c02ce --- /dev/null +++ b/csharp/ql/src/change-notes/2023-03-23-cs-web-debug-binary.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The query `cs/web/debug-binary` now disregards the `debug` attribute in case there is a transformation that removes it. \ No newline at end of file diff --git a/csharp/ql/src/utils/modelgenerator/CaptureDiscardedSummaryModels.ql b/csharp/ql/src/utils/modelgenerator/CaptureDiscardedSummaryModels.ql index 3a2a3454900..dd9648ce2d4 100644 --- a/csharp/ql/src/utils/modelgenerator/CaptureDiscardedSummaryModels.ql +++ b/csharp/ql/src/utils/modelgenerator/CaptureDiscardedSummaryModels.ql @@ -6,7 +6,7 @@ import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import internal.CaptureModels -import internal.CaptureSummaryFlow +import internal.CaptureSummaryFlowQuery from DataFlowTargetApi api, string flow where diff --git a/csharp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql b/csharp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql index 933df8c765a..e4424c54ad5 100644 --- a/csharp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql +++ b/csharp/ql/src/utils/modelgenerator/CaptureNeutralModels.ql @@ -8,7 +8,7 @@ import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import internal.CaptureModels -import internal.CaptureSummaryFlow +import internal.CaptureSummaryFlowQuery from DataFlowTargetApi api, string noflow where diff --git a/csharp/ql/src/utils/modelgenerator/CaptureSinkModels.ql b/csharp/ql/src/utils/modelgenerator/CaptureSinkModels.ql index bba5081c223..d00f49904a5 100644 --- a/csharp/ql/src/utils/modelgenerator/CaptureSinkModels.ql +++ b/csharp/ql/src/utils/modelgenerator/CaptureSinkModels.ql @@ -8,10 +8,6 @@ import internal.CaptureModels -class Activate extends ActiveConfiguration { - override predicate activateToSinkConfig() { any() } -} - from DataFlowTargetApi api, string sink where sink = captureSink(api) select sink order by sink diff --git a/csharp/ql/src/utils/modelgenerator/CaptureSourceModels.ql b/csharp/ql/src/utils/modelgenerator/CaptureSourceModels.ql index f504a291d7e..a4dc734d178 100644 --- a/csharp/ql/src/utils/modelgenerator/CaptureSourceModels.ql +++ b/csharp/ql/src/utils/modelgenerator/CaptureSourceModels.ql @@ -8,10 +8,6 @@ import internal.CaptureModels -class Activate extends ActiveConfiguration { - override predicate activateFromSourceConfig() { any() } -} - from DataFlowTargetApi api, string source where source = captureSource(api) select source order by source diff --git a/csharp/ql/src/utils/modelgenerator/CaptureSummaryModels.ql b/csharp/ql/src/utils/modelgenerator/CaptureSummaryModels.ql index 641c260adf8..920c5b57a74 100644 --- a/csharp/ql/src/utils/modelgenerator/CaptureSummaryModels.ql +++ b/csharp/ql/src/utils/modelgenerator/CaptureSummaryModels.ql @@ -8,7 +8,7 @@ import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import internal.CaptureModels -import internal.CaptureSummaryFlow +import internal.CaptureSummaryFlowQuery from DataFlowTargetApi api, string flow where flow = captureFlow(api) and not api.(FlowSummaryImpl::Public::SummarizedCallable).isManual() diff --git a/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll index 893c62191b3..5ca3ffed782 100644 --- a/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -5,14 +5,6 @@ private import CaptureModelsSpecific -class ActiveConfiguration extends Unit { - predicate activateThroughFlowConfig() { none() } - - predicate activateFromSourceConfig() { none() } - - predicate activateToSinkConfig() { none() } -} - class DataFlowTargetApi extends TargetApiSpecific { DataFlowTargetApi() { isRelevantForDataFlowModels(this) } } @@ -46,6 +38,20 @@ private predicate isRelevantContent(DataFlow::Content c) { DataFlowPrivate::containerContent(c) } +/** + * Gets the MaD string representation of the parameter node `p`. + */ +string parameterNodeAsInput(DataFlow::ParameterNode p) { + result = parameterAccess(p.asParameter()) + or + result = qualifierString() and p instanceof InstanceParameterNode +} + +/** + * Gets the MaD input string representation of `source`. + */ +string asInputArgument(DataFlow::Node source) { result = asInputArgumentSpecific(source) } + /** * Gets the summary model for `api` with `input`, `output` and `kind`. */ @@ -111,61 +117,70 @@ string captureQualifierFlow(TargetApiSpecific api) { private int accessPathLimit() { result = 2 } +private newtype TTaintState = + TTaintRead(int n) { n in [0 .. accessPathLimit()] } or + TTaintStore(int n) { n in [1 .. accessPathLimit()] } + +abstract private class TaintState extends TTaintState { + abstract string toString(); +} + /** * A FlowState representing a tainted read. */ -private class TaintRead extends DataFlow::FlowState { +private class TaintRead extends TaintState, TTaintRead { private int step; - TaintRead() { this = "TaintRead(" + step + ")" and step in [0 .. accessPathLimit()] } + TaintRead() { this = TTaintRead(step) } /** * Gets the flow state step number. */ int getStep() { result = step } + + override string toString() { result = "TaintRead(" + step + ")" } } /** * A FlowState representing a tainted write. */ -private class TaintStore extends DataFlow::FlowState { +private class TaintStore extends TaintState, TTaintStore { private int step; - TaintStore() { this = "TaintStore(" + step + ")" and step in [1 .. accessPathLimit()] } + TaintStore() { this = TTaintStore(step) } /** * Gets the flow state step number. */ int getStep() { result = step } + + override string toString() { result = "TaintStore(" + step + ")" } } /** - * A TaintTracking Configuration used for tracking flow through APIs. + * A data-flow configuration for tracking flow through APIs. * The sources are the parameters of an API and the sinks are the return values (excluding `this`) and parameters. * * This can be used to generate Flow summaries for APIs from parameter to return. */ -private class ThroughFlowConfig extends TaintTracking::Configuration { - ThroughFlowConfig() { - this = "ThroughFlowConfig" and any(ActiveConfiguration ac).activateThroughFlowConfig() - } +module ThroughFlowConfig implements DataFlow::StateConfigSig { + class FlowState = TaintState; - override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { + predicate isSource(DataFlow::Node source, FlowState state) { source instanceof DataFlow::ParameterNode and source.getEnclosingCallable() instanceof DataFlowTargetApi and state.(TaintRead).getStep() = 0 } - override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { + predicate isSink(DataFlow::Node sink, FlowState state) { sink instanceof DataFlowImplCommon::ReturnNodeExt and not isOwnInstanceAccessNode(sink) and not exists(captureQualifierFlow(sink.asExpr().getEnclosingCallable())) and (state instanceof TaintRead or state instanceof TaintStore) } - override predicate isAdditionalTaintStep( - DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, - DataFlow::FlowState state2 + predicate isAdditionalFlowStep( + DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 ) { exists(DataFlowImplCommon::TypedContent tc | DataFlowImplCommon::store(node1, tc, node2, _) and @@ -184,24 +199,28 @@ private class ThroughFlowConfig extends TaintTracking::Configuration { ) } - override predicate isSanitizer(DataFlow::Node n) { + predicate isBarrier(DataFlow::Node n) { exists(Type t | t = n.getType() and not isRelevantType(t)) } - override DataFlow::FlowFeature getAFeature() { + predicate isBarrier(DataFlow::Node node, FlowState state) { none() } + + DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureEqualSourceSinkCallContext } } +private module ThroughFlow = TaintTracking::GlobalWithState; + /** * Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter. */ string captureThroughFlow(DataFlowTargetApi api) { exists( - ThroughFlowConfig config, DataFlow::ParameterNode p, - DataFlowImplCommon::ReturnNodeExt returnNodeExt, string input, string output + DataFlow::ParameterNode p, DataFlowImplCommon::ReturnNodeExt returnNodeExt, string input, + string output | - config.hasFlow(p, returnNodeExt) and + ThroughFlow::flow(p, returnNodeExt) and returnNodeExt.getEnclosingCallable() = api and input = parameterNodeAsInput(p) and output = returnNodeAsOutput(returnNodeExt) and @@ -211,41 +230,37 @@ string captureThroughFlow(DataFlowTargetApi api) { } /** - * A TaintTracking Configuration used for tracking flow through APIs. + * A dataflow configuration used for finding new sources. * The sources are the already known existing sources and the sinks are the API return nodes. * * This can be used to generate Source summaries for an API, if the API expose an already known source * via its return (then the API itself becomes a source). */ -private class FromSourceConfiguration extends TaintTracking::Configuration { - FromSourceConfiguration() { - this = "FromSourceConfiguration" and any(ActiveConfiguration ac).activateFromSourceConfig() - } +module FromSourceConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) } - override predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(DataFlowTargetApi c | sink instanceof DataFlowImplCommon::ReturnNodeExt and sink.getEnclosingCallable() = c ) } - override DataFlow::FlowFeature getAFeature() { - result instanceof DataFlow::FeatureHasSinkCallContext - } + DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSinkCallContext } - override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { isRelevantTaintStep(node1, node2) } } +private module FromSource = TaintTracking::Global; + /** * Gets the source model(s) of `api`, if there is flow from an existing known source to the return of `api`. */ string captureSource(DataFlowTargetApi api) { - exists(DataFlow::Node source, DataFlow::Node sink, FromSourceConfiguration config, string kind | - config.hasFlow(source, sink) and + exists(DataFlow::Node source, DataFlow::Node sink, string kind | + FromSource::flow(source, sink) and ExternalFlow::sourceNode(source, kind) and api = sink.getEnclosingCallable() and isRelevantSourceKind(kind) and @@ -254,35 +269,30 @@ string captureSource(DataFlowTargetApi api) { } /** - * A TaintTracking Configuration used for tracking flow through APIs. + * A dataflow configuration used for finding new sinks. * The sources are the parameters of the API and the fields of the enclosing type. * * This can be used to generate Sink summaries for APIs, if the API propagates a parameter (or enclosing type field) * into an existing known sink (then the API itself becomes a sink). */ -private class PropagateToSinkConfiguration extends TaintTracking::Configuration { - PropagateToSinkConfiguration() { - this = "parameters or fields flowing into sinks" and - any(ActiveConfiguration ac).activateToSinkConfig() - } +module PropagateToSinkConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { apiSource(source) } - override predicate isSource(DataFlow::Node source) { apiSource(source) } + predicate isSink(DataFlow::Node sink) { ExternalFlow::sinkNode(sink, _) } - override predicate isSink(DataFlow::Node sink) { ExternalFlow::sinkNode(sink, _) } + predicate isBarrier(DataFlow::Node node) { sinkModelSanitizer(node) } - override predicate isSanitizer(DataFlow::Node node) { sinkModelSanitizer(node) } - - override DataFlow::FlowFeature getAFeature() { - result instanceof DataFlow::FeatureHasSourceCallContext - } + DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext } } +private module PropagateToSink = TaintTracking::Global; + /** * Gets the sink model(s) of `api`, if there is flow from a parameter to an existing known sink. */ string captureSink(DataFlowTargetApi api) { - exists(DataFlow::Node src, DataFlow::Node sink, PropagateToSinkConfiguration config, string kind | - config.hasFlow(src, sink) and + exists(DataFlow::Node src, DataFlow::Node sink, string kind | + PropagateToSink::flow(src, sink) and ExternalFlow::sinkNode(sink, kind) and api = src.getEnclosingCallable() and isRelevantSinkKind(kind) and diff --git a/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll b/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll index 1fc7636ca65..ea45e8e049b 100644 --- a/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll +++ b/csharp/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll @@ -7,7 +7,6 @@ private import dotnet private import semmle.code.csharp.commons.Util as Util private import semmle.code.csharp.commons.Collections as Collections private import semmle.code.csharp.dataflow.internal.DataFlowDispatch -private import semmle.code.csharp.frameworks.System as System private import semmle.code.csharp.frameworks.system.linq.Expressions import semmle.code.csharp.dataflow.ExternalFlow as ExternalFlow import semmle.code.csharp.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon @@ -19,8 +18,6 @@ module TaintTracking = CS::TaintTracking; class Type = CS::Type; -class Unit = DataFlowPrivate::Unit; - /** * Holds if any of the parameters of `api` are `System.Func<>`. */ @@ -110,7 +107,7 @@ predicate isRelevantType(CS::Type t) { } /** - * Gets the CSV string representation of the qualifier. + * Gets the MaD string representation of the qualifier. */ string qualifierString() { result = "Argument[this]" } @@ -120,14 +117,7 @@ string parameterAccess(CS::Parameter p) { else result = "Argument[" + p.getPosition() + "]" } -/** - * Gets the CSV string representation of the parameter node `p`. - */ -string parameterNodeAsInput(DataFlow::ParameterNode p) { - result = parameterAccess(p.asParameter()) - or - result = qualifierString() and p instanceof DataFlowPrivate::InstanceParameterNode -} +class InstanceParameterNode = DataFlowPrivate::InstanceParameterNode; pragma[nomagic] private CS::Parameter getParameter(DataFlowImplCommon::ReturnNodeExt node, ParameterPosition pos) { @@ -135,7 +125,7 @@ private CS::Parameter getParameter(DataFlowImplCommon::ReturnNodeExt node, Param } /** - * Gets the CSV string representation of the the return node `node`. + * Gets the MaD string representation of the the return node `node`. */ string returnNodeAsOutput(DataFlowImplCommon::ReturnNodeExt node) { if node.getKind() instanceof DataFlowImplCommon::ValueReturnKind @@ -188,9 +178,9 @@ predicate apiSource(DataFlow::Node source) { } /** - * Gets the CSV input string representation of `source`. + * Gets the MaD input string representation of `source`. */ -string asInputArgument(DataFlow::Node source) { +string asInputArgumentSpecific(DataFlow::Node source) { exists(int pos | pos = source.(DataFlow::ParameterNode).getParameter().getPosition() and result = "Argument[" + pos + "]" diff --git a/csharp/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll b/csharp/ql/src/utils/modelgenerator/internal/CaptureSummaryFlowQuery.qll similarity index 95% rename from csharp/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll rename to csharp/ql/src/utils/modelgenerator/internal/CaptureSummaryFlowQuery.qll index 1ed6b9a4850..2b3ce63249c 100644 --- a/csharp/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll +++ b/csharp/ql/src/utils/modelgenerator/internal/CaptureSummaryFlowQuery.qll @@ -1,9 +1,5 @@ private import CaptureModels -private class Activate extends ActiveConfiguration { - override predicate activateThroughFlowConfig() { any() } -} - /** * Capture fluent APIs that return `this`. * Example of a fluent API: diff --git a/java/ql/test/library-tests/frameworks/netty/test.expected b/csharp/ql/test/library-tests/dataflow/external-models/validatemodels.expected similarity index 100% rename from java/ql/test/library-tests/frameworks/netty/test.expected rename to csharp/ql/test/library-tests/dataflow/external-models/validatemodels.expected diff --git a/csharp/ql/test/library-tests/dataflow/external-models/validatemodels.ql b/csharp/ql/test/library-tests/dataflow/external-models/validatemodels.ql new file mode 100644 index 00000000000..d9e073ab78e --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/external-models/validatemodels.ql @@ -0,0 +1,15 @@ +import csharp +import semmle.code.csharp.dataflow.ExternalFlow +import semmle.code.csharp.dataflow.internal.AccessPathSyntax +import ModelValidation + +private predicate getRelevantAccessPath(string path) { + summaryModel(_, _, _, _, _, _, path, _, _, _) or + summaryModel(_, _, _, _, _, _, _, path, _, _) or + sinkModel(_, _, _, _, _, _, path, _, _) or + sourceModel(_, _, _, _, _, _, path, _, _) +} + +private class AccessPathsExternal extends AccessPath::Range { + AccessPathsExternal() { getRelevantAccessPath(this) } +} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-011/ASPNetDebug.expected b/csharp/ql/test/query-tests/Security Features/CWE-011/ASPNetDebug.expected index de43111afa6..8025e4990fd 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-011/ASPNetDebug.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-011/ASPNetDebug.expected @@ -1 +1,2 @@ -| bad/Web.config:4:5:7:7 | debug=true | The 'debug' flag is set for an ASP.NET configuration file. | +| bad1/Web.config:4:5:7:7 | debug=true | The 'debug' flag is set for an ASP.NET configuration file. | +| bad2/Web.config:4:5:7:7 | debug=true | The 'debug' flag is set for an ASP.NET configuration file. | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-011/bad/Web.config b/csharp/ql/test/query-tests/Security Features/CWE-011/bad1/Web.config similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-011/bad/Web.config rename to csharp/ql/test/query-tests/Security Features/CWE-011/bad1/Web.config diff --git a/csharp/ql/test/query-tests/Security Features/CWE-011/bad2/Web.Debug.config b/csharp/ql/test/query-tests/Security Features/CWE-011/bad2/Web.Debug.config new file mode 100644 index 00000000000..d12250bc040 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-011/bad2/Web.Debug.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-011/bad2/Web.config b/csharp/ql/test/query-tests/Security Features/CWE-011/bad2/Web.config new file mode 100644 index 00000000000..ffc04c240fa --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-011/bad2/Web.config @@ -0,0 +1,9 @@ + + + + + + diff --git a/csharp/ql/test/query-tests/Security Features/CWE-011/Web.config b/csharp/ql/test/query-tests/Security Features/CWE-011/good1/Web.config similarity index 100% rename from csharp/ql/test/query-tests/Security Features/CWE-011/Web.config rename to csharp/ql/test/query-tests/Security Features/CWE-011/good1/Web.config diff --git a/csharp/ql/test/query-tests/Security Features/CWE-011/good2/Web.Release.config b/csharp/ql/test/query-tests/Security Features/CWE-011/good2/Web.Release.config new file mode 100644 index 00000000000..d12250bc040 --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-011/good2/Web.Release.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/csharp/ql/test/query-tests/Security Features/CWE-011/good2/Web.config b/csharp/ql/test/query-tests/Security Features/CWE-011/good2/Web.config new file mode 100644 index 00000000000..ffc04c240fa --- /dev/null +++ b/csharp/ql/test/query-tests/Security Features/CWE-011/good2/Web.config @@ -0,0 +1,9 @@ + + + + + + diff --git a/docs/codeql/codeql-language-guides/codeql-for-java.rst b/docs/codeql/codeql-language-guides/codeql-for-java.rst index aa10f481592..dc486b828a9 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-java.rst +++ b/docs/codeql/codeql-language-guides/codeql-for-java.rst @@ -45,4 +45,3 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat - :doc:`Working with source locations `: You can use the location of entities within Java code to look for potential errors. Locations allow you to deduce the presence, or absence, of white space which, in some cases, may indicate a problem. - :doc:`Abstract syntax tree classes for working with Java programs `: CodeQL has a large selection of classes for representing the abstract syntax tree of Java programs. - diff --git a/docs/codeql/codeql-language-guides/codeql-for-javascript.rst b/docs/codeql/codeql-language-guides/codeql-for-javascript.rst index 11a4c5e456c..be3950c53ec 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/codeql-for-javascript.rst @@ -28,8 +28,6 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat - :doc:`Using flow labels for precise data flow analysis `: You can associate flow labels with each value tracked by the flow analysis to determine whether the flow contains potential vulnerabilities. -- :doc:`Specifying remote flow sources for JavaScript `: You can model potential sources of untrusted user input in your code without making changes to the CodeQL standard library by specifying extra remote flow sources in an external file. - - :doc:`Using type tracking for API modeling `: You can track data through an API by creating a model using the CodeQL type-tracking library for JavaScript. - :doc:`Abstract syntax tree classes for working with JavaScript and TypeScript programs `: CodeQL has a large selection of classes for representing the abstract syntax tree of JavaScript and TypeScript programs. diff --git a/docs/codeql/codeql-language-guides/customizing-library-models-for-java.rst b/docs/codeql/codeql-language-guides/customizing-library-models-for-java.rst new file mode 100644 index 00000000000..40ddb14be4d --- /dev/null +++ b/docs/codeql/codeql-language-guides/customizing-library-models-for-java.rst @@ -0,0 +1,417 @@ +.. _customizing-library-models-for-java: + +:orphan: +:nosearch: + +Customizing Library Models for Java +=================================== + +.. include:: ../reusables/beta-note-customizing-library-models.rst + +The Java analysis can be customized by adding library models (summaries, sinks and sources) in data extension files. +A model is a definition of a behavior of a library element, such as a method, that is used to improve the data flow analysis precision by identifying more results. +Most of the security related queries are taint tracking queries that try to find paths from a source of untrusted input to a sink that represents a vulnerability. Sources are the starting points of a taint tracking data flow analysis, and sinks are the end points of a taint tracking data flow analysis. + +Furthermore, the taint tracking queries also need to know how data can flow through elements that are not included in the source code. These are named summaries: they are models of elements that allow us to synthesize the elements flow behavior without having them in the source code. This is especially helpful when using a third party (or the standard) library. + +The models are defined using data extensions where each tuple constitutes a model. +A data extension file for Java is a YAML file in the form: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/java-all + extensible: + data: + - + - + - ... + +Data extensions contribute to the extensible predicates defined in the CodeQL library. For more information on how to define data extensions and extensible predicates as well as how to wire them up, see the :ref:`data-extensions` documentation. + +The CodeQL library for Java exposes the following extensible predicates: + +- **sourceModel**\(package, type, subtypes, name, signature, ext, output, kind, provenance). This is used for **source** models. +- **sinkModel**\(package, type, subtypes, name, signature, ext, input, kind, provenance). This is used for **sink** models. +- **summaryModel**\(package, type, subtypes, name, signature, ext, input, output, kind, provenance). This is used for **summary** models. +- **neutralModel**\(package, type, name, signature, provenance). This is used for **neutral** models, which only have minor impact on the data flow analysis. + +The extensible predicates are populated using data extensions specified in YAML files. + +In the sections below, we will provide examples of how to add tuples to the different extensible predicates. +The extensible predicates are used to customize and improve the existing data flow queries, by providing sources, sinks, and flow through (summaries) for library elements. +The :ref:`reference-material` section will provide details on the *mini DSLs* that define models for each extensible predicate. + +Example: Taint sink in the **java.sql** package +------------------------------------------------ + +In this example we will show how to model the argument of the **execute** method as a SQL injection sink. +This is the **execute** method in the **Statement** class, which is located in the **java.sql** package. +Note that this sink is already added to the CodeQL Java analysis. + +.. code-block:: java + + public static void taintsink(Connection conn, String query) throws SQLException { + Statement stmt = conn.createStatement(); + stmt.execute(query); // The argument to this method is a SQL injection sink. + } + +We need to add a tuple to the **sinkModel**\(package, type, subtypes, name, signature, ext, input, kind, provenance) extensible predicate. To do this, add the following to a data extension file: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["java.sql", "Statement", True, "execute", "(String)", "", "Argument[0]", "sql", "manual"] + + +Since we are adding a new sink, we need to add a tuple to the **sinkModel** extensible predicate. +The first five values identify the callable (in this case a method) to be modeled as a sink. + +- The first value **java.sql** is the package name. +- The second value **Statement** is the name of the class (type) that contains the method. +- The third value **True** is a flag that indicates whether or not the sink also applies to all overrides of the method. +- The fourth value **execute** is the method name. +- The fifth value **(String)** is the method input type signature. + +The sixth value should be left empty and is out of scope for this documentation. +The remaining values are used to define the **access path**, the **kind**, and the **provenance** (origin) of the sink. + +- The seventh value **Argument[0]** is the **access path** to the first argument passed to the method, which means that this is the location of the sink. +- The eighth value **sql** is the kind of the sink. The sink kind is used to define the queries where the sink is in scope. In this case - the SQL injection queries. +- The ninth value **manual** is the provenance of the sink, which is used to identify the origin of the sink. + +Example: Taint source from the **java.net** package +---------------------------------------------------- +In this example we show how to model the return value from the **getInputStream** method as a **remote** source. +This is the **getInputStream** method in the **Socket** class, which is located in the **java.net** package. +Note that this source is already added to the CodeQL Java analysis. + +.. code-block:: java + + public static void tainted(Socket socket) throws IOException { + InputStream stream = socket.getInputStream(); // The return value of this method is a remote source of taint. + ... + } + +We need to add a tuple to the **sourceModel**\(package, type, subtypes, name, signature, ext, output, kind, provenance) extensible predicate. To do this, add the following to a data extension file: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/java-all + extensible: sourceModel + data: + - ["java.net", "Socket", False, "getInputStream", "()", "", "ReturnValue", "remote", "manual"] + + +Since we are adding a new source, we need to add a tuple to the **sourceModel** extensible predicate. +The first five values identify the callable (in this case a method) to be modeled as a source. + +- The first value **java.net** is the package name. +- The second value **Socket** is the name of the class (type) that contains the source. +- The third value **False** is a flag that indicates whether or not the source also applies to all overrides of the method. +- The fourth value **getInputStream** is the method name. +- The fifth value **()** is the method input type signature. + +The sixth value should be left empty and is out of scope for this documentation. +The remaining values are used to define the **access path**, the **kind**, and the **provenance** (origin) of the source. + +- The seventh value **ReturnValue** is the access path to the return of the method, which means that it is the return value that should be considered a source of tainted input. +- The eighth value **remote** is the kind of the source. The source kind is used to define the queries where the source is in scope. **remote** applies to many of the security related queries as it means a remote source of untrusted data. As an example the SQL injection query uses **remote** sources. +- The ninth value **manual** is the provenance of the source, which is used to identify the origin of the source. + +Example: Add flow through the **concat** method +------------------------------------------------ +In this example we show how to model flow through a method for a simple case. +This pattern covers many of the cases where we need to define flow through a method. +Note that the flow through the **concat** method is already added to the CodeQL Java analysis. + +.. code-block:: java + + public static void taintflow(String s1, String s2) { + String t = s1.concat(s2); // There is taint flow from s1 and s2 to t. + ... + } + +We need to add tuples to the **summaryModel**\(package, type, subtypes, name, signature, ext, input, output, kind, provenance) extensible predicate. To do this, add the following to a data extension file: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["java.lang", "String", False, "concat", "(String)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["java.lang", "String", False, "concat", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + +Reasoning: + +Since we are adding flow through a method, we need to add tuples to the **summaryModel** extensible predicate. +Each tuple defines flow from one argument to the return value. +The first row defines flow from the qualifier (**s1** in the example) to the return value (**t** in the example) and the second row defines flow from the first argument (**s2** in the example) to the return value (**t** in the example). + +The first five values identify the callable (in this case a method) to be modeled as a summary. +These are the same for both of the rows above as we are adding two summaries for the same method. + +- The first value **java.lang** is the package name. +- The second value **String** is the class (type) name. +- The third value **False** is a flag that indicates whether or not the summary also applies to all overrides of the method. +- The fourth value **concat** is the method name. +- The fifth value **(String)** is the method input type signature. + +The sixth value should be left empty and is out of scope for this documentation. +The remaining values are used to define the **access path**, the **kind**, and the **provenance** (origin) of the summary. + +- The seventh value is the access path to the input (where data flows from). **Argument[this]** is the access path to the qualifier (**s1** in the example) and **Argument[0]** is the access path to the first argument (**s2** in the example). +- The eighth value **ReturnValue** is the access path to the output (where data flows to), in this case **ReturnValue**, which means that the input flows to the return value. +- The ninth value **taint** is the kind of the flow. **taint** means that taint is propagated through the call. +- The tenth value **manual** is the provenance of the summary, which is used to identify the origin of the summary. + +Example: Add flow through the **map** method +--------------------------------------------- +In this example, we will see a more complex example of modeling flow through a method. +This pattern shows how to model flow through higher order methods and collection types. +Note that the flow through the **map** method is already added to the CodeQL Java analysis. + +.. code-block:: java + + public static void taintflow(Stream s) { + Stream l = s.map(e -> e.concat("\n")); + ... + } + +To do this, add the following to a data extension file: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["java.util.stream", "Stream", True, "map", "(Function)", "", "Argument[this].Element", "Argument[0].Parameter[0]", "value", "manual"] + - ["java.util.stream", "Stream", True, "map", "(Function)", "", "Argument[0].ReturnValue", "ReturnValue.Element", "value", "manual"] + + +Since we are adding flow through a method, we need to add tuples to the **summaryModel** extensible predicate. +Each tuple defines part of the flow that comprises the total flow through the **map** method. +The first five values identify the callable (in this case a method) to be modeled as a summary. +These are the same for both of the rows above as we are adding two summaries for the same method. + +- The first value **java.util.stream** is the package name. +- The second value **Stream** is the class (type) name. +- The third value **True** is a flag that indicates whether or not the summary also applies to all overrides of the method. +- The fourth value **map** is the method name. +- The fifth value **Function** is the method input type signature. + +The sixth value should be left empty and is out of scope for this documentation. +The remaining values are used to define the **access path**, the **kind**, and the **provenance** (origin) of the summary definition. + +- The seventh value is the access path to the **input** (where data flows from). +- The eighth value is the access path to the **output** (where data flows to). + +For the first row: + +- The seventh value is **Argument[this].Element**, which is the access path to the elements of the qualifier (the elements of the stream **s** in the example). +- The eight value is **Argument[0].Parameter[0]**, which is the access path to the first parameter of the **Function** argument of **map** (the lambda parameter **e** in the example). + +For the second row: + +- The seventh value is **Argument[0].ReturnValue**, which is the access path to the return value of the **Function** argument of **map** (the return value of the lambda in the example). +- The eighth value is **ReturnValue.Element**, which is the access path to the elements of the return value of **map** (the elements of the stream **l** in the example). + +For the remaining values for both rows: + +- The ninth value **value** is the kind of the flow. **value** means that the value is preserved. +- The tenth value **manual** is the provenance of the summary, which is used to identify the origin of the summary. + +That is, the first row models that there is value flow from the elements of the qualifier stream into the first argument of the function provided to **map** and the second row models that there is value flow from the return value of the function to the elements of the stream returned from **map**. + +Example: Add a **neutral** method +---------------------------------- +In this example we will show how to model the **now** method as being neutral. +A neutral model is used to define that there is no flow through a method. +Note that the neutral model for the **now** method is already added to the CodeQL Java analysis. + +.. code-block:: java + + public static void taintflow() { + Instant t = Instant.now(); // There is no flow from now to t. + ... + } + +We need to add a tuple to the **neutralModel**\(package, type, name, signature, provenance) extensible predicate. To do this, add the following to a data extension file: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/java-all + extensible: neutralModel + data: + - ["java.time", "Instant", "now", "()", "manual"] + + +Since we are adding a neutral model, we need to add tuples to the **neutralModel** extensible predicate. +The first five values identify the callable (in this case a method) to be modeled as a neutral and the fifth value is the provenance (origin) of the neutral. + +- The first value **java.time** is the package name. +- The second value **Instant** is the class (type) name. +- The third value **now** is the method name. +- The fourth value **()** is the method input type signature. +- The fifth value **manual** is the provenance of the neutral. + +.. _reference-material: + +Reference material +------------------ + +The following sections provide reference material for extensible predicates. +This includes descriptions of each of the arguments (e.g. access paths, kinds and provenance). + +Extensible predicates +--------------------- + +Below is a description of the columns for each extensible predicate. +Sources, sinks, summaries and neutrals are commonly known as models. +The semantics of many of the columns of the extensible predicates are shared. + +The shared columns are: + +- **package**: Name of the package containing the element(s) to be modeled. +- **type**: Name of the type containing the element(s) to be modeled. +- **subtypes**: A boolean flag indicating whether the model should also apply to all overrides of the selected element(s). +- **name**: Name of the element (optional). If this is left blank, it means all elements matching the previous selection criteria. +- **signature**: Type signature of the selected element (optional). If this is left blank, it means all elements matching the previous selection criteria. +- **ext**: Specifies additional API-graph-like edges (mostly empty) and out of scope for this document. +- **provenance**: Provenance (origin) of the model definition. + +The columns **package**, **type**, **subtypes**, **name**, and **signature** are used to select the element(s) that the model applies to. + +The :ref:`access-paths` section describes how access paths are composed. +This is the most complicated part of the extensible predicates and the **mini DSL** for access paths is shared across all extensible predicates. + +sourceModel(package, type, subtypes, name, signature, ext, output, kind, provenance) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Taint source. Most taint tracking queries will use all sources added to this extensible predicate regardless of their kind. + +- **output**: Access path to the source, where the possibly tainted data flows from. +- **kind**: Kind of the source. +- **provenance**: Provenance (origin) of the source definition. + +As most sources are used by all taint tracking queries there are only a few different source kinds. +The following source kinds are supported: + +- **remote**: A remote source of possibly tainted data. This is the most common kind for a source. Sources of this kind are used for almost all taint tracking queries. + +Below is an enumeration of the remaining source kinds, but they are out of scope for this documentation: + +- **contentprovider**, **android-widget**, **android-external-storage-dir**. + +sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Taint sink. As opposed to source kinds, there are many different kinds of sinks as these tend to be more query specific. + +- **input**: Access path to the sink, where we want to check if tainted data can flow into. +- **kind**: Kind of the sink. + +The following sink kinds are supported: + +- **sql**: A SQL injection vulnerability sink. +- **xss**: A cross-site scripting vulnerability sink. +- **logging**: A log output sink. + +Below is an enumeration of the remaining sinks, but they are out of scope for this documentation: + +- **open-url**, **jndi-injection**, **ldap**, **jdbc-url** +- **mvel**, **xpath**, **groovy**, **ognl-injection** +- **intent-start**, **pending-intent-sent**, **url-open-stream**, **url-redirect** +- **create-file**, **read-file**, **write-file**, **set-hostname-verifier** +- **header-splitting**, **information-leak**, **xslt**, **jexl** +- **bean-validation**, **ssti**, **fragment-injection**, **regex-use[**\ `arg`\ **]** + +summaryModel(package, type, subtypes, name, signature, ext, input, output, kind, provenance) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Flow through (summary). This extensible predicate is used to model flow through elements. + +- **input**: Access path to the input of the element (where data will flow from to the output). +- **output**: Access path to the output of the element (where data will flow to from the input). +- **kind**: Kind of the flow through. +- **provenance**: Provenance (origin) of the flow through. + +The following kinds are supported: + +- **taint**: This means the output is not necessarily equal to the input, but it was derived from the input in an unrestrictive way. An attacker who controls the input will have significant control over the output as well. +- **value**: This means that the output equals the input or a copy of the input such that all of its properties are preserved. + +neutralModel(package, type, name, signature, provenance) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This extensible predicate is not typically needed externally, but included here for completeness. +It only has minor impact on the data flow analysis. +Manual neutrals are considered high confidence dispatch call targets and can reduce the number of dispatch call targets during data flow analysis (a performance optimization). + +- **provenance**: Provenance (origin) of the flow through. + +.. _access-paths: + +Access paths +------------ +The **input**, and **output** columns consist of a **.**-separated list of components, which is evaluated from left to right, with each step selecting a new set of values derived from the previous set of values. + +The following components are supported: + +- **Argument[**\ `n`\ **]** selects the argument at index `n` (zero-indexed). +- **Argument[**\ `this`\ **]** selects the qualifier (instance parameter). +- **Argument[**\ `n1..n2`\ **]** selects the arguments in the given range (both ends included). +- **Parameter[**\ `n`\ **]** selects the parameter at index `n` (zero-indexed). +- **Parameter[**\ `n1..n2`\ **]** selects the parameters in the given range (both ends included). +- **ReturnValue** selects the return value. +- **Field[**\ `name`\ **]** selects the field with the fully qualified name `name`. +- **SyntheticField[**\ `name`\ **]** selects the synthetic field with name `name`. +- **SyntheticGlobal[**\ `name`\ **]** selects the synthetic global with name `name`. +- **ArrayElement** selects the elements of an array. +- **Element** selects the elements of a collection-like container. +- **MapKey** selects the element keys of a map. +- **MapValue** selects the element values of a map. + +Provenance +---------- + +The **provenance** column is used to specify the provenance (origin) of the model definition and how the model was verified. +The following values are supported: + +- **manual**: The model was manually created and added to the extensible predicate. + +or values in the form **origin-verification**, where origin is one of: + +- **ai**: The model was generated by AI. +- **df**: The model was generated by the dataflow model generator. +- **tb**: The model was generated by the type based model generator. +- **hq**: The model was generated using a heuristic query. + +and verification is one of: + +- **manual**: The model was verified by a human. +- **generated**: The model was generated, but not verified by a human. + +The provenance is used to distinguish between models that are manually added (or verified) to the extensible predicate and models that are automatically generated. +Furthermore, it impacts the data flow analysis in the following way: + +- A **manual** model takes precedence over **generated** models. If a **manual** model exists for an element then all **generated** models are ignored. +- A **generated** model is ignored during analysis, if the source code of the element it is modeling is available. + +That is, generated models are less trusted than manual models and only used if neither source code nor a manual model is available. + + +.. include:: ../reusables/data-extensions.rst \ No newline at end of file diff --git a/docs/codeql/codeql-language-guides/customizing-library-models-for-javascript.rst b/docs/codeql/codeql-language-guides/customizing-library-models-for-javascript.rst new file mode 100644 index 00000000000..a50b6b11a85 --- /dev/null +++ b/docs/codeql/codeql-language-guides/customizing-library-models-for-javascript.rst @@ -0,0 +1,479 @@ +.. _customizing-library-models-for-javascript: + +:orphan: +:nosearch: + +Customizing Library Models for JavaScript +========================================= + +.. include:: ../reusables/beta-note-customizing-library-models.rst + +JavaScript analysis can be customized by adding library models in data extension files. + +A data extension for JavaScript is a YAML file of the form: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/javascript-all + extensible: + data: + - + - + - ... + +The CodeQL library for JavaScript exposes the following extensible predicates: + +- **sourceModel**\(type, path, kind) +- **sinkModel**\(type, path, kind) +- **typeModel**\(type1, type2, path) +- **summaryModel**\(type, path, input, output, kind) + +See the [CLI documentation for how to load and use data extensions in a CodeQL evaluation run](https://docs.google.com/document/d/14IYCHX8wWuU-HTvJ2gPSdXQKHKYbWCHQKOgn8oLaa80/edit#heading=h.m0v53lpi6w2n) (internal access required). + +We'll explain how to use these using a few examples, and provide some reference material at the end of this article. + +Example: Taint sink in the 'execa' package +------------------------------------------ + +In this example, we'll show how to add the following argument, passed to **execa**, as a command-line injection sink: + +.. code-block:: js + + import { shell } from "execa"; + shell(cmd); // <-- add 'cmd' as a taint sink + +Note that this sink is already recognized by the CodeQL JS analysis, but for this example, you could use the following data extension: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/javascript-all + extensible: sinkModel + data: + - ["execa", "Member[shell].Argument[0]", "command-line-injection"] + + +- Since we're adding a new sink, we add a tuple to the **sinkModel** extensible predicate. +- The first column, **"execa"**, identifies a set of values from which to begin the search for the sink. + The string **"execa"** means we start at the places where the codebase imports the NPM package **execa**. +- The second column is an access path that is evaluated from left to right, starting at the values that were identified by the first column. + + - **Member[shell]** selects accesses to the **shell** member of the **execa** package. + - **Argument[0]** selects the first argument to calls to that member. + +- **command-line-injection** indicates that this is considered a sink for the command injection query. + +Example: Taint sources from window 'message' events +--------------------------------------------------- + +In this example, we'll show how the **event.data** expression below could be marked as a remote flow source: + +.. code-block:: js + + window.addEventListener("message", function (event) { + let data = event.data; // <-- add 'event.data' as a taint source + }); + +Note that this source is already known by the CodeQL JS analysis, but for this example, you could use the following data extension: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/javascript-all + extensible: sourceModel + data: + - [ + "global", + "Member[addEventListener].Argument[1].Parameter[0].Member[data]", + "remote", + ] + + +- Since we're adding a new taint source, we add a tuple to the **sourceModel** extensible predicate. +- The first column, **"global"**, begins the search at references to the global object (also known as **window** in browser contexts). This is a special JavaScript object that contains all global variables and methods. +- **Member[addEventListener]** selects accesses to the **addEventListener** member. +- **Argument[1]** selects the second argument of calls to that member (the argument containing the callback). +- **Parameter[0]** selects the first parameter of the callback (the parameter named **event**). +- **Member[data]** selects accesses to the **data** property of the event object. +- Finally, the kind **remote** indicates that this is considered a source of remote flow. + +In the next section, we'll show how to restrict the model to recognize events of a specific type. + +Continued example: Restricting the event type +--------------------------------------------- + +The model above treats all events as sources of remote flow, not just **message** events. +For example, it would also pick up this irrelevant source: + +.. code-block:: js + + window.addEventListener("onclick", function (event) { + let data = event.data; // <-- 'event.data' became a spurious taint source + }); + + +We can refine the model by adding the **WithStringArgument** component to restrict the set of calls being considered: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/javascript-all + extensible: sourceModel + data: + - [ + "global", + "Member[addEventListener].WithStringArgument[0=message].Argument[1].Parameter[0].Member[data]", + "remote", + ] + +The **WithStringArgument[0=message]** component here selects the subset of calls to **addEventListener** where the first argument is a string literal with the value **"message"**. + +Example: Using types to add MySQL injection sinks +------------------------------------------------- + +In this example, we'll show how to add the following SQL injection sink: + +.. code-block:: ts + + import { Connection } from "mysql"; + + function submit(connection: Connection, q: string) { + connection.query(q); // <-- add 'q' as a SQL injection sink + } + +We can recognize this using the following extension: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/javascript-all + extensible: sinkModel + data: + - ["mysql.Connection", "Member[query].Argument[0]", "sql-injection"] + + +- The first column, **"mysql.Connection"**, begins the search at any expression whose value is known to be an instance of + the **Connection** type from the **mysql** package. This will select the **connection** parameter above because of its type annotation. +- **Member[query]** selects the **query** member from the connection object. +- **Argument[0]** selects the first argument of a call to that member. +- **sql-injection** indicates that this is considered a sink for the SQL injection query. + +This works in this example because the **connection** parameter has a type annotation that matches what the model is looking for. + +Note that there is a significant difference between the following two rows: + +.. code-block:: yaml + + data: + - ["mysql.Connection", "", ...] + - ["mysql", "Member[Connection]", ...] + +The first row matches instances of **mysql.Connection**, which are objects that encapsulate a MySQL connection. +The second row would match something like **require('mysql').Connection**, which is not itself a connection object. + +In the next section, we'll show how to generalize the model to handle the absence of type annotations. + +Continued example: Dealing with untyped code +-------------------------------------------- + +Suppose we want the model from above to detect the sink in this snippet: + +.. code-block:: js + + import { getConnection } from "@example/db"; + let connection = getConnection(); + connection.query(q); // <-- add 'q' as a SQL injection sink + +There is no type annotation on **connection**, and there is no indication of what **getConnection()** returns. +Using a **typeModel** tuple we can tell our model that this function returns an instance of **mysql.Connection**: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/javascript-all + extensible: typeModel + data: + - ["mysql.Connection", "@example/db", "Member[getConnection].ReturnValue"] + + +- Since we're providing type information, we add a tuple to the **typeModel** extensible predicate. +- The first column, **"mysql.Connection"**, names the type that we're adding a new definition for. +- The second column, **"@example/db"**, begins the search at imports of the hypothetical NPM package **@example/db**. +- **Member[getConnection]** selects references to the **getConnection** member from that package. +- **ReturnValue** selects the return value from a call to that member. + +The new model states that the return value of **getConnection()** has type **mysql.Connection**. +Combining this with the sink model we added earlier, the sink in the example is detected by the model. + +The mechanism used here is how library models work for both TypeScript and plain JavaScript. +A good library model contains **typeModel** tuples to ensure it works even in codebases without type annotations. +For example, the **mysql** model that is included with the CodeQL JS analysis includes this type definition (among many others): + +.. code-block:: yaml + + - ["mysql.Connection", "mysql", "Member[createConnection].ReturnValue"] + +Example: Adding flow through 'decodeURIComponent' +------------------------------------------------- + +In this example, we'll show how to add flow through calls to `decodeURIComponent`: + +.. code-block:: js + + let y = decodeURIComponent(x); // add taint flow from 'x' to 'y' + +Note that this flow is already recognized by the CodeQL JS analysis, but for this example, you could use the following data extension: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/javascript-all + extensible: summaryModel + data: + - [ + "global", + "Member[decodeURIComponent]", + "Argument[0]", + "ReturnValue", + "taint", + ] + + +- Since we're adding flow through a function call, we add a tuple to the **summaryModel** extensible predicate. +- The first column, **"global"**, begins the search for relevant calls at references to the global object. + In JavaScript, global variables are properties of the global object, so this lets us access global variables or functions. +- The second column, **Member[decodeURIComponent]**, is a path leading to the function calls we wish to model. + In this case, we select references to the **decodeURIComponent** member from the global object, that is, + the global variable named **decodeURIComponent**. +- The third column, **Argument[0]**, indicates the input of the flow. In this case, the first argument to the function call. +- The fourth column, **ReturnValue**, indicates the output of the flow. In this case, the return value of the function call. +- The last column, **taint**, indicates the kind of flow to add. The value **taint** means the output is not necessarily equal + to the input, but was derived from the input in a taint-preserving way. + +Example: Adding flow through 'underscore.forEach' +------------------------------------------------- + +In this example, we'll show how to add flow through calls to **forEach** from the **underscore** package: + +.. code-block:: js + + require('underscore').forEach([x, y], (v) => { ... }); // add value flow from 'x' and 'y' to 'v' + +Note that this flow is already recognized by the CodeQL JS analysis, but for this example, you could use the following data extension: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/javascript-all + extensible: summaryModel + data: + - [ + "underscore", + "Member[forEach]", + "Argument[0].ArrayElement", + "Argument[1].Parameter[0]", + "value", + ] + + +- Since we're adding flow through a function call, we add a tuple to the **summaryModel** extensible predicate. +- The first column, **"underscore"**, begins the search for relevant calls at places where the **underscore** package is imported. +- The second column, **Member[forEach]**, selects references to the **forEach** member from the **underscore** package. +- The third column specifies the input of the flow: + + - **Argument[0]** selects the first argument of **forEach**, which is the array being iterated over. + - **ArrayElement** selects the elements of that array (the expressions **x** and **y**). + +- The fourth column specifies the output of the flow: + + - **Argument[1]** selects the second argument of **forEach** (the argument containing the callback function). + - **Parameter[0]** selects the first parameter of the callback function (the parameter named **v**). + +- The last column, **value**, indicates the kind of flow to add. The value **value** means the input value is unchanged as + it flows to the output. + +Reference material +------------------ + +The following sections provide reference material for extensible predicates, access paths, types, and kinds. + +Extensible predicates +--------------------- + +sourceModel(type, path, kind) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Adds a new taint source. Most taint-tracking queries will use the new source. + +- **type**: Name of a type from which to evaluate **path**. +- **path**: Access path leading to the source. +- **kind**: Kind of source to add. Currently only **remote** is used. + +Example: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/javascript-all + extensible: sourceModel + data: + - ["global", "Member[user].Member[name]", "remote"] + +sinkModel(type, path, kind) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Adds a new taint sink. Sinks are query-specific and will typically affect one or two queries. + +- **type**: Name of a type from which to evaluate **path**. +- **path**: Access path leading to the sink. +- **kind**: Kind of sink to add. See the section on sink kinds for a list of supported kinds. + +Example: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/javascript-all + extensible: sinkModel + data: + - ["global", "Member[eval].Argument[0]", "code-injection"] + +summaryModel(type, path, input, output, kind) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Adds flow through a function call. + +- **type**: Name of a type from which to evaluate **path**. +- **path**: Access path leading to a function call. +- **input**: Path relative to the function call that leads to input of the flow. +- **output**: Path relative to the function call leading to the output of the flow. +- **kind**: Kind of summary to add. Can be **taint** for taint-propagating flow, or **value** for value-preserving flow. + +Example: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/javascript-all + extensible: summaryModel + data: + - [ + "global", + "Member[decodeURIComponent]", + "Argument[0]", + "ReturnValue", + "taint", + ] + +typeModel(type1, type2, path) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Adds a new definition of a type. + +- **type1**: Name of the type to define. +- **type2**: Name of the type from which to evaluate **path**. +- **path**: Access path leading from **type2** to **type1**. + +Example: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/javascript-all + extensible: typeModel + data: + - [ + "mysql.Connection", + "@example/db", + "Member[getConnection].ReturnValue", + ] + +Types +----- + +A type is a string that identifies a set of values. +In each of the extensible predicates mentioned in previous section, the first column is always the name of a type. +A type can be defined by adding **typeModel** tuples for that type. Additionally, the following built-in types are available: + +- The name of an NPM package matches imports of that package. For example, the type **express** matches the expression **require("express")**. If the package name includes dots, it must be surrounded by single quotes, such as in **'lodash.escape'**. +- The type **global** identifies the global object, also known as **window**. In JavaScript, global variables are properties of the global object, so global variables can be identified using this type. (This type also matches imports of the NPM package named **global**, which is a package that happens to export the global object.) +- A qualified type name of form **.** identifies expressions of type **** from ****. For example, **mysql.Connection** identifies expression of type **Connection** from the **mysql** package. Note that this only works if type annotations are present in the codebase, or if sufficient **typeModel** tuples have been provided for that type. + +Access paths +------------ + +The **path**, **input**, and **output** columns consist of a **.**-separated list of components, which is evaluated from left to right, with each step selecting a new set of values derived from the previous set of values. + +The following components are supported: + +- **Argument[**\ `number`\ **]** selects the argument at the given index. +- **Argument[this]** selects the receiver of a method call. +- **Parameter[**\ `number`\ **]** selects the parameter at the given index. +- **Parameter[this]** selects the **this** parameter of a function. +- **ReturnValue** selects the return value of a function or call. +- **Member[**\ `name`\ **]** selects the property with the given name. +- **AnyMember** selects any property regardless of name. +- **ArrayElement** selects an element of an array. +- **Element** selects an element of an array, iterator, or set object. +- **MapValue** selects a value of a map object. +- **Awaited** selects the value of a promise. +- **Instance** selects instances of a class. + +The following components are called "call site filters". They select a subset of the previously-selected calls, if the call fits certain criteria: + +- **WithArity[**\ `number`\ **]** selects the subset of calls that have the given number of arguments. +- **WithStringArgument[**\ `number`\ **=**\ `value`\ **]** selects the subset of calls where the argument at the given index is a string literal with the given value. + +Components related to decorators: + +- **DecoratedClass** selects a class that has the current value as a decorator. For example, **Member[Component].DecoratedClass** selects any class that is decorated with **@Component**. +- **DecoratedParameter** selects a parameter that is decorated by the current value. +- **DecoratedMember** selects a method, field, or accessor that is decorated by the current value. + +Additional notes about the syntax of operands: + +- Multiple operands may be given to a single component, as a shorthand for the union of the operands. For example, **Member[foo,bar]** matches the union of **Member[foo]** and **Member[bar]**. +- Numeric operands to **Argument**, **Parameter**, and **WithArity** may be given as an interval. For example, **Argument[0..2]** matches argument 0, 1, or 2. +- **Argument[N-1]** selects the last argument of a call, and **Parameter[N-1]** selects the last parameter of a function, with **N-2** being the second-to-last and so on. + +Kinds +----- + +Source kinds +~~~~~~~~~~~~ + +- **remote**: A generic source of remote flow. Most taint-tracking queries will use such a source. Currently this is the only supported source kind. + +Sink kinds +~~~~~~~~~~ + +Unlike sources, sinks tend to be highly query-specific, rarely affecting more than one or two queries. Not every query supports customizable sinks. If the following sinks are not suitable for your use case, you should add a new query. + +- **code-injection**: A sink that can be used to inject code, such as in calls to **eval**. +- **command-line-injection**: A sink that can be used to inject shell commands, such as in calls to **child_process.spawn**. +- **path-injection**: A sink that can be used for path injection in a file system access, such as in calls to **fs.readFile**. +- **sql-injection**: A sink that can be used for SQL injection, such as in a MySQL **query** call. +- **nosql-injection**: A sink that can be used for NoSQL injection, such as in a MongoDB **findOne** call. +- **html-injection**: A sink that can be used for HTML injection, such as in a jQuery **$()** call. +- **request-forgery**: A sink that controls the URL of a request, such as in a **fetch** call. +- **url-redirection**: A sink that can be used to redirect the user to a malicious URL. +- **unsafe-deserialization**: A deserialization sink that can lead to code execution or other unsafe behaviour, such as an unsafe YAML parser. + +Summary kinds +~~~~~~~~~~~~~ + +- **taint**: A summary that propagates taint. This means the output is not necessarily equal to the input, but it was derived from the input in an unrestrictive way. An attacker who controls the input will have significant control over the output as well. +- **value**: A summary that preserves the value of the input or creates a copy of the input such that all of its object properties are preserved. diff --git a/docs/codeql/codeql-language-guides/functions-in-python.rst b/docs/codeql/codeql-language-guides/functions-in-python.rst index fbb4ff0d6e5..d389dab31d6 100644 --- a/docs/codeql/codeql-language-guides/functions-in-python.rst +++ b/docs/codeql/codeql-language-guides/functions-in-python.rst @@ -75,12 +75,12 @@ This query uses ``Call`` and ``Name`` to find calls to the function ``eval`` - w select call, "call to 'eval'." The ``Call`` class represents calls in Python. The ``Call.getFunc()`` predicate gets the expression being called. ``Name.getId()`` gets the identifier (as a string) of the ``Name`` expression. -Due to the dynamic nature of Python, this query will select any call of the form ``eval(...)`` regardless of whether it is a call to the built-in function ``eval`` or not. -In a later tutorial we will see how to use the type-inference library to find calls to the built-in function ``eval`` regardless of name of the variable called. +This query will select any call of the form ``eval(...)`` regardless of whether it is a call to the built-in function ``eval`` or not. +Due to the dynamic nature of Python, such syntactic queries can be inaccurate. If one is looking for invocations of the built-in function ``eval``, +it is preferred to use the API graph, see ":doc:`Using API graphs in Python `." Further reading --------------- .. include:: ../reusables/python-further-reading.rst .. include:: ../reusables/codeql-ref-tools-further-reading.rst - diff --git a/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst b/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst index cc3fe5e9469..7ee1706db45 100644 --- a/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/specifying-additional-remote-flow-sources-for-javascript.rst @@ -3,13 +3,14 @@ Specifying additional remote flow sources for JavaScript ======================================================== -You can model potential sources of untrusted user input in your code without making changes to the CodeQL standard library by specifying extra remote flow sources in an external file. - .. pull-quote:: - Note + Deprecation Notice - Specifying remote flow sources in external files is currently in beta and subject to change. + Specifying remote flow sources with the JSON format described here is soon to be deprecated + and will be removed in the future. + +You can model potential sources of untrusted user input in your code without making changes to the CodeQL standard library by specifying extra remote flow sources in an external file. As mentioned in the :ref:`Data flow cheat sheet for JavaScript `, the CodeQL libraries for JavaScript provide a class `RemoteFlowSource `__ to represent sources of untrusted user input, sometimes also referred to as remote flow diff --git a/docs/codeql/reusables/beta-note-customizing-library-models.rst b/docs/codeql/reusables/beta-note-customizing-library-models.rst new file mode 100644 index 00000000000..051078d61d0 --- /dev/null +++ b/docs/codeql/reusables/beta-note-customizing-library-models.rst @@ -0,0 +1,7 @@ +.. pull-quote:: + + Beta Notice - Unstable API + + Library customization using data extensions is currently in beta and subject to change. + + Breaking changes to this format may occur while in beta. diff --git a/docs/codeql/reusables/data-extensions.rst b/docs/codeql/reusables/data-extensions.rst new file mode 100644 index 00000000000..5b79ba81265 --- /dev/null +++ b/docs/codeql/reusables/data-extensions.rst @@ -0,0 +1,10 @@ +.. _data-extensions: + +Data Extensions +=============== + +.. pull-quote:: + + Beta Notice - Internal documentation + + Data extensions are documented internally in a `Google doc `_. diff --git a/docs/codeql/reusables/supported-frameworks.rst b/docs/codeql/reusables/supported-frameworks.rst index 1c36480e9a7..cd1112a6e0c 100644 --- a/docs/codeql/reusables/supported-frameworks.rst +++ b/docs/codeql/reusables/supported-frameworks.rst @@ -223,7 +223,9 @@ and the CodeQL library pack ``codeql/python-all`` (`changelog implements DataFlowSig { +module Global implements GlobalFlowSig { private module C implements FullStateConfigSig { import DefaultState import Config @@ -233,10 +233,15 @@ module Make implements DataFlowSig { import Impl } +/** DEPRECATED: Use `Global` instead. */ +deprecated module Make implements GlobalFlowSig { + import Global +} + /** - * Constructs a data flow computation using flow state. + * Constructs a global data flow computation using flow state. */ -module MakeWithState implements DataFlowSig { +module GlobalWithState implements GlobalFlowSig { private module C implements FullStateConfigSig { import Config } @@ -244,6 +249,11 @@ module MakeWithState implements DataFlowSig { import Impl } +/** DEPRECATED: Use `GlobalWithState` instead. */ +deprecated module MakeWithState implements GlobalFlowSig { + import GlobalWithState +} + signature class PathNodeSig { /** Gets a textual representation of this element. */ string toString(); diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll index c47b0308855..6ea97954bdf 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll @@ -8,6 +8,7 @@ private import DataFlowImplCommon private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommonPublic +private import codeql.util.Unit import DataFlow /** @@ -91,10 +92,10 @@ signature module FullStateConfigSig { */ FlowFeature getAFeature(); - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ predicate sourceGrouping(Node source, string sourceGroup); - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ predicate sinkGrouping(Node sink, string sinkGroup); /** @@ -445,11 +446,7 @@ module Impl { } private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } + class Ap = Unit; private class Cc = boolean; @@ -3633,7 +3630,7 @@ module Impl { * The corresponding paths are generated from the end-points and the graph * included in the module `PathGraph`. */ - predicate hasFlowPath(PathNode source, PathNode sink) { + predicate flowPath(PathNode source, PathNode sink) { exists(PathNodeImpl flowsource, PathNodeImpl flowsink | source = flowsource and sink = flowsink | @@ -3643,6 +3640,9 @@ module Impl { ) } + /** DEPRECATED: Use `flowPath` instead. */ + deprecated predicate hasFlowPath = flowPath/2; + private predicate flowsTo(PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink) { flowsource.isSource() and flowsource.getNodeEx().asNode() = source and @@ -3653,17 +3653,26 @@ module Impl { /** * Holds if data can flow from `source` to `sink`. */ - predicate hasFlow(Node source, Node sink) { flowsTo(_, _, source, sink) } + predicate flow(Node source, Node sink) { flowsTo(_, _, source, sink) } + + /** DEPRECATED: Use `flow` instead. */ + deprecated predicate hasFlow = flow/2; /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + predicate flowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + + /** DEPRECATED: Use `flowTo` instead. */ + deprecated predicate hasFlowTo = flowTo/1; /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate flowToExpr(DataFlowExpr sink) { flowTo(exprNode(sink)) } + + /** DEPRECATED: Use `flowToExpr` instead. */ + deprecated predicate hasFlowToExpr = flowToExpr/1; private predicate finalStats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples @@ -4574,7 +4583,7 @@ module Impl { * * To use this in a `path-problem` query, import the module `PartialPathGraph`. */ - predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { + predicate partialFlow(PartialPathNode source, PartialPathNode node, int dist) { partialFlow(source, node) and dist = node.getSourceDistance() } @@ -4594,7 +4603,7 @@ module Impl { * Note that reverse flow has slightly lower precision than the corresponding * forward flow, as reverse flow disregards type pruning among other features. */ - predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { + predicate partialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { revPartialFlow(node, sink) and dist = node.getSinkDistance() } diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll index e6bdc74cceb..be70086a93a 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll index e6bdc74cceb..be70086a93a 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll index d09fdcfca3e..e6fce328326 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll @@ -140,10 +140,8 @@ private module LambdaFlow { } pragma[nomagic] - private TReturnPositionSimple viableReturnPosLambda( - DataFlowCall call, DataFlowCallOption lastCall, ReturnKind kind - ) { - result = TReturnPositionSimple0(viableCallableLambda(call, lastCall), kind) + private TReturnPositionSimple viableReturnPosLambda(DataFlowCall call, ReturnKind kind) { + result = TReturnPositionSimple0(viableCallableLambda(call, _), kind) } private predicate viableReturnPosOutNonLambda( @@ -155,11 +153,12 @@ private module LambdaFlow { ) } + pragma[nomagic] private predicate viableReturnPosOutLambda( - DataFlowCall call, DataFlowCallOption lastCall, TReturnPositionSimple pos, OutNode out + DataFlowCall call, TReturnPositionSimple pos, OutNode out ) { exists(ReturnKind kind | - pos = viableReturnPosLambda(call, lastCall, kind) and + pos = viableReturnPosLambda(call, kind) and out = getAnOutNode(call, kind) ) } @@ -188,6 +187,7 @@ private module LambdaFlow { else any() } + pragma[assume_small_delta] pragma[nomagic] predicate revLambdaFlow0( DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn, @@ -274,6 +274,7 @@ private module LambdaFlow { ) } + pragma[assume_small_delta] pragma[nomagic] predicate revLambdaFlowOut( DataFlowCall lambdaCall, LambdaCallKind kind, TReturnPositionSimple pos, DataFlowType t, @@ -285,7 +286,7 @@ private module LambdaFlow { or // non-linear recursion revLambdaFlowOutLambdaCall(lambdaCall, kind, out, t, toJump, call, lastCall) and - viableReturnPosOutLambda(call, _, pos, out) + viableReturnPosOutLambda(call, pos, out) ) } diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplForStringsNewReplacer.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplForStringsNewReplacer.qll index e6bdc74cceb..be70086a93a 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplForStringsNewReplacer.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplForStringsNewReplacer.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll index f6cb63c1c75..6cddbd7b980 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll @@ -3,6 +3,7 @@ private import DataFlowUtil private import DataFlowImplCommon private import ContainerFlow private import FlowSummaryImpl as FlowSummaryImpl +private import codeql.util.Unit import DataFlowNodes::Private private newtype TReturnKind = @@ -339,15 +340,6 @@ predicate forceHighPrecision(Content c) { c instanceof ArrayContent or c instanceof CollectionContent } -/** The unit type. */ -private newtype TUnit = TMkUnit() - -/** The trivial type with a single element. */ -class Unit extends TUnit { - /** Gets a textual representation of this element. */ - string toString() { result = "unit" } -} - /** * Gets the `i`th argument of call `c`, where the receiver of a method call * counts as argument -1. diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 478328d90bf..6665e0e7480 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -10,6 +10,7 @@ private import FlowSummaryImplSpecific private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommon +private import codeql.util.Unit /** Provides classes and predicates for defining flow summaries. */ module Public { @@ -109,6 +110,7 @@ module Public { } /** Gets the stack obtained by dropping the first `i` elements, if any. */ + pragma[assume_small_delta] SummaryComponentStack drop(int i) { i = 0 and result = this or diff --git a/go/ql/lib/semmle/go/dataflow/internal/TaintTrackingUtil.qll b/go/ql/lib/semmle/go/dataflow/internal/TaintTrackingUtil.qll index 6dfc0dbdcff..38e03f62b44 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/TaintTrackingUtil.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/TaintTrackingUtil.qll @@ -4,6 +4,7 @@ private import go private import FlowSummaryImpl as FlowSummaryImpl +private import codeql.util.Unit /** * Holds if taint can flow from `src` to `sink` in zero or more @@ -66,14 +67,6 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { ) } -private newtype TUnit = TMkUnit() - -/** A singleton class containing a single dummy "unit" value. */ -private class Unit extends TUnit { - /** Gets a textual representation of this element. */ - string toString() { result = "unit" } -} - /** * A unit class for adding additional taint steps. * diff --git a/go/ql/lib/semmle/go/dataflow/internal/tainttracking1/TaintTracking.qll b/go/ql/lib/semmle/go/dataflow/internal/tainttracking1/TaintTracking.qll index 7f96fe5e6fb..872ac8d4cb8 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/tainttracking1/TaintTracking.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/tainttracking1/TaintTracking.qll @@ -33,9 +33,9 @@ private module AddTaintDefaults imp } /** - * Constructs a standard taint tracking computation. + * Constructs a global taint tracking computation. */ -module Make implements DataFlow::DataFlowSig { +module Global implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import DataFlowInternal::DefaultState import Config @@ -48,10 +48,15 @@ module Make implements DataFlow::DataFlowSig { import DataFlowInternal::Impl } +/** DEPRECATED: Use `Global` instead. */ +deprecated module Make implements DataFlow::GlobalFlowSig { + import Global +} + /** - * Constructs a taint tracking computation using flow state. + * Constructs a global taint tracking computation using flow state. */ -module MakeWithState implements DataFlow::DataFlowSig { +module GlobalWithState implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import Config } @@ -62,3 +67,8 @@ module MakeWithState implements DataFlow::DataF import DataFlowInternal::Impl } + +/** DEPRECATED: Use `GlobalWithState` instead. */ +deprecated module MakeWithState implements DataFlow::GlobalFlowSig { + import GlobalWithState +} diff --git a/java/documentation/library-coverage/coverage.csv b/java/documentation/library-coverage/coverage.csv index 84e5a0db8eb..d5df48676e6 100644 --- a/java/documentation/library-coverage/coverage.csv +++ b/java/documentation/library-coverage/coverage.csv @@ -33,38 +33,38 @@ freemarker.cache,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,, freemarker.template,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,, groovy.lang,26,,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, groovy.util,5,,,,,,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -hudson.model,4,,1,,2,,,,,,,,,,,,,1,,1,,,,,,,,,,,,,,,,,,,,,1, -hudson.os,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -hudson.remoting,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -hudson.util,4,,1,,3,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,1, +hudson,44,,16,,19,,,,,,,,,,,,,6,,17,,,,,,,,,,,,,2,,,,,,,,16, io.netty.bootstrap,3,,,,,,,,,,,,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,, -io.netty.channel,9,,,,,,,,,,,,,,,,,9,,,,,,,,,,,,,,,,,,,,,,,, -io.netty.handler.codec.http,3,,1,,,,,,,,,,,,,,,2,,1,,,,,,,,,,,,,,,,,,,,,1, +io.netty.buffer,,,207,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,130,77 +io.netty.channel,9,2,,,,,,,,,,,,,,,,9,,,,,,,,,,,,,,,,,,,,,,2,, +io.netty.handler.codec,3,13,260,,,,,,,,,,,,,,,2,,1,,,,,,,,,,,,,,,,,,,,13,144,116 io.netty.handler.ssl,2,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,, io.netty.handler.stream,1,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,, io.netty.resolver,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -io.netty.util.internal,2,,2,,1,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,2, +io.netty.util,2,,23,,1,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,21,2 jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,7,, jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23 jakarta.ws.rs.client,1,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,, jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,, jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,94,55 +java.awt,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3 java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -java.io,42,,40,,17,,,,,,,,,,,,,,,3,,,,,,,,,,,,,22,,,,,,,,39,1 -java.lang,16,,76,,,,,,,,,,,,8,,,,,3,,4,,,1,,,,,,,,,,,,,,,,53,23 -java.net,12,3,16,,,,,,,,,,,,,,,12,,,,,,,,,,,,,,,,,,,,,,3,16, -java.nio,20,,16,,15,,,,,,,,,,,,,,,3,,,,,,,,,,,,,2,,,,,,,,16, -java.sql,13,,2,,,,,,,,4,,,,,,,,,,,,,,,,,,9,,,,,,,,,,,,1,1 -java.util,44,,465,,,,,,,,,,,,34,,,,,,,,5,2,,1,2,,,,,,,,,,,,,,38,427 +java.io,42,,45,,17,,,,,,,,,,,,,,,3,,,,,,,,,,,,,22,,,,,,,,43,2 +java.lang,16,,90,,,,,,,,,,,,8,,,,,3,,4,,,1,,,,,,,,,,,,,,,,55,35 +java.net,12,3,17,,,,,,,,,,,,,,,12,,,,,,,,,,,,,,,,,,,,,,3,17, +java.nio,25,,30,,19,,,,,,,,,,,,,,,4,,,,,,,,,,,,,2,,,,,,,,30, +java.sql,13,,3,,,,,,,,4,,,,,,,,,,,,,,,,,,9,,,,,,,,,,,,2,1 +java.util,44,,478,,,,,,,,,,,,34,,,,,,,,5,2,,1,2,,,,,,,,,,,,,,41,437 javafx.scene.web,1,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,, javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,7,, +javax.imageio.stream,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, javax.jms,,9,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,57, javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23 javax.management.remote,2,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -javax.naming,7,,,,,,,,,,,,6,1,,,,,,,,,,,,,,,,,,,,,,,,,,,, +javax.naming,7,,1,,,,,,,,,,6,1,,,,,,,,,,,,,,,,,,,,,,,,,,,1, javax.net.ssl,2,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,, javax.script,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,, -javax.servlet,4,21,2,,,,,3,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,21,2, +javax.servlet,5,21,2,,,,,3,1,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,21,2, javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,, javax.ws.rs.client,1,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,, javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,, @@ -108,6 +108,7 @@ org.apache.velocity.runtime,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,, org.codehaus.cargo.container.installer,3,,,,2,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,, org.codehaus.groovy.control,1,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, org.dom4j,20,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,20,,,,,,,, +org.geogebra.web.full.main,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,, org.hibernate,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,,, org.jboss.logging,324,,,,,,,,,,,,,,324,,,,,,,,,,,,,,,,,,,,,,,,,,, org.jdbi.v3.core,6,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, diff --git a/java/documentation/library-coverage/coverage.rst b/java/documentation/library-coverage/coverage.rst index cc6fdb875ff..973ffad9f13 100644 --- a/java/documentation/library-coverage/coverage.rst +++ b/java/documentation/library-coverage/coverage.rst @@ -18,10 +18,10 @@ Java framework & library support `Google Guava `_,``com.google.common.*``,,730,39,,6,,,,, JBoss Logging,``org.jboss.logging``,,,324,,,,,,, `JSON-java `_,``org.json``,,236,,,,,,,, - Java Standard Library,``java.*``,3,616,147,32,,,9,,,12 - Java extensions,"``javax.*``, ``jakarta.*``",63,609,33,1,,4,,1,1,2 + Java Standard Library,``java.*``,3,667,152,36,,,9,,,12 + Java extensions,"``javax.*``, ``jakarta.*``",63,611,34,1,,4,,1,1,2 Kotlin Standard Library,``kotlin*``,,1835,12,10,,,,,,2 `Spring `_,``org.springframework.*``,29,480,101,,,,19,14,,29 - Others,"``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.hubspot.jinjava``, ``com.mitchellbosecke.pebble``, ``com.opensymphony.xwork2.ognl``, ``com.rabbitmq.client``, ``com.thoughtworks.xstream``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``freemarker.cache``, ``freemarker.template``, ``groovy.lang``, ``groovy.util``, ``hudson.model``, ``hudson.os``, ``hudson.remoting``, ``hudson.util``, ``io.netty.bootstrap``, ``io.netty.channel``, ``io.netty.handler.codec.http``, ``io.netty.handler.ssl``, ``io.netty.handler.stream``, ``io.netty.resolver``, ``io.netty.util.internal``, ``javafx.scene.web``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.apache.commons.codec``, ``org.apache.commons.compress.archivers.tar``, ``org.apache.commons.jelly``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.tools.ant``, ``org.apache.tools.zip``, ``org.apache.velocity.app``, ``org.apache.velocity.runtime``, ``org.codehaus.cargo.container.installer``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jdbi.v3.core``, ``org.jooq``, ``org.kohsuke.stapler``, ``org.mvel2``, ``org.openjdk.jmh.runner.options``, ``org.scijava.log``, ``org.slf4j``, ``org.thymeleaf``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``",60,314,327,12,,,18,18,,28 - Totals,,217,8491,1640,146,6,10,113,33,1,113 + Others,"``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.hubspot.jinjava``, ``com.mitchellbosecke.pebble``, ``com.opensymphony.xwork2.ognl``, ``com.rabbitmq.client``, ``com.thoughtworks.xstream``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``freemarker.cache``, ``freemarker.template``, ``groovy.lang``, ``groovy.util``, ``hudson``, ``io.netty.bootstrap``, ``io.netty.buffer``, ``io.netty.channel``, ``io.netty.handler.codec``, ``io.netty.handler.ssl``, ``io.netty.handler.stream``, ``io.netty.resolver``, ``io.netty.util``, ``javafx.scene.web``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.apache.commons.codec``, ``org.apache.commons.compress.archivers.tar``, ``org.apache.commons.jelly``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.tools.ant``, ``org.apache.tools.zip``, ``org.apache.velocity.app``, ``org.apache.velocity.runtime``, ``org.codehaus.cargo.container.installer``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.geogebra.web.full.main``, ``org.hibernate``, ``org.jdbi.v3.core``, ``org.jooq``, ``org.kohsuke.stapler``, ``org.mvel2``, ``org.openjdk.jmh.runner.options``, ``org.scijava.log``, ``org.slf4j``, ``org.thymeleaf``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``",75,813,364,26,,,18,18,,33 + Totals,,232,9043,1683,164,6,10,113,33,1,118 diff --git a/java/kotlin-extractor/build.py b/java/kotlin-extractor/build.py index f31484bdec3..b52ff05b00e 100755 --- a/java/kotlin-extractor/build.py +++ b/java/kotlin-extractor/build.py @@ -11,8 +11,6 @@ import os import os.path import sys import shlex -import distutils -from distutils import dir_util def parse_args(): @@ -203,7 +201,7 @@ def compile(jars, java_jars, dependency_folder, transform_to_embeddable, output, version.replace('.', '_') if os.path.exists(d): # copy and overwrite files from the version folder to the include folder - distutils.dir_util.copy_tree(d, include_version_folder) + shutil.copytree(d, include_version_folder, dirs_exist_ok=True) # remove all version folders: for version in kotlin_plugin_versions.many_versions: diff --git a/java/ql/lib/change-notes/2023-02-15-add-top-jdk-models.md b/java/ql/lib/change-notes/2023-02-15-add-top-jdk-models.md new file mode 100644 index 00000000000..a74fb161e58 --- /dev/null +++ b/java/ql/lib/change-notes/2023-02-15-add-top-jdk-models.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added more dataflow models for frequently-used JDK APIs. diff --git a/java/ql/lib/change-notes/2023-02-28-netty.md b/java/ql/lib/change-notes/2023-02-28-netty.md new file mode 100644 index 00000000000..18a2f4b211b --- /dev/null +++ b/java/ql/lib/change-notes/2023-02-28-netty.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added sources and flow step models for the Netty framework up to version 4.1. \ No newline at end of file diff --git a/java/ql/lib/change-notes/2023-03-20-nativesql-summary.md b/java/ql/lib/change-notes/2023-03-20-nativesql-summary.md new file mode 100644 index 00000000000..8d350f77bd3 --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-20-nativesql-summary.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added a summary model for the `nativeSQL` method of the `java.sql.Connection` interface. diff --git a/java/ql/lib/change-notes/2023-03-22-deprecate-webviewdubuggingenabledquery.md b/java/ql/lib/change-notes/2023-03-22-deprecate-webviewdubuggingenabledquery.md new file mode 100644 index 00000000000..e4f2933c04a --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-22-deprecate-webviewdubuggingenabledquery.md @@ -0,0 +1,4 @@ +--- +category: deprecated +--- +* The `WebViewDubuggingQuery` library has been renamed to `WebViewDebuggingQuery` to fix the typo in the file name. `WebViewDubuggingQuery` is now deprecated. diff --git a/java/ql/lib/change-notes/2023-03-23-dataflow-renaming.md b/java/ql/lib/change-notes/2023-03-23-dataflow-renaming.md new file mode 100644 index 00000000000..54df71fae46 --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-23-dataflow-renaming.md @@ -0,0 +1,6 @@ +--- +category: deprecated +--- +* The recently introduced new data flow and taint tracking APIs have had a + number of module and predicate renamings. The old APIs remain in place for + now. diff --git a/java/ql/lib/change-notes/2023-03-23-jndi-sanitizer.md b/java/ql/lib/change-notes/2023-03-23-jndi-sanitizer.md new file mode 100644 index 00000000000..20738f07c05 --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-23-jndi-sanitizer.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added the extensible abstract class `JndiInjectionSanitizer`. Now this class can be extended to add more sanitizers to the `java/jndi-injection` query. diff --git a/java/ql/lib/change-notes/2023-03-27-hudson-models.md b/java/ql/lib/change-notes/2023-03-27-hudson-models.md new file mode 100644 index 00000000000..27c0b73cbbb --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-27-hudson-models.md @@ -0,0 +1,7 @@ +--- +category: minorAnalysis +--- +* Added more sink and summary dataflow models for the following packages: + * `hudson.model` + * `hudson.scm` + * `hudson.util` diff --git a/java/ql/lib/change-notes/2023-03-27-more-hudson-models.md b/java/ql/lib/change-notes/2023-03-27-more-hudson-models.md new file mode 100644 index 00000000000..2ddaec593fb --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-27-more-hudson-models.md @@ -0,0 +1,8 @@ +--- +category: minorAnalysis +--- +* Added more sink and summary dataflow models for the following packages: + * `hudson.cli` + * `hudson.lifecycle` + * `hudson` + * `hudson.util.io` diff --git a/java/ql/lib/change-notes/2023-03-28-dataflow-rm-footgun.md b/java/ql/lib/change-notes/2023-03-28-dataflow-rm-footgun.md new file mode 100644 index 00000000000..82dc0a1d893 --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-28-dataflow-rm-footgun.md @@ -0,0 +1,4 @@ +--- +category: fix +--- +* Fixed some accidental predicate visibility in the backwards-compatible wrapper for data flow configurations. In particular `DataFlow::hasFlowPath`, `DataFlow::hasFlow`, `DataFlow::hasFlowTo`, and `DataFlow::hasFlowToExpr` were accidentally exposed in a single version. diff --git a/java/ql/lib/change-notes/2023-03-28-deprecated-exectainted.md b/java/ql/lib/change-notes/2023-03-28-deprecated-exectainted.md new file mode 100644 index 00000000000..abe4eaf4bad --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-28-deprecated-exectainted.md @@ -0,0 +1,5 @@ +--- +category: deprecated +--- +* The `execTainted` predicate in `CommandLineQuery.qll` has been deprecated and replaced with the predicate `execIsTainted`. + diff --git a/java/ql/lib/change-notes/2023-03-29-rangeanalysis-add.md b/java/ql/lib/change-notes/2023-03-29-rangeanalysis-add.md new file mode 100644 index 00000000000..a097923ae46 --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-29-rangeanalysis-add.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Improved the handling of addition in the range analysis. This can cause in minor changes to the results produced by `java/index-out-of-bounds` and `java/constant-comparison`. diff --git a/java/ql/lib/ext/hudson.cli.model.yml b/java/ql/lib/ext/hudson.cli.model.yml new file mode 100644 index 00000000000..138899d4bd3 --- /dev/null +++ b/java/ql/lib/ext/hudson.cli.model.yml @@ -0,0 +1,7 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["hudson.cli", "FullDuplexHttpStream", True, "FullDuplexHttpStream", "(URL,String,String)", "", "Argument[0]", "open-url", "ai-generated"] + - ["hudson.cli", "FullDuplexHttpStream", True, "FullDuplexHttpStream", "(URL,String,String)", "", "Argument[1]", "open-url", "manual"] diff --git a/java/ql/lib/ext/hudson.lifecycle.model.yml b/java/ql/lib/ext/hudson.lifecycle.model.yml new file mode 100644 index 00000000000..84fae40ab92 --- /dev/null +++ b/java/ql/lib/ext/hudson.lifecycle.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["hudson.lifecycle", "Lifecycle", True, "rewriteHudsonWar", "(File)", "", "Argument[0]", "create-file", "ai-generated"] diff --git a/java/ql/lib/ext/hudson.model.model.yml b/java/ql/lib/ext/hudson.model.model.yml index 2c0c7e46be6..1eb109ff7e1 100644 --- a/java/ql/lib/ext/hudson.model.model.yml +++ b/java/ql/lib/ext/hudson.model.model.yml @@ -1,14 +1,18 @@ extensions: - - addsTo: - pack: codeql/java-all - extensible: summaryModel - data: - - ["hudson.model", "DirectoryBrowserSupport$Path", False, "Path", "(String,String,boolean,long,boolean,long)", "", "Argument[0]", "Argument[this].SyntheticField[hudson.model.DirectoryBrowserSupport$Path.href]", "taint", "ai-generated"] - addsTo: pack: codeql/java-all extensible: sinkModel data: + - ["hudson.model", "DownloadService", True, "loadJSON", "(URL)", "", "Argument[0]", "open-url", "ai-generated"] + - ["hudson.model", "DownloadService", True, "loadJSONHTML", "(URL)", "", "Argument[0]", "open-url", "ai-generated"] - ["hudson.model", "DirectoryBrowserSupport", False, "DirectoryBrowserSupport", "(ModelObject,FilePath,String,String,boolean)", "", "Argument[1]", "read-file", "ai-generated"] + - ["hudson.model", "Items", True, "load", "(ItemGroup,File)", "", "Argument[1]", "read-file", "ai-generated"] - ["hudson.model", "UpdateCenter$UpdateCenterConfiguration", True, "download", "(DownloadJob,URL)", "", "Argument[1]", "open-url", "ai-generated"] - ["hudson.model", "UpdateCenter$UpdateCenterConfiguration", True, "install", "(DownloadJob,File,File)", "", "Argument[1]", "create-file", "ai-generated"] # should be delete-file - ["hudson.model", "UpdateCenter$UpdateCenterConfiguration", True, "install", "(DownloadJob,File,File)", "", "Argument[2]", "create-file", "ai-generated"] + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["hudson.model", "Node", True, "createPath", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] + - ["hudson.model", "DirectoryBrowserSupport$Path", False, "Path", "(String,String,boolean,long,boolean,long)", "", "Argument[0]", "Argument[this].SyntheticField[hudson.model.DirectoryBrowserSupport$Path.href]", "taint", "ai-generated"] diff --git a/java/ql/lib/ext/hudson.model.yml b/java/ql/lib/ext/hudson.model.yml new file mode 100644 index 00000000000..04984703274 --- /dev/null +++ b/java/ql/lib/ext/hudson.model.yml @@ -0,0 +1,26 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["hudson", "FilePath", False, "copyFrom", "(FilePath)", "", "Argument[0]", "read-file", "manual"] + - ["hudson", "FilePath", False, "copyFrom", "(URL)", "", "Argument[0]", "read-file", "manual"] + - ["hudson", "FilePath", False, "copyFrom", "(FileItem)", "", "Argument[0]", "read-file", "ai-generated"] + - ["hudson", "FilePath", False, "copyRecursiveTo", "(DirScanner,FilePath,String,TarCompression)", "", "Argument[1]", "create-file", "ai-generated"] + - ["hudson", "FilePath", False, "copyRecursiveTo", "(DirScanner,FilePath,String)", "", "Argument[1]", "write-file", "ai-generated"] + - ["hudson", "FilePath", False, "copyRecursiveTo", "(String,FilePath)", "", "Argument[1]", "create-file", "ai-generated"] + - ["hudson", "FilePath", False, "copyRecursiveTo", "(String,String,FilePath)", "", "Argument[0]", "read-file", "ai-generated"] + - ["hudson", "FilePath", False, "copyRecursiveTo", "(String,String,FilePath)", "", "Argument[2]", "create-file", "ai-generated"] + - ["hudson", "FilePath", False, "copyTo", "(FilePath)", "", "Argument[0]", "create-file", "ai-generated"] + - ["hudson", "FilePath", False, "installIfNecessaryFrom", "(URL,TaskListener,String)", "", "Argument[0]", "open-url", "ai-generated"] + - ["hudson", "FilePath", False, "newInputStreamDenyingSymlinkAsNeeded", "(File,String,boolean)", "", "Argument[0]", "read-file", "ai-generated"] + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["hudson", "FilePath", False, "child", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] + - ["hudson", "FilePath", False, "list", "(String,String,boolean)", "", "Argument[this]", "ReturnValue", "taint", "ai-generated"] + - ["hudson", "FilePath", False, "list", "(String,String)", "", "Argument[this]", "ReturnValue", "taint", "ai-generated"] + - ["hudson", "FilePath", False, "list", "(String)", "", "Argument[this]", "ReturnValue", "taint", "ai-generated"] + - ["hudson", "FilePath", False, "normalize", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] + - ["hudson", "FilePath", False, "sibling", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] diff --git a/java/ql/lib/ext/hudson.scm.model.yml b/java/ql/lib/ext/hudson.scm.model.yml new file mode 100644 index 00000000000..477c31b6412 --- /dev/null +++ b/java/ql/lib/ext/hudson.scm.model.yml @@ -0,0 +1,18 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["hudson.scm", "ChangeLogParser", True, "parse", "(AbstractBuild,File)", "", "Argument[1]", "read-file", "ai-generated"] + - ["hudson.scm", "ChangeLogParser", True, "parse", "(Run,RepositoryBrowser,File)", "", "Argument[2]", "read-file", "ai-generated"] + - ["hudson.scm", "SCM", True, "checkout", "(AbstractBuild,Launcher,FilePath,BuildListener,File)", "", "Argument[2]", "create-file", "ai-generated"] + - ["hudson.scm", "SCM", True, "checkout", "(Run,Launcher,FilePath,TaskListener,File,SCMRevisionState)", "", "Argument[2]", "create-file", "ai-generated"] + - ["hudson.scm", "SCM", True, "compareRemoteRevisionWith", "(Job,Launcher,FilePath,TaskListener,SCMRevisionState)", "", "Argument[2]", "read-file", "ai-generated"] + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["hudson.scm", "SCM", True, "getModuleRoot", "(FilePath,AbstractBuild)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] + - ["hudson.scm", "SCM", True, "getModuleRoot", "(FilePath)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] + - ["hudson.scm", "SCM", True, "getModuleRoots", "(FilePath,AbstractBuild)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] + - ["hudson.scm", "SCM", True, "getModuleRoots", "(FilePath)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] diff --git a/java/ql/lib/ext/hudson.util.io.model.yml b/java/ql/lib/ext/hudson.util.io.model.yml new file mode 100644 index 00000000000..a629beab66c --- /dev/null +++ b/java/ql/lib/ext/hudson.util.io.model.yml @@ -0,0 +1,7 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["hudson.util.io", "ReopenableFileOutputStream", True, "ReopenableFileOutputStream", "(File)", "", "Argument[0]", "create-file", "ai-generated"] + - ["hudson.util.io", "RewindableFileOutputStream", True, "RewindableFileOutputStream", "(File)", "", "Argument[0]", "create-file", "ai-generated"] diff --git a/java/ql/lib/ext/hudson.util.model.yml b/java/ql/lib/ext/hudson.util.model.yml index df34e56791f..969bd4a1e86 100644 --- a/java/ql/lib/ext/hudson.util.model.yml +++ b/java/ql/lib/ext/hudson.util.model.yml @@ -1,11 +1,25 @@ extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["hudson.util", "AtomicFileWriter", True, "AtomicFileWriter", "(File)", "", "Argument[0]", "create-file", "ai-generated"] + - ["hudson.util", "AtomicFileWriter", True, "AtomicFileWriter", "(Path,Charset,boolean,boolean)", "", "Argument[0]", "create-file", "ai-generated"] + - ["hudson.util", "AtomicFileWriter", True, "AtomicFileWriter", "(Path,Charset)", "", "Argument[0]", "create-file", "ai-generated"] + - ["hudson.util", "ClasspathBuilder", True, "add", "(FilePath)", "", "Argument[0]", "read-file", "ai-generated"] + - ["hudson.util", "IOUtils", True, "mkdirs", "(File)", "", "Argument[0]", "create-file", "ai-generated"] + - ["hudson.util", "StreamTaskListener", True, "StreamTaskListener", "(File,boolean,Charset)", "", "Argument[0]", "create-file", "ai-generated"] + - ["hudson.util", "TextFile", True, "delete", "()", "", "Argument[this]", "create-file", "manual"] + - ["hudson.util", "TextFile", True, "fastTail", "", "", "Argument[this]", "read-file", "manual"] + - ["hudson.util", "TextFile", True, "head", "", "", "Argument[this]", "read-file", "manual"] + - ["hudson.util", "TextFile", True, "lines", "()", "", "Argument[this]", "read-file", "manual"] + - ["hudson.util", "TextFile", True, "read", "()", "", "Argument[this]", "read-file", "manual"] + - ["hudson.util", "TextFile", True, "readTrim", "()", "", "Argument[this]", "read-file", "manual"] + - ["hudson.util", "TextFile", True, "write", "(String)", "", "Argument[0]", "write-file", "manual"] - addsTo: pack: codeql/java-all extensible: summaryModel data: - ["hudson.util", "QuotedStringTokenizer", True, "tokenize", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] - - addsTo: - pack: codeql/java-all - extensible: sinkModel - data: - - ["hudson.util", "StreamTaskListener", True, "StreamTaskListener", "(File,boolean,Charset)", "", "Argument[0]", "create-file", "ai-generated"] + - ["hudson.util", "TextFile", True, "TextFile", "(File)", "", "Argument[0]", "Argument[this]", "taint", "ai-generated"] + diff --git a/java/ql/lib/ext/io.netty.buffer.model.yml b/java/ql/lib/ext/io.netty.buffer.model.yml new file mode 100644 index 00000000000..81474a784f2 --- /dev/null +++ b/java/ql/lib/ext/io.netty.buffer.model.yml @@ -0,0 +1,212 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["io.netty.buffer", "ByteBufConvertible", True, "asByteBuf", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "array", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "asReadOnly", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "capacity", "(int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "copy", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "discardReadBytes", "()", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "discardSomeReadBytes", "()", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "duplicate", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "ensureWritable", "(int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getBytes", "(int,byte[])", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getBytes", "(int,byte[],int,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getBytes", "(int,ByteBuf)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getBytes", "(int,ByteBuffer)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getBytes", "(int,ByteBuf,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getBytes", "(int,ByteBuf,int,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getBytes", "(int,OutputStream,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "markReaderIndex", "()", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "markWriterIndex", "()", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "nioBuffer", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "nioBuffers", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "order", "(ByteOrder)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(byte[])", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(byte[],int,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(ByteBuf)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(ByteBuffer)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(ByteBuf,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(ByteBuf,int,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(OutputStream,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readerIndex", "(int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "resetReaderIndex", "()", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "resetWriterIndex", "()", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "retainedDuplicate", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "retainedSlice", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setBoolean", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setByte", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setBytes", "(int,byte[])", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setBytes", "(int,byte[],int,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setBytes", "(int,ByteBuf)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setBytes", "(int,ByteBuffer)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setBytes", "(int,ByteBuf,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setBytes", "(int,ByteBuf,int,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setChar", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setDouble", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setDoubleLE", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setFloat", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setFloatLE", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setIndex", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setInt", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setIntLE", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setLong", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setLongLE", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setMedium", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setMediumLE", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setShort", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setShortLE", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setZero", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "skipBytes", "(int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "slice", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "toString", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "unwrap", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeBoolean", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeByte", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeBytes", "(byte[])", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeBytes", "(byte[],int,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeBytes", "(ByteBuf)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeBytes", "(ByteBuffer)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeBytes", "(ByteBuf,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeBytes", "(ByteBuf,int,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeChar", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeDouble", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeDoubleLE", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeFloat", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeFloatLE", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeInt", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeIntLE", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeLong", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeLongLE", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeMedium", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeMediumLE", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeShort", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeShortLE", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeZero", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writerIndex", "(int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBufHolder", True, "copy", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBufHolder", True, "content", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBufHolder", True, "duplicate", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBufHolder", True, "retainedDuplicate", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBufHolder", True, "replace", "(ByteBuf)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getBytes", "(int,byte[])", "", "Argument[this]", "Argument[1]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getBytes", "(int,byte[],int,int)", "", "Argument[this]", "Argument[1]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getBytes", "(int,ByteBuf)", "", "Argument[this]", "Argument[1]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getBytes", "(int,ByteBuffer)", "", "Argument[this]", "Argument[1]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getBytes", "(int,ByteBuf,int)", "", "Argument[this]", "Argument[1]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getBytes", "(int,ByteBuf,int,int)", "", "Argument[this]", "Argument[1]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getBytes", "(int,FileChannel,long,int)", "", "Argument[this]", "Argument[1]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getBytes", "(int,GatheringByteChannel,int)", "", "Argument[this]", "Argument[1]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getBytes", "(int,OutputStream,int)", "", "Argument[this]", "Argument[1]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getChar", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "getCharSequence", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(byte[])", "", "Argument[this]", "Argument[0]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(byte[],int,int)", "", "Argument[this]", "Argument[0]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(ByteBuf)", "", "Argument[this]", "Argument[0]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(ByteBuffer)", "", "Argument[this]", "Argument[0]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(ByteBuf,int)", "", "Argument[this]", "Argument[0]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(ByteBuf,int,int)", "", "Argument[this]", "Argument[0]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(FileChannel,long,int)", "", "Argument[this]", "Argument[0]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(GatheringByteChannel,int)", "", "Argument[this]", "Argument[0]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(OutputStream,int)", "", "Argument[this]", "Argument[0]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readBytes", "(int)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readChar", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readCharSequence", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readSlice", "(int)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "readRetainedSlice", "(int)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setBytes", "(int,byte[])", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setBytes", "(int,byte[],int,int)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setBytes", "(int,ByteBuf)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setBytes", "(int,ByteBuffer)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setBytes", "(int,ByteBuf,int)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setBytes", "(int,ByteBuf,int,int)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setBytes", "(int,FileChannel,long,int)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setBytes", "(int,ScatteringByteChannel,int)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setBytes", "(int,InputStream,int)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setChar", "", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "setCharSequence", "", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeByte", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeBytes", "(byte[])", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeBytes", "(byte[],int,int)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeBytes", "(ByteBuf)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeBytes", "(ByteBuffer)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeBytes", "(ByteBuf,int)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeBytes", "(ByteBuf,int,int)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeBytes", "(FileChannel,long,int)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeBytes", "(ScatteringByteChannel,int)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeBytes", "(InputStream,int)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeChar", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBuf", True, "writeCharSequence", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", False, "CompositeByteBuf", "(ByteBufAllocator,boolean,int,ByteBuf[])", "", "Argument[3].ArrayElement", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", False, "CompositeByteBuf", "(ByteBufAllocator,boolean,int,Iterable)", "", "Argument[3].Element", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "addComponent", "(ByteBuf)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "addComponent", "(int,ByteBuf)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "addComponent", "(boolean,ByteBuf)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "addComponent", "(boolean,int,ByteBuf)", "", "Argument[2]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "addComponents", "(ByteBuf[])", "", "Argument[0].ArrayElement", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "addComponents", "(int,ByteBuf[])", "", "Argument[1].ArrayElement", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "addComponents", "(boolean,ByteBuf[])", "", "Argument[1].ArrayElement", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "addComponents", "(Iterable)", "", "Argument[0].Element", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "addComponents", "(int,Iterable)", "", "Argument[1].Element", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "addComponents", "(boolean,Iterable)", "", "Argument[1].Element", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "addFlattenedComponents", "(boolean,ByteBuf)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "addComponent", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "addComponents", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "addFlattenedComponents", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "component", "(int)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "componentAtOffset", "(int)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "consolidate", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "consolidate", "(int,int)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "CompositeByteBuf", True, "decompose", "(int,int)", "", "Argument[this]", "ReturnValue.Element", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "copiedBuffer", "(byte[])", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "copiedBuffer", "(byte[][])", "", "Argument[0].ArrayElement", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "copiedBuffer", "(byte[],int,int)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "copiedBuffer", "(ByteBuf)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "copiedBuffer", "(ByteBuf[])", "", "Argument[0].ArrayElement", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "copiedBuffer", "(ByteBuffer)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "copiedBuffer", "(ByteBuffer[])", "", "Argument[0].ArrayElement", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "copiedBuffer", "(char[],Charset)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "copiedBuffer", "(char[],int,int,Charset)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "copiedBuffer", "(CharSequence,Charset)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "copiedBuffer", "(CharSequence,int,int,Charset)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "unmodifiableBuffer", "(ByteBuf)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "unmodifiableBuffer", "(ByteBuf[])", "", "Argument[0].ArrayElement", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "unreleasableBuffer", "(ByteBuf)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "wrappedBuffer", "(byte[])", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "wrappedBuffer", "(byte[][])", "", "Argument[0].ArrayElement", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "wrappedBuffer", "(byte[],int,int)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "wrappedBuffer", "(ByteBuf)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "wrappedBuffer", "(ByteBuf[])", "", "Argument[0].ArrayElement", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "wrappedBuffer", "(ByteBuffer)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "wrappedBuffer", "(ByteBuffer[])", "", "Argument[0].ArrayElement", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "wrappedBuffer", "(int,byte[][])", "", "Argument[1].ArrayElement", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "wrappedBuffer", "(int,ByteBuf[])", "", "Argument[1].ArrayElement", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "wrappedBuffer", "(int,ByteBuffer[])", "", "Argument[1].ArrayElement", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "Unpooled", False, "wrappedUnmodifiableBuffer", "(ByteBuf[])", "", "Argument[0].ArrayElement", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "copy", "(AsciiString,ByteBuf)", "", "Argument[0]", "Argument[1]", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "copy", "(AsciiString,int,ByteBuf,int)", "", "Argument[0]", "Argument[2]", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "copy", "(AsciiString,int,ByteBuf,int,int)", "", "Argument[0]", "Argument[2]", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "decodeHexDump", "(CharSequence)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "decodeHexDump", "(CharSequence,int,int)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "encodeString", "(ByteBufAllocator,CharBuffer,Charset)", "", "Argument[1]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "encodeString", "(ByteBufAllocator,CharBuffer,Charset,int)", "", "Argument[1]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "ensureAccessible", "(ByteBuf)", "", "Argument[0]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "getBytes", "(ByteBuf)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "getBytes", "(ByteBuf,int,int)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "getBytes", "(ByteBuf,int,int,boolean)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "readBytes", "(ByteBufAllocator,ByteBuf,int)", "", "Argument[1]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "reserveAndWriteUtf8", "(ByteBuf,CharSequence,int)", "", "Argument[1]", "Argument[0]", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "reserveAndWriteUtf8", "(ByteBuf,CharSequence,int,int,int)", "", "Argument[1]", "Argument[0]", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "setShortBE", "(ByteBuf,int,int)", "", "Argument[0]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "writeAscii", "(ByteBuf,CharSequence)", "", "Argument[1]", "Argument[0]", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "writeAscii", "(ByteBufAllocator,CharSequence)", "", "Argument[1]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "writeShortBE", "(ByteBuf,int)", "", "Argument[0]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "writeMediumBE", "(ByteBuf,int)", "", "Argument[0]", "ReturnValue", "value", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "writeUtf8", "(ByteBuf,CharSequence)", "", "Argument[1]", "Argument[0]", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "writeUtf8", "(ByteBuf,CharSequence,int,int)", "", "Argument[1]", "Argument[0]", "taint", "manual"] + - ["io.netty.buffer", "ByteBufUtil", False, "writeUtf8", "(ByteBufAllocator,CharSequence)", "", "Argument[1]", "ReturnValue", "taint", "manual"] + - ["io.netty.buffer", "ByteBufInputStream", True, "ByteBufInputStream", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBufOutputStream", True, "ByteBufOutputStream", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.buffer", "ByteBufOutputStream", True, "buffer", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] \ No newline at end of file diff --git a/java/ql/lib/ext/io.netty.channel.model.yml b/java/ql/lib/ext/io.netty.channel.model.yml index e1125013a63..89bfd708360 100644 --- a/java/ql/lib/ext/io.netty.channel.model.yml +++ b/java/ql/lib/ext/io.netty.channel.model.yml @@ -12,3 +12,9 @@ extensions: - ["io.netty.channel", "DefaultChannelPipeline", False, "connect", "(SocketAddress,ChannelPromise)", "", "Argument[0]", "open-url", "ai-generated"] - ["io.netty.channel", "DefaultChannelPipeline", False, "connect", "(SocketAddress,SocketAddress,ChannelPromise)", "", "Argument[0]", "open-url", "ai-generated"] - ["io.netty.channel", "DefaultChannelPipeline", False, "connect", "(SocketAddress,SocketAddress)", "", "Argument[0]", "open-url", "ai-generated"] + - addsTo: + pack: codeql/java-all + extensible: sourceModel + data: + - ["io.netty.channel", "ChannelInboundHandler", True, "channelRead", "", "", "Parameter[1]", "remote", "manual"] + - ["io.netty.channel", "SimpleChannelInboundHandler", True, "channelRead0", "", "", "Parameter[1]", "remote", "manual"] diff --git a/java/ql/lib/ext/io.netty.handler.codec.base64.model.yml b/java/ql/lib/ext/io.netty.handler.codec.base64.model.yml new file mode 100644 index 00000000000..01ebb7bbe54 --- /dev/null +++ b/java/ql/lib/ext/io.netty.handler.codec.base64.model.yml @@ -0,0 +1,8 @@ +extensions: +- addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["io.netty.handler.codec.base64", "Base64", True, "decode", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.base64", "Base64", True, "encode", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + \ No newline at end of file diff --git a/java/ql/lib/ext/io.netty.handler.codec.http.cookie.model.yml b/java/ql/lib/ext/io.netty.handler.codec.http.cookie.model.yml new file mode 100644 index 00000000000..f8b189be18d --- /dev/null +++ b/java/ql/lib/ext/io.netty.handler.codec.http.cookie.model.yml @@ -0,0 +1,19 @@ +extensions: +- addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["io.netty.handler.codec.http.cookie", "Cookie", True, "domain", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.cookie", "Cookie", True, "name", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.cookie", "Cookie", True, "path", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.cookie", "Cookie", True, "value", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.cookie", "Cookie", True, "setDomain", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.cookie", "Cookie", True, "setPath", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.cookie", "Cookie", True, "setValue", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.cookie", "ServerCookieDecoder", True, "decode", "(String)", "", "Argument[0]", "ReturnValue.Element", "taint", "manual"] + - ["io.netty.handler.codec.http.cookie", "ServerCookieDecoder", True, "decodeAll", "(String)", "", "Argument[0]", "ReturnValue.Element", "taint", "manual"] + - ["io.netty.handler.codec.http.cookie", "ServerCookieEncoder", True, "encode", "(Cookie)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.cookie", "ServerCookieEncoder", True, "encode", "(Cookie[])", "", "Argument[0].ArrayElement", "ReturnValue.Element", "taint", "manual"] + - ["io.netty.handler.codec.http.cookie", "ServerCookieEncoder", True, "encode", "(Collection)", "", "Argument[0].Element", "ReturnValue.Element", "taint", "manual"] + - ["io.netty.handler.codec.http.cookie", "ServerCookieEncoder", True, "encode", "(Iterable)", "", "Argument[0].Element", "ReturnValue.Element", "taint", "manual"] + - ["io.netty.handler.codec.http.cookie", "ServerCookieEncoder", True, "encode", "(String,String)", "", "Argument[1..2]", "ReturnValue", "taint", "manual"] \ No newline at end of file diff --git a/java/ql/lib/ext/io.netty.handler.codec.http.model.yml b/java/ql/lib/ext/io.netty.handler.codec.http.model.yml index 6a4b0e7922e..fb283479dec 100644 --- a/java/ql/lib/ext/io.netty.handler.codec.http.model.yml +++ b/java/ql/lib/ext/io.netty.handler.codec.http.model.yml @@ -1,12 +1,83 @@ extensions: - - addsTo: - pack: codeql/java-all - extensible: sinkModel - data: - - ["io.netty.handler.codec.http", "DefaultFullHttpRequest", True, "DefaultFullHttpRequest", "(HttpVersion,HttpMethod,String,ByteBuf)", "", "Argument[2]", "open-url", "ai-generated"] - - ["io.netty.handler.codec.http", "DefaultHttpRequest", True, "DefaultHttpRequest", "(HttpVersion,HttpMethod,String)", "", "Argument[2]", "open-url", "ai-generated"] - - addsTo: - pack: codeql/java-all - extensible: summaryModel - data: - - ["io.netty.handler.codec.http", "QueryStringEncoder", True, "QueryStringEncoder", "(String)", "", "Argument[0]", "Argument[this]", "taint", "ai-generated"] +- addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["io.netty.handler.codec.http", "DefaultFullHttpRequest", True, "DefaultFullHttpRequest", "(HttpVersion,HttpMethod,String,ByteBuf)", "", "Argument[2]", "open-url", "ai-generated"] + - ["io.netty.handler.codec.http", "DefaultHttpRequest", True, "DefaultHttpRequest", "(HttpVersion,HttpMethod,String)", "", "Argument[2]", "open-url", "ai-generated"] +- addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["io.netty.handler.codec.http", "QueryStringEncoder", True, "QueryStringEncoder", "(String)", "", "Argument[0]", "Argument[this]", "taint", "ai-generated"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "add", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "add", "(CharSequence,Iterable)", "", "Argument[0]", "Argument[this].Element.MapKey", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "add", "(CharSequence,Iterable)", "", "Argument[1].Element", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "add", "(CharSequence,Object)", "", "Argument[0]", "Argument[this].Element.MapKey", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "add", "(CharSequence,Object)", "", "Argument[1]", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "add", "(String,Iterable)", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "add", "(String,Iterable)", "", "Argument[1].Element", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "add", "(String,Object)", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "add", "(String,Object)", "", "Argument[1]", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "add", "(HttpHeaders)", "", "Argument[0].Element.MapKey", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "add", "(HttpHeaders)", "", "Argument[0].Element.MapValue", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "addInt", "(CharSequence,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "addInt", "(CharSequence,int)", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "addShort", "(CharSequence,short)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "addShort", "(CharSequence,short)", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "copy", "()", "", "Argument[this].Element.MapKey", "ReturnValue.Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "copy", "()", "", "Argument[this].Element.MapValue", "ReturnValue.Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "entries", "()", "", "Argument[this].Element.MapKey", "ReturnValue.Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "entries", "()", "", "Argument[this].Element.MapValue", "ReturnValue.Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "get", "", "", "Argument[this].Element.MapValue", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "get", "", "", "Argument[1]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "getAll", "", "", "Argument[this].Element.MapValue", "ReturnValue.Element", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "getAllAsString", "", "", "Argument[this].Element.MapValue", "ReturnValue.Element", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "getAsString", "", "", "Argument[this].Element.MapValue", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "getHeader", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "getHeader", "", "", "Argument[2]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "getHost", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "getHost", "", "", "Argument[1]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "iteratorAsString", "()", "", "Argument[this].Element.MapKey", "ReturnValue.Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "iteratorAsString", "()", "", "Argument[this].Element.MapValue", "ReturnValue.Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "iteratorCharSequence", "()", "", "Argument[this].Element.MapKey", "ReturnValue.Element.MapKey", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "iteratorCharSequence", "()", "", "Argument[this].Element.MapValue", "ReturnValue.Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "names", "()", "", "Argument[this].Element.MapKey", "ReturnValue.Element", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "newEntity", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "remove", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "set", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "set", "(CharSequence,Iterable)", "", "Argument[0]", "Argument[this].Element.MapKey", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "set", "(CharSequence,Iterable)", "", "Argument[1].Element", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "set", "(CharSequence,Object)", "", "Argument[0]", "Argument[this].Element.MapKey", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "set", "(CharSequence,Object)", "", "Argument[1]", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "set", "(String,Iterable)", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "set", "(String,Iterable)", "", "Argument[1].Element", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "set", "(String,Object)", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "set", "(String,Object)", "", "Argument[1]", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "set", "(HttpHeaders)", "", "Argument[0].Element.MapKey", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "set", "(HttpHeaders)", "", "Argument[0].Element.MapValue", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "setAll", "(HttpHeaders)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "setAll", "(HttpHeaders)", "", "Argument[0].Element.MapKey", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "setAll", "(HttpHeaders)", "", "Argument[0].Element.MapValue", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "setInt", "(CharSequence,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "setInt", "(CharSequence,int)", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "setShort", "(CharSequence,short)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "setShort", "(CharSequence,short)", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "valueStringIterator", "(CharSequence)", "", "Argument[this].Element.MapValue", "ReturnValue.Element", "value", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "valueCharSequenceIterator", "(CharSequence)", "", "Argument[this].Element.MapValue", "ReturnValue.Element", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "toString", "", "", "Argument[this].Element.MapKey", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpHeaders", True, "toString", "", "", "Argument[this].Element.MapValue", "ReturnValue", "taint", "manual"] + # Currently all write steps to http messages are taint flow. It may reduce FPs to use a synthetic field for headers instead. + - ["io.netty.handler.codec.http", "HttpMessage", True, "headers", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "LastHttpContent", True, "trailingHeaders", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpRequest", True, "getUri", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpRequest", True, "uri", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "HttpRequest", True, "setUri", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http", "QueryStringDecoder", True, "QueryStringDecoder", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http", "QueryStringDecoder", True, "decodeComponent", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "QueryStringDecoder", True, "parameters", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "QueryStringDecoder", True, "path", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "QueryStringDecoder", True, "rawPath", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "QueryStringDecoder", True, "rawQuery", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "QueryStringDecoder", True, "toString", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http", "QueryStringDecoder", True, "uri", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/io.netty.handler.codec.http.multipart.model.yml b/java/ql/lib/ext/io.netty.handler.codec.http.multipart.model.yml index 5f0dceb85a0..3335994dec0 100644 --- a/java/ql/lib/ext/io.netty.handler.codec.http.multipart.model.yml +++ b/java/ql/lib/ext/io.netty.handler.codec.http.multipart.model.yml @@ -4,3 +4,40 @@ extensions: extensible: sinkModel data: - ["io.netty.handler.codec.http.multipart", "HttpPostRequestEncoder", True, "addBodyFileUpload", "(String,File,String,boolean)", "", "Argument[1]", "read-file", "ai-generated"] + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["io.netty.handler.codec.http.multipart", "InterfaceHttpPostRequestDecoder", True, "currentPartialHttpData", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "InterfaceHttpPostRequestDecoder", True, "getBodyHttpData", "(String)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "InterfaceHttpPostRequestDecoder", True, "getBodyHttpDatas", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "InterfaceHttpPostRequestDecoder", True, "getBodyHttpDatas", "(String)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "InterfaceHttpPostRequestDecoder", True, "next", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "InterfaceHttpPostRequestDecoder", True, "offer", "(HttpContent)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "InterfaceHttpPostRequestDecoder", True, "offer", "(HttpContent)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpPostRequestDecoder", True, "HttpPostRequestDecoder", "(HttpRequest)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpPostRequestDecoder", True, "HttpPostRequestDecoder", "(HttpDataFactory,HttpRequest)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpPostRequestDecoder", True, "HttpPostRequestDecoder", "(HttpDataFactory,HttpRequest,Charset)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpPostStandardRequestDecoder", True, "HttpPostStandardRequestDecoder", "(HttpRequest)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpPostStandardRequestDecoder", True, "HttpPostStandardRequestDecoder", "(HttpDataFactory,HttpRequest)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpPostStandardRequestDecoder", True, "HttpPostStandardRequestDecoder", "(HttpDataFactory,HttpRequest,Charset)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpPostMultipartRequestDecoder", True, "HttpPostMultipartRequestDecoder", "(HttpRequest)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpPostMultipartRequestDecoder", True, "HttpPostMultipartRequestDecoder", "(HttpDataFactory,HttpRequest)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpPostMultipartRequestDecoder", True, "HttpPostMultipartRequestDecoder", "(HttpDataFactory,HttpRequest,Charset)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "InterfaceHttpData", True, "getName", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpData", True, "addContent", "(ByteBuf,boolean)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpData", True, "get", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpData", True, "getByteBuf", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpData", True, "getChunk", "(int)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpData", True, "getString", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpData", True, "getString", "(Charset)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "Attribute", True, "getValue", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "Attribute", True, "setValue", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "FileUpload", True, "getContentTransferEncoding", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "FileUpload", True, "getContentType", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "FileUpload", True, "getFilename", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "FileUpload", True, "setContentTransferEncoding", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "FileUpload", True, "setContentType", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "FileUpload", True, "setFilename", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpData", True, "setContent", "(ByteBuf)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.multipart", "HttpData", True, "setContent", "(InputStream)", "", "Argument[0]", "Argument[this]", "taint", "manual"] diff --git a/java/ql/lib/ext/io.netty.handler.codec.http.websocketx.model.yml b/java/ql/lib/ext/io.netty.handler.codec.http.websocketx.model.yml new file mode 100644 index 00000000000..2ea3414c125 --- /dev/null +++ b/java/ql/lib/ext/io.netty.handler.codec.http.websocketx.model.yml @@ -0,0 +1,25 @@ +extensions: +- addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["io.netty.handler.codec.http.websocketx", "CloseWebSocketFrame", True, "CloseWebSocketFrame", "(boolean,int,ByteBuf)", "", "Argument[2]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "CloseWebSocketFrame", True, "CloseWebSocketFrame", "(boolean,int,int,String)", "", "Argument[3]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "CloseWebSocketFrame", True, "CloseWebSocketFrame", "(int,String)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "CloseWebSocketFrame", True, "CloseWebSocketFrame", "(WebSocketCloseStatus,String)", "", "Argument[1]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "CloseWebSocketFrame", True, "reasonText", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "BinaryWebSocketFrame", True, "BinaryWebSocketFrame", "(boolean,int,ByteBuf)", "", "Argument[2]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "BinaryWebSocketFrame", True, "BinaryWebSocketFrame", "(ByteBuf)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "ContinuationWebSocketFrame", True, "ContinuationWebSocketFrame", "(boolean,int,ByteBuf)", "", "Argument[2]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "ContinuationWebSocketFrame", True, "ContinuationWebSocketFrame", "(boolean,int,String)", "", "Argument[2]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "ContinuationWebSocketFrame", True, "ContinuationWebSocketFrame", "(ByteBuf)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "ContinuationWebSocketFrame", True, "text", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "PingWebSocketFrame", True, "PingWebSocketFrame", "(boolean,int,ByteBuf)", "", "Argument[2]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "PingWebSocketFrame", True, "PingWebSocketFrame", "(ByteBuf)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "PongWebSocketFrame", True, "PongWebSocketFrame", "(boolean,int,ByteBuf)", "", "Argument[2]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "PongWebSocketFrame", True, "PongWebSocketFrame", "(ByteBuf)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "TextWebSocketFrame", True, "TextWebSocketFrame", "(boolean,int,ByteBuf)", "", "Argument[2]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "TextWebSocketFrame", True, "TextWebSocketFrame", "(boolean,int,String)", "", "Argument[2]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "TextWebSocketFrame", True, "TextWebSocketFrame", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "TextWebSocketFrame", True, "TextWebSocketFrame", "(ByteBuf)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.handler.codec.http.websocketx", "TextWebSocketFrame", True, "text", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] \ No newline at end of file diff --git a/java/ql/lib/ext/io.netty.handler.codec.http2.model.yml b/java/ql/lib/ext/io.netty.handler.codec.http2.model.yml new file mode 100644 index 00000000000..bb84e7e43e2 --- /dev/null +++ b/java/ql/lib/ext/io.netty.handler.codec.http2.model.yml @@ -0,0 +1,49 @@ +extensions: +- addsTo: + pack: codeql/java-all + extensible: sourceModel + data: + - ["io.netty.handler.codec.http2", "Http2FrameListener", True, "onDataRead", "", "", "Parameter[2]", "remote", "manual"] + - ["io.netty.handler.codec.http2", "Http2FrameListener", True, "onHeadersRead", "", "", "Parameter[2]", "remote", "manual"] + - ["io.netty.handler.codec.http2", "Http2FrameListener", True, "onPushPromiseRead", "", "", "Parameter[3]", "remote", "manual"] + - ["io.netty.handler.codec.http2", "Http2FrameListener", True, "onUnknownFrame", "", "", "Parameter[4]", "remote", "manual"] +- addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["io.netty.handler.codec.http2", "Http2Headers", True, "authority", "()", "", "Argument[this].Element.MapValue", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http2", "Http2Headers", True, "authority", "(CharSequence)", "", "Argument[0]", "Argument[this].Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec.http2", "Http2Headers", True, "authority", "(CharSequence)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http2", "Http2Headers", True, "method", "()", "", "Argument[this].Element.MapValue", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http2", "Http2Headers", True, "method", "(CharSequence)", "", "Argument[0]", "Argument[this].Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec.http2", "Http2Headers", True, "method", "(CharSequence)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http2", "Http2Headers", True, "path", "()", "", "Argument[this].Element.MapValue", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http2", "Http2Headers", True, "path", "(CharSequence)", "", "Argument[0]", "Argument[this].Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec.http2", "Http2Headers", True, "path", "(CharSequence)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http2", "Http2Headers", True, "scheme", "()", "", "Argument[this].Element.MapValue", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http2", "Http2Headers", True, "scheme", "(CharSequence)", "", "Argument[0]", "Argument[this].Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec.http2", "Http2Headers", True, "scheme", "(CharSequence)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http2", "Http2Headers", True, "status", "()", "", "Argument[this].Element.MapValue", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http2", "Http2Headers", True, "status", "(CharSequence)", "", "Argument[0]", "Argument[this].Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec.http2", "Http2Headers", True, "status", "(CharSequence)", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec.http2", "Http2Headers", True, "valueIterator", "(CharSequence)", "", "Argument[this].Element.MapValue", "ReturnValue.Element", "value", "manual"] + - ["io.netty.handler.codec.http2", "Http2HeadersFrame", True, "headers", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http2", "Http2PushPromiseFrame", True, "http2Headers", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "addHttp2ToHttpHeaders", "(int,Http2Headers,FullHttpMessage,boolean)", "", "Argument[1].Element.MapKey", "Argument[2]", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "addHttp2ToHttpHeaders", "(int,Http2Headers,FullHttpMessage,boolean)", "", "Argument[1].Element.MapValue", "Argument[2]", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "addHttp2ToHttpHeaders", "(int,Http2Headers,HttpHeaders,HttpVersion,boolean,boolean)", "", "Argument[1].Element.MapKey", "Argument[2].Element.MapKey", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "addHttp2ToHttpHeaders", "(int,Http2Headers,HttpHeaders,HttpVersion,boolean,boolean)", "", "Argument[1].Element.MapValue", "Argument[2].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "toFullHttpRequest", "", "", "Argument[1].Element.MapKey", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "toFullHttpRequest", "", "", "Argument[1].Element.MapValue", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "toFullHttpRequest", "(int,Http2Headers,ByteBuf,boolean)", "", "Argument[2]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "toFullHttpResponse", "", "", "Argument[1].Element.MapKey", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "toFullHttpResponse", "", "", "Argument[1].Element.MapValue", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "toFullHttpResponse", "(int,Http2Headers,ByteBuf,boolean)", "", "Argument[2]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "toHttp2Headers", "(HttpHeaders,boolean)", "", "Argument[0].Element.MapKey", "ReturnValue.Element.MapKey", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "toHttp2Headers", "(HttpHeaders,boolean)", "", "Argument[0].Element.MapValue", "ReturnValue.Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "toHttp2Headers", "(HttpHeaders,Http2Headers)", "", "Argument[0].Element.MapKey", "Argument[1].Element.MapKey", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "toHttp2Headers", "(HttpHeaders,Http2Headers)", "", "Argument[0].Element.MapValue", "Argument[1].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "toHttpRequest", "", "", "Argument[1].Element.MapKey", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "toHttpRequest", "", "", "Argument[1].Element.MapValue", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "toHttpResponse", "", "", "Argument[1].Element.MapKey", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec.http2", "HttpConversionUtil", False, "toHttpResponse", "", "", "Argument[1].Element.MapValue", "ReturnValue", "taint", "manual"] \ No newline at end of file diff --git a/java/ql/lib/ext/io.netty.handler.codec.model.yml b/java/ql/lib/ext/io.netty.handler.codec.model.yml new file mode 100644 index 00000000000..b458fc09f8a --- /dev/null +++ b/java/ql/lib/ext/io.netty.handler.codec.model.yml @@ -0,0 +1,103 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sourceModel + data: + - ["io.netty.handler.codec", "ByteToMessageDecoder", True, "callDecode", "", "", "Parameter[1]", "remote", "manual"] + - ["io.netty.handler.codec", "ByteToMessageDecoder", True, "decode", "", "", "Parameter[1]", "remote", "manual"] + - ["io.netty.handler.codec", "ByteToMessageDecoder", True, "decodeLast", "", "", "Parameter[1]", "remote", "manual"] + - ["io.netty.handler.codec", "ByteToMessageCodec", True, "decode", "", "", "Parameter[1]", "remote", "manual"] + - ["io.netty.handler.codec", "ByteToMessageCodec", True, "decodeLast", "", "", "Parameter[1]", "remote", "manual"] + - ["io.netty.handler.codec", "MessageToMessageDecoder", True, "acceptInboundMessage", "", "", "Parameter[0]", "remote", "manual"] + - ["io.netty.handler.codec", "MessageToMessageDecoder", True, "decode", "", "", "Parameter[1]", "remote", "manual"] + - ["io.netty.handler.codec", "MessageToMessageCodec", True, "acceptInboundMessage", "", "", "Parameter[0]", "remote", "manual"] + - ["io.netty.handler.codec", "MessageToMessageCodec", True, "decode", "", "", "Parameter[1]", "remote", "manual"] + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["io.netty.handler.codec", "ByteToMessageDecoder$Cumulator", True, "cumulate", "(ByteBufAllocator,ByteBuf,ByteBuf)", "", "Argument[1..2]", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec", "HeadersUtils", False, "getAsString", "(Headers,Object)", "", "Argument[0].Element.MapValue", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec", "HeadersUtils", False, "getAllAsString", "(Headers,Object)", "", "Argument[0].Element.MapValue", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec", "HeadersUtils", False, "namesAsString", "(Headers)", "", "Argument[0].Element.MapKey", "ReturnValue.Element", "value", "manual"] + - ["io.netty.handler.codec", "HeadersUtils", False, "iteratorAsString", "(Iterable)", "", "Argument[0].Element.MapKey", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec", "HeadersUtils", False, "iteratorAsString", "(Iterable)", "", "Argument[0].Element.MapValue", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec", "HeadersUtils", False, "toString", "(Class,Iterator,int)", "", "Argument[1].Element.MapKey", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec", "HeadersUtils", False, "toString", "(Class,Iterator,int)", "", "Argument[1].Element.MapValue", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec", "Headers", True, "get", "(Object)", "", "Argument[this].Element.MapValue", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec", "Headers", True, "get", "(Object,Object)", "", "Argument[this].Element.MapValue", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec", "Headers", True, "get", "(Object,Object)", "", "Argument[1]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "getAll", "(Object)", "", "Argument[this].Element.MapValue", "ReturnValue.Element", "taint", "manual"] + - ["io.netty.handler.codec", "Headers", True, "getAllAndRemove", "(Object)", "", "Argument[this].Element.MapValue", "ReturnValue.Element", "taint", "manual"] + - ["io.netty.handler.codec", "Headers", True, "getAndRemove", "(Object)", "", "Argument[this].Element.MapValue", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec", "Headers", True, "getAndRemove", "(Object)", "", "Argument[this].Element.MapValue", "ReturnValue", "taint", "manual"] + - ["io.netty.handler.codec", "Headers", True, "getAndRemove", "(Object,Object)", "", "Argument[1]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "names", "()", "", "Argument[this].Element.MapKey", "ReturnValue.Element", "taint", "manual"] + - ["io.netty.handler.codec", "Headers", True, "add", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "add", "(Headers)", "", "Argument[0].Element.MapKey", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "add", "(Headers)", "", "Argument[0].Element.MapValue", "Argument[this].Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "add", "(Object,Iterable)", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "add", "(Object,Iterable)", "", "Argument[1].Element", "Argument[this].Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "add", "(Object,Object[])", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "add", "(Object,Object[])", "", "Argument[1].ArrayElement", "Argument[this].Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "add", "(Object,Object)", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "add", "(Object,Object)", "", "Argument[1]", "Argument[this].Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addObject", "(Object,Iterable)", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addObject", "(Object,Iterable)", "", "Argument[1].Element", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addObject", "(Object,Object[])", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addObject", "(Object,Object[])", "", "Argument[1].ArrayElement", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addObject", "(Object,Object)", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addObject", "(Object,Object)", "", "Argument[1]", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addBoolean", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addBoolean", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addByte", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addByte", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addChar", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addChar", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addDouble", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addDouble", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addFloat", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addFloat", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addInt", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addInt", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addLong", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addLong", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addShort", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addShort", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addTimeMillis", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "addTimeMillis", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "set", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "set", "(Headers)", "", "Argument[0].Element.MapKey", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "set", "(Headers)", "", "Argument[0].Element.MapValue", "Argument[this].Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "set", "(Object,Iterable)", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "set", "(Object,Iterable)", "", "Argument[1].Element", "Argument[this].Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "set", "(Object,Object[])", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "set", "(Object,Object[])", "", "Argument[1].ArrayElement", "Argument[this].Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "set", "(Object,Object)", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "set", "(Object,Object)", "", "Argument[1]", "Argument[this].Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setAll", "(Headers)", "", "Argument[0].Element.MapKey", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setAll", "(Headers)", "", "Argument[0].Element.MapValue", "Argument[this].Element.MapValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setObject", "(Object,Iterable)", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setObject", "(Object,Iterable)", "", "Argument[1].Element", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setObject", "(Object,Object[])", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setObject", "(Object,Object[])", "", "Argument[1].ArrayElement", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setObject", "(Object,Object)", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setObject", "(Object,Object)", "", "Argument[1]", "Argument[this].Element.MapValue", "taint", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setBoolean", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setBoolean", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setByte", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setByte", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setChar", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setChar", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setDouble", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setDouble", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setFloat", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setFloat", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setInt", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setInt", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setLong", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setLong", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setShort", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setShort", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setTimeMillis", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.handler.codec", "Headers", True, "setTimeMillis", "", "", "Argument[0]", "Argument[this].Element.MapKey", "value", "manual"] diff --git a/java/ql/lib/ext/io.netty.util.model.yml b/java/ql/lib/ext/io.netty.util.model.yml new file mode 100644 index 00000000000..9b9b0be3f5a --- /dev/null +++ b/java/ql/lib/ext/io.netty.util.model.yml @@ -0,0 +1,27 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["io.netty.util", "ReferenceCounted", True, "retain", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.util", "ReferenceCounted", True, "touch", "", "", "Argument[this]", "ReturnValue", "value", "manual"] + - ["io.netty.util", "AsciiString", False, "AsciiString", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "array", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "cached", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "concat", "(CharSequence)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "concat", "(CharSequence)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "copy", "(int,byte[],int,int)", "", "Argument[this]", "Argument[1]", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "copy", "(int,char[],int,int)", "", "Argument[this]", "Argument[1]", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "of", "(CharSequence)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "replace", "(char,char)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "split", "(char)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "split", "(String,int)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "split", "(char)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "subSequence", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "toByteArray", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "toCharArray", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "toString", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "toLowerCase", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "toUpperCase", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "trim", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["io.netty.util", "AsciiString", False, "trim", "(CharSequence)", "", "Argument[0]", "ReturnValue", "taint", "manual"] \ No newline at end of file diff --git a/java/ql/lib/ext/java.awt.model.yml b/java/ql/lib/ext/java.awt.model.yml new file mode 100644 index 00000000000..4bbbc3738cf --- /dev/null +++ b/java/ql/lib/ext/java.awt.model.yml @@ -0,0 +1,16 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["java.awt", "Container", True, "add", "(Component)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] + - ["java.awt", "Container", True, "add", "(Component)", "", "Argument[0]", "ReturnValue", "value", "manual"] + - ["java.awt", "Container", True, "add", "(Component,Object)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] + + - addsTo: + pack: codeql/java-all + extensible: neutralModel + data: + # The below APIs have numeric flow and are currently being stored as neutral models. + # These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future. + - ["java.awt", "Insets", "Insets", "(int,int,int,int)", "manual"] # value-numeric diff --git a/java/ql/lib/ext/java.io.model.yml b/java/ql/lib/ext/java.io.model.yml index 4ba64033fa4..a14f4fe7782 100644 --- a/java/ql/lib/ext/java.io.model.yml +++ b/java/ql/lib/ext/java.io.model.yml @@ -69,6 +69,9 @@ extensions: - ["java.io", "File", True, "getCanonicalFile", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["java.io", "File", True, "getCanonicalPath", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["java.io", "File", True, "getName", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["java.io", "File", True, "getParentFile", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["java.io", "File", True, "getPath", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["java.io", "File", True, "listFiles", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["java.io", "File", True, "toPath", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["java.io", "File", True, "toString", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["java.io", "File", True, "toURI", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] @@ -88,9 +91,28 @@ extensions: - ["java.io", "OutputStream", True, "write", "(int)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["java.io", "Reader", True, "read", "", "", "Argument[this]", "Argument[0]", "taint", "manual"] - ["java.io", "StringReader", False, "StringReader", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["java.io", "StringWriter", False, "toString", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["java.io", "UncheckedIOException", False, "UncheckedIOException", "(IOException)", "", "Argument[0]", "Argument[this].SyntheticField[java.lang.Throwable.cause]", "value", "manual"] - ["java.io", "Writer", True, "write", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] - addsTo: pack: codeql/java-all extensible: neutralModel data: + - ["java.io", "Closeable", "close", "()", "manual"] + - ["java.io", "DataOutput", "writeBoolean", "(boolean)", "manual"] + - ["java.io", "File", "delete", "()", "manual"] - ["java.io", "File", "exists", "()", "manual"] + - ["java.io", "File", "isFile", "()", "manual"] + - ["java.io", "File", "length", "()", "manual"] + - ["java.io", "File", "isDirectory", "()", "manual"] + - ["java.io", "File", "mkdirs", "()", "manual"] + - ["java.io", "FileInputStream", "FileInputStream", "(File)", "manual"] + - ["java.io", "InputStream", "close", "()", "manual"] + - ["java.io", "OutputStream", "flush", "()", "manual"] + + # The below APIs have numeric flow and are currently being stored as neutral models. + # These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future. + - ["java.io", "DataInput", "readInt", "()", "manual"] # taint-numeric + - ["java.io", "DataInput", "readLong", "()", "manual"] # taint-numeric + - ["java.io", "DataOutput", "writeInt", "(int)", "manual"] # taint-numeric + - ["java.io", "DataOutput", "writeLong", "(long)", "manual"] # taint-numeric diff --git a/java/ql/lib/ext/java.lang.invoke.model.yml b/java/ql/lib/ext/java.lang.invoke.model.yml new file mode 100644 index 00000000000..16259190a02 --- /dev/null +++ b/java/ql/lib/ext/java.lang.invoke.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: neutralModel + data: + - ["java.lang.invoke", "MethodHandles", "lookup", "()", "manual"] diff --git a/java/ql/lib/ext/java.lang.model.yml b/java/ql/lib/ext/java.lang.model.yml index 774cf751a13..f1b84ae70b6 100644 --- a/java/ql/lib/ext/java.lang.model.yml +++ b/java/ql/lib/ext/java.lang.model.yml @@ -37,6 +37,8 @@ extensions: - ["java.lang", "AbstractStringBuilder", True, "AbstractStringBuilder", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["java.lang", "AbstractStringBuilder", True, "append", "", "", "Argument[this]", "ReturnValue", "value", "manual"] - ["java.lang", "AbstractStringBuilder", True, "append", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] + # When `WithoutElement` is implemented for Java, `java.lang.AbstractStringBuilder#delete` might require a `taint` step of the form `Argument[this].WithoutElement -> Argument[this]` in addition to the below `value` step. + - ["java.lang", "AbstractStringBuilder", True, "delete", "(int,int)", "", "Argument[this]", "ReturnValue", "value", "manual"] - ["java.lang", "AbstractStringBuilder", True, "getChars", "", "", "Argument[this]", "Argument[2]", "taint", "manual"] - ["java.lang", "AbstractStringBuilder", True, "insert", "", "", "Argument[this]", "ReturnValue", "value", "manual"] - ["java.lang", "AbstractStringBuilder", True, "insert", "", "", "Argument[1]", "Argument[this]", "taint", "manual"] @@ -48,16 +50,21 @@ extensions: - ["java.lang", "AbstractStringBuilder", True, "toString", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["java.lang", "Appendable", True, "append", "", "", "Argument[this]", "ReturnValue", "value", "manual"] - ["java.lang", "Appendable", True, "append", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["java.lang", "AssertionError", False, "AssertionError", "(Object)", "", "Argument[0]", "Argument[this].SyntheticField[java.lang.Throwable.message]", "value", "manual"] - ["java.lang", "CharSequence", True, "charAt", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["java.lang", "CharSequence", True, "subSequence", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["java.lang", "CharSequence", True, "toString", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - ["java.lang", "Class", False, "cast", "(Object)", "", "Argument[0]", "ReturnValue", "value", "manual"] - ["java.lang", "Exception", False, "Exception", "(String)", "", "Argument[0]", "Argument[this].SyntheticField[java.lang.Throwable.message]", "value", "manual"] + - ["java.lang", "Exception", False, "Exception", "(String,Throwable)", "", "Argument[0]", "Argument[this].SyntheticField[java.lang.Throwable.message]", "value", "manual"] + - ["java.lang", "Exception", False, "Exception", "(String,Throwable)", "", "Argument[1]", "Argument[this].SyntheticField[java.lang.Throwable.cause]", "value", "manual"] - ["java.lang", "IllegalArgumentException", False, "IllegalArgumentException", "(String)", "", "Argument[0]", "Argument[this].SyntheticField[java.lang.Throwable.message]", "value", "manual"] - ["java.lang", "IllegalStateException", False, "IllegalStateException", "(String)", "", "Argument[0]", "Argument[this].SyntheticField[java.lang.Throwable.message]", "value", "manual"] - ["java.lang", "IndexOutOfBoundsException", False, "IndexOutOfBoundsException", "(String)", "", "Argument[0]", "Argument[this].SyntheticField[java.lang.Throwable.message]", "value", "manual"] - ["java.lang", "Iterable", True, "forEach", "(Consumer)", "", "Argument[this].Element", "Argument[0].Parameter[0]", "value", "manual"] - ["java.lang", "Iterable", True, "iterator", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"] - ["java.lang", "Iterable", True, "spliterator", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"] + - ["java.lang", "NullPointerException", False, "NullPointerException", "(String)", "", "Argument[0]", "Argument[this].SyntheticField[java.lang.Throwable.message]", "value", "manual"] - ["java.lang", "Object", True, "clone", "", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"] - ["java.lang", "Object", True, "clone", "", "", "Argument[this].MapKey", "ReturnValue.MapKey", "value", "manual"] - ["java.lang", "Object", True, "clone", "", "", "Argument[this].MapValue", "ReturnValue.MapValue", "value", "manual"] @@ -107,50 +114,105 @@ extensions: - ["java.lang", "StringBuffer", True, "StringBuffer", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["java.lang", "StringBuilder", True, "StringBuilder", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["java.lang", "System", False, "arraycopy", "", "", "Argument[0]", "Argument[2]", "taint", "manual"] + - ["java.lang", "Thread", False, "Thread", "(Runnable)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["java.lang", "Thread", False, "Thread", "(String)", "", "Argument[0]", "Argument[this].SyntheticField[java.lang.Thread.name]", "value", "manual"] + - ["java.lang", "Thread", True, "getName", "()", "", "Argument[this].SyntheticField[java.lang.Thread.name]", "ReturnValue", "value", "manual"] + - ["java.lang", "ThreadLocal", True, "get", "()", "", "Argument[this].SyntheticField[java.lang.ThreadLocal.value]", "ReturnValue", "value", "manual"] + - ["java.lang", "ThreadLocal", True, "set", "(Object)", "", "Argument[0]", "Argument[this].SyntheticField[java.lang.ThreadLocal.value]", "value", "manual"] - ["java.lang", "Throwable", False, "Throwable", "(Throwable)", "", "Argument[0]", "Argument[this].SyntheticField[java.lang.Throwable.cause]", "value", "manual"] + - ["java.lang", "Throwable", False, "Throwable", "(String)", "", "Argument[0]", "Argument[this].SyntheticField[java.lang.Throwable.message]", "value", "manual"] - ["java.lang", "Throwable", True, "getCause", "()", "", "Argument[this].SyntheticField[java.lang.Throwable.cause]", "ReturnValue", "value", "manual"] - ["java.lang", "Throwable", True, "getMessage", "()", "", "Argument[this].SyntheticField[java.lang.Throwable.message]", "ReturnValue", "value", "manual"] + - ["java.lang", "Throwable", True, "getLocalizedMessage", "()", "", "Argument[this].SyntheticField[java.lang.Throwable.message]", "ReturnValue", "value", "manual"] + - ["java.lang", "Throwable", True, "toString", "()", "", "Argument[this].SyntheticField[java.lang.Throwable.message]", "ReturnValue", "taint", "manual"] + - addsTo: pack: codeql/java-all extensible: neutralModel data: - ["java.lang", "AbstractStringBuilder", "length", "()", "manual"] + - ["java.lang", "AbstractStringBuilder", "setCharAt", "(int,char)", "manual"] + - ["java.lang", "AbstractStringBuilder", "setLength", "(int)", "manual"] + - ["java.lang", "Boolean", "booleanValue", "()", "manual"] - ["java.lang", "Boolean", "equals", "(Object)", "manual"] + - ["java.lang", "Boolean", "parseBoolean", "(String)", "manual"] + - ["java.lang", "Boolean", "valueOf", "(boolean)", "manual"] + - ["java.lang", "CharSequence", "length", "()", "manual"] + - ["java.lang", "Class", "forName", "(String)", "manual"] + - ["java.lang", "Class", "getCanonicalName", "()", "manual"] - ["java.lang", "Class", "getClassLoader", "()", "manual"] + - ["java.lang", "Class", "getDeclaredConstructor", "(Class[])", "manual"] # This model may be changed to a taint step for an unsafe reflection query in the future. + - ["java.lang", "Class", "getDeclaredField", "(String)", "manual"] # This model may be changed to a taint step for an unsafe reflection query in the future. + - ["java.lang", "Class", "getMethod", "(String,Class[])", "manual"] # This model may be changed to a taint step for an unsafe reflection query in the future. - ["java.lang", "Class", "getName", "()", "manual"] + - ["java.lang", "Class", "getResource", "(String)", "manual"] + - ["java.lang", "Class", "getResourceAsStream", "(String)", "manual"] - ["java.lang", "Class", "getSimpleName", "()", "manual"] - ["java.lang", "Class", "isAssignableFrom", "(Class)", "manual"] + - ["java.lang", "Class", "isInstance", "(Object)", "manual"] + - ["java.lang", "Class", "toString", "()", "manual"] + - ["java.lang", "ClassLoader", "getResource", "(String)", "manual"] + - ["java.lang", "ClassLoader", "getResourceAsStream", "(String)", "manual"] - ["java.lang", "Enum", "Enum", "(String,int)", "manual"] - ["java.lang", "Enum", "equals", "(Object)", "manual"] + - ["java.lang", "Enum", "hashCode", "()", "manual"] - ["java.lang", "Enum", "name", "()", "manual"] + - ["java.lang", "Enum", "ordinal", "()", "manual"] - ["java.lang", "Enum", "toString", "()", "manual"] + - ["java.lang", "Integer", "equals", "(Object)", "manual"] - ["java.lang", "Long", "equals", "(Object)", "manual"] - ["java.lang", "Object", "equals", "(Object)", "manual"] - ["java.lang", "Object", "getClass", "()", "manual"] - ["java.lang", "Object", "hashCode", "()", "manual"] - ["java.lang", "Object", "toString", "()", "manual"] + - ["java.lang", "Runnable", "run", "()", "manual"] + - ["java.lang", "Runtime", "getRuntime", "()", "manual"] + - ["java.lang", "String", "compareTo", "(String)", "manual"] - ["java.lang", "String", "contains", "(CharSequence)", "manual"] - ["java.lang", "String", "endsWith", "(String)", "manual"] - ["java.lang", "String", "equals", "(Object)", "manual"] - ["java.lang", "String", "equalsIgnoreCase", "(String)", "manual"] - ["java.lang", "String", "hashCode", "()", "manual"] + - ["java.lang", "String", "indexOf", "(int)", "manual"] - ["java.lang", "String", "indexOf", "(String)", "manual"] - ["java.lang", "String", "isEmpty", "()", "manual"] + - ["java.lang", "String", "lastIndexOf", "(int)", "manual"] + - ["java.lang", "String", "lastIndexOf", "(String)", "manual"] - ["java.lang", "String", "length", "()", "manual"] - ["java.lang", "String", "startsWith", "(String)", "manual"] + - ["java.lang", "String", "valueOf", "(boolean)", "manual"] - ["java.lang", "System", "currentTimeMillis", "()", "manual"] + - ["java.lang", "System", "exit", "(int)", "manual"] + - ["java.lang", "System", "getenv", "(String)", "manual"] + - ["java.lang", "System", "identityHashCode", "(Object)", "manual"] + - ["java.lang", "System", "lineSeparator", "()", "manual"] - ["java.lang", "System", "nanoTime", "()", "manual"] - ["java.lang", "Thread", "currentThread", "()", "manual"] + - ["java.lang", "Thread", "getContextClassLoader", "()", "manual"] + - ["java.lang", "Thread", "interrupt", "()", "manual"] - ["java.lang", "Thread", "sleep", "(long)", "manual"] + - ["java.lang", "Thread", "start", "()", "manual"] # The below APIs have numeric flow and are currently being stored as neutral models. # These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future. - - ["java.lang", "Integer", "intValue", "()", "manual"] # taint-numeric - - ["java.lang", "Integer", "parseInt", "(String)", "manual"] # taint-numeric - - ["java.lang", "Integer", "toString", "(int)", "manual"] # taint-numeric - - ["java.lang", "Integer", "valueOf", "(int)", "manual"] # taint-numeric - - ["java.lang", "Long", "longValue", "()", "manual"] # taint-numeric - - ["java.lang", "Long", "parseLong", "(String)", "manual"] # taint-numeric - - ["java.lang", "Long", "toString", "()", "manual"] # taint-numeric - - ["java.lang", "Math", "min", "(int,int)", "manual"] # value-numeric - - ["java.lang", "String", "valueOf", "(int)", "manual"] # taint-numeric - - ["java.lang", "String", "valueOf", "(long)", "manual"] # taint-numeric + - ["java.lang", "Double", "doubleToLongBits", "(double)", "manual"] # taint-numeric + - ["java.lang", "Double", "parseDouble", "(String)", "manual"] # taint-numeric + - ["java.lang", "Double", "valueOf", "(double)", "manual"] # taint-numeric + - ["java.lang", "Integer", "Integer", "(int)", "manual"] # taint-numeric + - ["java.lang", "Integer", "intValue", "()", "manual"] # taint-numeric + - ["java.lang", "Integer", "parseInt", "(String)", "manual"] # taint-numeric + - ["java.lang", "Integer", "toHexString", "(int)", "manual"] # taint-numeric + - ["java.lang", "Integer", "toString", "", "manual"] # taint-numeric + - ["java.lang", "Integer", "valueOf", "", "manual"] # taint-numeric + - ["java.lang", "Long", "Long", "(long)", "manual"] # taint-numeric + - ["java.lang", "Long", "intValue", "()", "manual"] # taint-numeric + - ["java.lang", "Long", "longValue", "()", "manual"] # taint-numeric + - ["java.lang", "Long", "parseLong", "(String)", "manual"] # taint-numeric + - ["java.lang", "Long", "toString", "", "manual"] # taint-numeric + - ["java.lang", "Long", "valueOf", "", "manual"] # taint-numeric + - ["java.lang", "Math", "max", "", "manual"] # value-numeric + - ["java.lang", "Math", "min", "", "manual"] # value-numeric + - ["java.lang", "Number", "doubleValue", "()", "manual"] # taint-numeric + - ["java.lang", "Number", "intValue", "()", "manual"] # taint-numeric + - ["java.lang", "Number", "longValue", "()", "manual"] # taint-numeric + - ["java.lang", "String", "valueOf", "(int)", "manual"] # taint-numeric + - ["java.lang", "String", "valueOf", "(long)", "manual"] # taint-numeric diff --git a/java/ql/lib/ext/java.lang.reflect.model.yml b/java/ql/lib/ext/java.lang.reflect.model.yml new file mode 100644 index 00000000000..9430807d00b --- /dev/null +++ b/java/ql/lib/ext/java.lang.reflect.model.yml @@ -0,0 +1,10 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: neutralModel + data: + # The below models may be changed to taint steps for an unsafe reflection query in the future. + - ["java.lang.reflect", "Constructor", "newInstance", "(Object[])", "manual"] + - ["java.lang.reflect", "Field", "get", "(Object)", "manual"] + - ["java.lang.reflect", "Method", "getName", "()", "manual"] + - ["java.lang.reflect", "Method", "invoke", "(Object,Object[])", "manual"] diff --git a/java/ql/lib/ext/java.math.model.yml b/java/ql/lib/ext/java.math.model.yml index 1d45a4076bf..b3ee529339f 100644 --- a/java/ql/lib/ext/java.math.model.yml +++ b/java/ql/lib/ext/java.math.model.yml @@ -7,6 +7,16 @@ extensions: # The below APIs have numeric flow and are currently being stored as neutral models. # These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future. - - ["java.math", "BigDecimal", "BigDecimal", "(String)", "manual"] # taint-numeric - - ["java.math", "BigDecimal", "valueOf", "(double)", "manual"] # taint-numeric - - ["java.math", "BigDecimal", "valueOf", "(long)", "manual"] # taint-numeric + - ["java.math", "BigDecimal", "BigDecimal", "", "manual"] # taint-numeric + - ["java.math", "BigDecimal", "add", "(BigDecimal)", "manual"] # taint-numeric + - ["java.math", "BigDecimal", "doubleValue", "()", "manual"] # taint-numeric + - ["java.math", "BigDecimal", "intValue", "()", "manual"] # taint-numeric + - ["java.math", "BigDecimal", "multiply", "(BigDecimal)", "manual"] # taint-numeric + - ["java.math", "BigDecimal", "setScale", "(int,RoundingMode)", "manual"] # taint-numeric + - ["java.math", "BigDecimal", "subtract", "(BigDecimal)", "manual"] # taint-numeric + - ["java.math", "BigDecimal", "toBigInteger", "()", "manual"] # taint-numeric + - ["java.math", "BigDecimal", "toString", "()", "manual"] # taint-numeric + - ["java.math", "BigDecimal", "valueOf", "", "manual"] # taint-numeric + - ["java.math", "BigInteger", "BigInteger", "(String)", "manual"] # taint-numeric + - ["java.math", "BigInteger", "or", "(BigInteger)", "manual"] # taint-numeric + - ["java.math", "BigInteger", "valueOf", "(long)", "manual"] # taint-numeric diff --git a/java/ql/lib/ext/java.nio.charset.model.yml b/java/ql/lib/ext/java.nio.charset.model.yml new file mode 100644 index 00000000000..16e8943f99c --- /dev/null +++ b/java/ql/lib/ext/java.nio.charset.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: neutralModel + data: + - ["java.nio.charset", "Charset", "name", "()", "manual"] diff --git a/java/ql/lib/ext/java.nio.file.model.yml b/java/ql/lib/ext/java.nio.file.model.yml index cca00413c33..6c5c2d13f96 100644 --- a/java/ql/lib/ext/java.nio.file.model.yml +++ b/java/ql/lib/ext/java.nio.file.model.yml @@ -43,6 +43,7 @@ extensions: - ["java.nio.file", "FileSystem", True, "getPath", "(String,String[])", "", "Argument[1]", "ReturnValue", "taint", "ai-generated"] - ["java.nio.file", "FileSystem", True, "getPathMatcher", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] - ["java.nio.file", "FileSystem", True, "getRootDirectories", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["java.nio.file", "Path", True, "getFileName", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["java.nio.file", "Path", True, "getParent", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["java.nio.file", "Path", True, "normalize", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["java.nio.file", "Path", True, "of", "(String,String[])", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] @@ -61,3 +62,9 @@ extensions: # - ["java.nio.file", "Files", True, "walkFileTree", "(Path,FileVisitor)", "", "Argument[0]", "Argument[1].Method[preVisitDirectory(Path,BasicFileAttributes)].Parameter[0]", "taint", "ai-generated"] # - ["java.nio.file", "Files", True, "walkFileTree", "(Path,FileVisitor)", "", "Argument[0]" "Argument[1].Method[visitFile(Path,BasicFileAttributes)].Parameter[0]", "taint", "ai-generated"] # - ["java.nio.file", "Files", True, "walkFileTree", "(Path,FileVisitor)", "", "Argument[0]", "Argument[1].Method[visitFileFailed(Path,IOException)].Parameter[0]", "taint", "ai-generated"] + + - addsTo: + pack: codeql/java-all + extensible: neutralModel + data: + - ["java.nio.file", "Files", "exists", "(Path,LinkOption[])", "manual"] diff --git a/java/ql/lib/ext/java.nio.model.yml b/java/ql/lib/ext/java.nio.model.yml index 675b85bf766..d64d4809c5c 100644 --- a/java/ql/lib/ext/java.nio.model.yml +++ b/java/ql/lib/ext/java.nio.model.yml @@ -6,3 +6,11 @@ extensions: - ["java.nio", "ByteBuffer", False, "array", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["java.nio", "ByteBuffer", False, "get", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["java.nio", "ByteBuffer", False, "wrap", "(byte[])", "", "Argument[0]", "ReturnValue", "taint", "manual"] + + - addsTo: + pack: codeql/java-all + extensible: neutralModel + data: + - ["java.nio", "Buffer", "position", "()", "manual"] + - ["java.nio", "Buffer", "remaining", "()", "manual"] + - ["java.nio", "ByteBuffer", "allocate", "(int)", "manual"] diff --git a/java/ql/lib/ext/java.sql.model.yml b/java/ql/lib/ext/java.sql.model.yml index e5516043989..7c8174fca43 100644 --- a/java/ql/lib/ext/java.sql.model.yml +++ b/java/ql/lib/ext/java.sql.model.yml @@ -20,14 +20,28 @@ extensions: pack: codeql/java-all extensible: summaryModel data: + - ["java.sql", "Connection", True, "nativeSQL", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["java.sql", "PreparedStatement", True, "setString", "(int,String)", "", "Argument[1]", "Argument[this]", "value", "manual"] - ["java.sql", "ResultSet", True, "getString", "(String)", "", "Argument[this]", "ReturnValue", "taint", "manual"] + - addsTo: pack: codeql/java-all extensible: neutralModel data: + - ["java.sql", "Connection", "createStatement", "()", "manual"] + - ["java.sql", "PreparedStatement", "executeUpdate", "()", "manual"] + - ["java.sql", "PreparedStatement", "executeQuery", "()", "manual"] - ["java.sql", "ResultSet", "next", "()", "manual"] + - ["java.sql", "Statement", "close", "()", "manual"] + # The below APIs have numeric flow and are currently being stored as neutral models. # These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future. - - ["java.sql", "PreparedStatement", "setInt", "(int,int)", "manual"] # value-numeric - - ["java.sql", "ResultSet", "getInt", "(String)", "manual"] # taint-numeric + - ["java.sql", "PreparedStatement", "setInt", "(int,int)", "manual"] # value-numeric + - ["java.sql", "PreparedStatement", "setLong", "(int,long)", "manual"] # value-numeric + - ["java.sql", "ResultSet", "getInt", "(int)", "manual"] # taint-numeric + - ["java.sql", "ResultSet", "getInt", "(String)", "manual"] # taint-numeric + - ["java.sql", "ResultSet", "getLong", "(String)", "manual"] # taint-numeric + - ["java.sql", "ResultSet", "getString", "(int)", "manual"] # taint-numeric, potentially interesting for second order SQL injection + - ["java.sql", "ResultSet", "getTimestamp", "(String)", "manual"] # taint-numeric + - ["java.sql", "Timestamp", "Timestamp", "(long)", "manual"] # taint-numeric + - ["java.sql", "Timestamp", "getTime", "()", "manual"] # taint-numeric diff --git a/java/ql/lib/ext/java.text.model.yml b/java/ql/lib/ext/java.text.model.yml index bbb01596f17..86099195f46 100644 --- a/java/ql/lib/ext/java.text.model.yml +++ b/java/ql/lib/ext/java.text.model.yml @@ -6,4 +6,5 @@ extensions: # The below APIs have numeric flow and are currently being stored as neutral models. # These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future. - ["java.text", "DateFormat", "format", "(Date)", "manual"] # taint-numeric + - ["java.text", "DateFormat", "parse", "(String)", "manual"] # taint-numeric - ["java.text", "SimpleDateFormat", "SimpleDateFormat", "(String)", "manual"] # taint-numeric diff --git a/java/ql/lib/ext/java.time.chrono.model.yml b/java/ql/lib/ext/java.time.chrono.model.yml new file mode 100644 index 00000000000..b222058d932 --- /dev/null +++ b/java/ql/lib/ext/java.time.chrono.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: neutralModel + data: + - ["java.time.chrono", "ChronoZonedDateTime", "toInstant", "()", "manual"] diff --git a/java/ql/lib/ext/java.time.format.model.yml b/java/ql/lib/ext/java.time.format.model.yml new file mode 100644 index 00000000000..5cfb255733c --- /dev/null +++ b/java/ql/lib/ext/java.time.format.model.yml @@ -0,0 +1,7 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: neutralModel + data: + - ["java.time.format", "DateTimeFormatter", "format", "(TemporalAccessor)", "manual"] + - ["java.time.format", "DateTimeFormatter", "ofPattern", "(String)", "manual"] diff --git a/java/ql/lib/ext/java.time.model.yml b/java/ql/lib/ext/java.time.model.yml index 002240c6488..7f12490964d 100644 --- a/java/ql/lib/ext/java.time.model.yml +++ b/java/ql/lib/ext/java.time.model.yml @@ -4,8 +4,22 @@ extensions: extensible: neutralModel data: - ["java.time", "Instant", "now", "()", "manual"] + - ["java.time", "LocalDate", "now", "()", "manual"] + - ["java.time", "LocalDateTime", "now", "()", "manual"] - ["java.time", "ZonedDateTime", "now", "()", "manual"] + - ["java.time", "ZoneId", "of", "(String)", "manual"] + - ["java.time", "ZoneId", "systemDefault", "()", "manual"] # The below APIs have numeric flow and are currently being stored as neutral models. # These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future. - - ["java.time", "LocalDate", "of", "(int,int,int)", "manual"] # taint-numeric + - ["java.time", "Duration", "ofMillis", "(long)", "manual"] # taint-numeric + - ["java.time", "Duration", "ofMinutes", "(long)", "manual"] # taint-numeric + - ["java.time", "Duration", "ofSeconds", "(long)", "manual"] # taint-numeric + - ["java.time", "Duration", "toMillis", "()", "manual"] # taint-numeric + - ["java.time", "Instant", "ofEpochMilli", "(long)", "manual"] # taint-numeric + - ["java.time", "Instant", "parse", "(CharSequence)", "manual"] # taint-numeric + - ["java.time", "Instant", "toEpochMilli", "()", "manual"] # taint-numeric + - ["java.time", "LocalDate", "plusDays", "(long)", "manual"] # taint-numeric + - ["java.time", "LocalDate", "of", "(int,int,int)", "manual"] # taint-numeric + - ["java.time", "LocalDate", "parse", "(CharSequence)", "manual"] # taint-numeric + - ["java.time", "LocalDateTime", "of", "(int,int,int,int,int,int)", "manual"] # taint-numeric diff --git a/java/ql/lib/ext/java.util.concurrent.atomic.model.yml b/java/ql/lib/ext/java.util.concurrent.atomic.model.yml index b4b49273790..b92ed441ade 100644 --- a/java/ql/lib/ext/java.util.concurrent.atomic.model.yml +++ b/java/ql/lib/ext/java.util.concurrent.atomic.model.yml @@ -5,12 +5,23 @@ extensions: data: - ["java.util.concurrent.atomic", "AtomicReference", False, "AtomicReference", "(Object)", "", "Argument[0]", "Argument[this].SyntheticField[java.util.concurrent.atomic.AtomicReference.value]", "value", "manual"] - ["java.util.concurrent.atomic", "AtomicReference", False, "get", "()", "", "Argument[this].SyntheticField[java.util.concurrent.atomic.AtomicReference.value]", "ReturnValue", "value", "manual"] + - ["java.util.concurrent.atomic", "AtomicReference", False, "set", "(Object)", "", "Argument[0]", "Argument[this].SyntheticField[java.util.concurrent.atomic.AtomicReference.value]", "value", "manual"] - addsTo: pack: codeql/java-all extensible: neutralModel data: + - ["java.util.concurrent.atomic", "AtomicBoolean", "AtomicBoolean", "(boolean)", "manual"] + - ["java.util.concurrent.atomic", "AtomicBoolean", "compareAndSet", "(boolean,boolean)", "manual"] + - ["java.util.concurrent.atomic", "AtomicBoolean", "get", "()", "manual"] + - ["java.util.concurrent.atomic", "AtomicBoolean", "set", "(boolean)", "manual"] + # The below APIs have numeric flow and are currently being stored as neutral models. # These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future. - ["java.util.concurrent.atomic", "AtomicInteger", "AtomicInteger", "(int)", "manual"] # value-numeric - ["java.util.concurrent.atomic", "AtomicInteger", "get", "()", "manual"] # value-numeric + - ["java.util.concurrent.atomic", "AtomicInteger", "incrementAndGet", "()", "manual"] # taint-numeric + - ["java.util.concurrent.atomic", "AtomicLong", "AtomicLong", "(long)", "manual"] # value-numeric + - ["java.util.concurrent.atomic", "AtomicLong", "addAndGet", "(long)", "manual"] # taint-numeric + - ["java.util.concurrent.atomic", "AtomicLong", "get", "()", "manual"] # value-numeric + - ["java.util.concurrent.atomic", "AtomicLong", "incrementAndGet", "()", "manual"] # taint-numeric diff --git a/java/ql/lib/ext/java.util.concurrent.locks.model.yml b/java/ql/lib/ext/java.util.concurrent.locks.model.yml new file mode 100644 index 00000000000..54a86493fc1 --- /dev/null +++ b/java/ql/lib/ext/java.util.concurrent.locks.model.yml @@ -0,0 +1,7 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: neutralModel + data: + - ["java.util.concurrent.locks", "Lock", "lock", "()", "manual"] + - ["java.util.concurrent.locks", "Lock", "unlock", "()", "manual"] diff --git a/java/ql/lib/ext/java.util.concurrent.model.yml b/java/ql/lib/ext/java.util.concurrent.model.yml index dd0c6b75754..723035f408e 100644 --- a/java/ql/lib/ext/java.util.concurrent.model.yml +++ b/java/ql/lib/ext/java.util.concurrent.model.yml @@ -17,7 +17,13 @@ extensions: - ["java.util.concurrent", "BlockingQueue", True, "poll", "(long,TimeUnit)", "", "Argument[this].Element", "ReturnValue", "value", "manual"] - ["java.util.concurrent", "BlockingQueue", True, "put", "(Object)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] - ["java.util.concurrent", "BlockingQueue", True, "take", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"] + - ["java.util.concurrent", "CompletableFuture", False, "complete", "(Object)", "", "Argument[0]", "Argument[this].SyntheticField[java.util.concurrent.Future.value]", "value", "manual"] + - ["java.util.concurrent", "CompletableFuture", False, "completedFuture", "(Object)", "", "Argument[0]", "ReturnValue.SyntheticField[java.util.concurrent.Future.value]", "value", "manual"] + - ["java.util.concurrent", "CompletableFuture", False, "join", "()", "", "Argument[this].SyntheticField[java.util.concurrent.Future.value]", "ReturnValue", "value", "manual"] + - ["java.util.concurrent", "CompletionStage", False, "toCompletableFuture", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["java.util.concurrent", "ConcurrentHashMap", True, "elements", "()", "", "Argument[this].MapValue", "ReturnValue.Element", "value", "manual"] + - ["java.util.concurrent", "ExecutorService", True, "submit", "(Runnable)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["java.util.concurrent", "Future", True, "get", "()", "", "Argument[this].SyntheticField[java.util.concurrent.Future.value]", "ReturnValue", "value", "manual"] - ["java.util.concurrent", "TransferQueue", True, "transfer", "(Object)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] - ["java.util.concurrent", "TransferQueue", True, "tryTransfer", "(Object)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] - ["java.util.concurrent", "TransferQueue", True, "tryTransfer", "(Object,long,TimeUnit)", "", "Argument[0]", "Argument[this].Element", "value", "manual"] @@ -26,9 +32,15 @@ extensions: pack: codeql/java-all extensible: neutralModel data: + - ["java.util.concurrent", "CompletableFuture", "completeExceptionally", "(Throwable)", "manual"] + - ["java.util.concurrent", "CompletableFuture", "isDone", "()", "manual"] + - ["java.util.concurrent", "CountDownLatch", "await", "", "manual"] - ["java.util.concurrent", "CountDownLatch", "countDown", "()", "manual"] + - ["java.util.concurrent", "Executor", "execute", "(Runnable)", "manual"] + - ["java.util.concurrent", "ExecutorService", "shutdown", "()", "manual"] # The below APIs have numeric flow and are currently being stored as neutral models. # These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future. - ["java.util.concurrent", "CountDownLatch", "CountDownLatch", "(int)", "manual"] # value-numeric - ["java.util.concurrent", "CountDownLatch", "getCount", "()", "manual"] # value-numeric + - ["java.util.concurrent", "TimeUnit", "toMillis", "(long)", "manual"] # taint-numeric diff --git a/java/ql/lib/ext/java.util.function.model.yml b/java/ql/lib/ext/java.util.function.model.yml index 90ed9c1b9ab..8cdab4149cd 100644 --- a/java/ql/lib/ext/java.util.function.model.yml +++ b/java/ql/lib/ext/java.util.function.model.yml @@ -4,3 +4,9 @@ extensions: extensible: sinkModel data: - ["java.util.function", "Predicate", False, "test", "(Object)", "", "Argument[this]", "regex-use[0]", "manual"] + + - addsTo: + pack: codeql/java-all + extensible: neutralModel + data: + - ["java.util.function", "Function", "identity", "()", "manual"] diff --git a/java/ql/lib/ext/java.util.logging.model.yml b/java/ql/lib/ext/java.util.logging.model.yml index 41a59ceee3a..b3f4188ed97 100644 --- a/java/ql/lib/ext/java.util.logging.model.yml +++ b/java/ql/lib/ext/java.util.logging.model.yml @@ -41,4 +41,12 @@ extensions: pack: codeql/java-all extensible: summaryModel data: + - ["java.util.logging", "Logger", False, "getLogger", "(String)", "", "Argument[0]", "ReturnValue.SyntheticField[java.util.logging.Logger.name]", "value", "manual"] + - ["java.util.logging", "Logger", False, "getName", "()", "", "Argument[this].SyntheticField[java.util.logging.Logger.name]", "ReturnValue", "value", "manual"] - ["java.util.logging", "LogRecord", False, "LogRecord", "", "", "Argument[1]", "Argument[this]", "taint", "manual"] + + - addsTo: + pack: codeql/java-all + extensible: neutralModel + data: + - ["java.util.logging", "Logger", "isLoggable", "(Level)", "manual"] diff --git a/java/ql/lib/ext/java.util.model.yml b/java/ql/lib/ext/java.util.model.yml index 5f3dad67c37..5df5b1bf4bc 100644 --- a/java/ql/lib/ext/java.util.model.yml +++ b/java/ql/lib/ext/java.util.model.yml @@ -124,6 +124,8 @@ extensions: - ["java.util", "EnumMap", False, "EnumMap", "(Map)", "", "Argument[0].MapValue", "Argument[this].MapValue", "value", "manual"] - ["java.util", "Enumeration", True, "asIterator", "", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"] - ["java.util", "Enumeration", True, "nextElement", "", "", "Argument[this].Element", "ReturnValue", "value", "manual"] + - ["java.util", "EventObject", False, "EventObject", "(Object)", "", "Argument[0]", "Argument[this].Field[java.util.EventObject.source]", "value", "manual"] + - ["java.util", "EventObject", True, "getSource", "()", "", "Argument[this].Field[java.util.EventObject.source]", "ReturnValue", "value", "manual"] - ["java.util", "HashMap", False, "HashMap", "(Map)", "", "Argument[0].MapKey", "Argument[this].MapKey", "value", "manual"] - ["java.util", "HashMap", False, "HashMap", "(Map)", "", "Argument[0].MapValue", "Argument[this].MapValue", "value", "manual"] - ["java.util", "HashSet", False, "HashSet", "(Collection)", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"] @@ -290,6 +292,7 @@ extensions: - ["java.util", "Queue", True, "peek", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"] - ["java.util", "Queue", True, "poll", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"] - ["java.util", "Queue", True, "remove", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"] + - ["java.util", "ResourceBundle", True, "getString", "(String)", "", "Argument[this].MapValue", "ReturnValue", "value", "manual"] - ["java.util", "Scanner", True, "Scanner", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["java.util", "Scanner", True, "findInLine", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["java.util", "Scanner", True, "findWithinHorizon", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] @@ -363,36 +366,74 @@ extensions: extensible: neutralModel data: - ["java.util", "ArrayList", "ArrayList", "(int)", "manual"] + - ["java.util", "ArrayList", "isEmpty", "()", "manual"] - ["java.util", "ArrayList", "size", "()", "manual"] + - ["java.util", "Arrays", "toString", "(Object[])", "manual"] + - ["java.util", "Calendar", "getInstance", "()", "manual"] + - ["java.util", "Collection", "contains", "(Object)", "manual"] - ["java.util", "Collection", "isEmpty", "()", "manual"] - ["java.util", "Collection", "size", "()", "manual"] - ["java.util", "Collections", "emptyList", "()", "manual"] - ["java.util", "Collections", "emptyMap", "()", "manual"] - ["java.util", "Collections", "emptySet", "()", "manual"] + - ["java.util", "Collections", "sort", "", "manual"] + - ["java.util", "Enumeration", "hasMoreElements", "()", "manual"] + - ["java.util", "HashMap", "containsKey", "(Object)", "manual"] + - ["java.util", "HashMap", "HashMap", "(int)", "manual"] + - ["java.util", "HashMap", "size", "()", "manual"] + - ["java.util", "HashSet", "HashSet", "(int)", "manual"] - ["java.util", "Iterator", "hasNext", "()", "manual"] - ["java.util", "List", "contains", "(Object)", "manual"] + - ["java.util", "List", "equals", "(Object)", "manual"] + - ["java.util", "List", "hashCode", "()", "manual"] + - ["java.util", "List", "indexOf", "(Object)", "manual"] - ["java.util", "List", "isEmpty", "()", "manual"] + - ["java.util", "List", "of", "()", "manual"] + - ["java.util", "List", "sort", "(Comparator)", "manual"] - ["java.util", "List", "size", "()", "manual"] + - ["java.util", "Locale", "forLanguageTag", "(String)", "manual"] - ["java.util", "Map", "containsKey", "(Object)", "manual"] - ["java.util", "Map", "isEmpty", "()", "manual"] - ["java.util", "Map", "size", "()", "manual"] - ["java.util", "Objects", "equals", "(Object,Object)", "manual"] - ["java.util", "Objects", "hash", "(Object[])", "manual"] + - ["java.util", "Objects", "hashCode", "(Object)", "manual"] + - ["java.util", "Objects", "isNull", "(Object)", "manual"] - ["java.util", "Objects", "nonNull", "(Object)", "manual"] - ["java.util", "Optional", "empty", "()", "manual"] + - ["java.util", "Optional", "isEmpty", "()", "manual"] - ["java.util", "Optional", "isPresent", "()", "manual"] + - ["java.util", "Random", "nextInt", "(int)", "manual"] - ["java.util", "Set", "contains", "(Object)", "manual"] - ["java.util", "Set", "isEmpty", "()", "manual"] - ["java.util", "Set", "size", "()", "manual"] + - ["java.util", "UUID", "equals", "(Object)", "manual"] + - ["java.util", "UUID", "fromString", "(String)", "manual"] - ["java.util", "UUID", "randomUUID", "()", "manual"] - ["java.util", "UUID", "toString", "()", "manual"] + - ["java.util", "TimeZone", "getTimeZone", "(String)", "manual"] + - ["java.util", "Vector", "size", "()", "manual"] # The below APIs are currently being stored as neutral models since `WithoutElement` has not yet been implemented for Java. # When `WithoutElement` is implemented, these should be changed to summary models of the form `Argument[this].WithoutElement -> Argument[this]`. + - ["java.util", "Collection", "removeIf", "(Predicate)", "manual"] + - ["java.util", "Iterator", "remove", "()", "manual"] - ["java.util", "List", "clear", "()", "manual"] + - ["java.util", "List", "remove", "(Object)", "manual"] - ["java.util", "Map", "clear", "()", "manual"] + - ["java.util", "Set", "clear", "()", "manual"] + - ["java.util", "Set", "remove", "(Object)", "manual"] + - ["java.util", "Set", "removeAll", "(Collection)", "manual"] # The below APIs have numeric flow and are currently being stored as neutral models. # These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future. - - ["java.util", "Date", "Date", "(long)", "manual"] # taint-numeric - - ["java.util", "Date", "getTime", "()", "manual"] # taint-numeric + - ["java.util", "Calendar", "add", "(int,int)", "manual"] # taint-numeric + - ["java.util", "Calendar", "get", "(int)", "manual"] # value-numeric + - ["java.util", "Calendar", "getTime", "()", "manual"] # taint-numeric + - ["java.util", "Calendar", "getTimeInMillis", "()", "manual"] # taint-numeric + - ["java.util", "Calendar", "set", "(int,int)", "manual"] # value-numeric + - ["java.util", "Calendar", "setTime", "(Date)", "manual"] # taint-numeric + - ["java.util", "Date", "Date", "(long)", "manual"] # taint-numeric + - ["java.util", "Date", "getTime", "()", "manual"] # taint-numeric + - ["java.util", "Date", "from", "(Instant)", "manual"] # taint-numeric + - ["java.util", "Date", "toInstant", "()", "manual"] # taint-numeric diff --git a/java/ql/lib/ext/java.util.regex.model.yml b/java/ql/lib/ext/java.util.regex.model.yml index d002fd93419..8be0c3105ae 100644 --- a/java/ql/lib/ext/java.util.regex.model.yml +++ b/java/ql/lib/ext/java.util.regex.model.yml @@ -21,6 +21,13 @@ extensions: - ["java.util.regex", "Matcher", False, "replaceAll", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["java.util.regex", "Matcher", False, "replaceFirst", "", "", "Argument[this]", "ReturnValue", "taint", "manual"] - ["java.util.regex", "Matcher", False, "replaceFirst", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["java.util.regex", "Pattern", False, "compile", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["java.util.regex", "Pattern", False, "matcher", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["java.util.regex", "Pattern", False, "quote", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["java.util.regex", "Pattern", False, "split", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + + - addsTo: + pack: codeql/java-all + extensible: neutralModel + data: + - ["java.util.regex", "Matcher", "find", "()", "manual"] diff --git a/java/ql/lib/ext/java.util.stream.model.yml b/java/ql/lib/ext/java.util.stream.model.yml index 1fafd506185..7ef65fd8a83 100644 --- a/java/ql/lib/ext/java.util.stream.model.yml +++ b/java/ql/lib/ext/java.util.stream.model.yml @@ -94,3 +94,9 @@ extensions: data: - ["java.util.stream", "Collectors", "toList", "()", "manual"] - ["java.util.stream", "Collectors", "toSet", "()", "manual"] + - ["java.util.stream", "Stream", "count", "()", "manual"] + + # The below APIs have numeric flow and are currently being stored as neutral models. + # These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future. + - ["java.util.stream", "IntStream", "mapToObj", "(IntFunction)", "manual"] # taint-numeric + - ["java.util.stream", "IntStream", "range", "(int,int)", "manual"] # taint-numeric diff --git a/java/ql/lib/semmle/code/Unit.qll b/java/ql/lib/semmle/code/Unit.qll index e9611ed3df4..83a4a03321d 100644 --- a/java/ql/lib/semmle/code/Unit.qll +++ b/java/ql/lib/semmle/code/Unit.qll @@ -1,10 +1,3 @@ /** Provides the `Unit` class. */ -/** The unit type. */ -private newtype TUnit = TMkUnit() - -/** The trivial type with a single element. */ -class Unit extends TUnit { - /** Gets a textual representation of this element. */ - string toString() { result = "unit" } -} +import codeql.util.Unit diff --git a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll index 94464bd263f..f94658e1372 100644 --- a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll +++ b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll @@ -365,6 +365,7 @@ private module ControlFlowGraphImpl { /** * Gets a non-overridable method that always throws an exception or calls `exit`. */ + pragma[assume_small_delta] private Method nonReturningMethod() { result instanceof MethodExit or @@ -381,6 +382,7 @@ private module ControlFlowGraphImpl { /** * Gets a virtual method that always throws an exception or calls `exit`. */ + pragma[assume_small_delta] private EffectivelyNonVirtualMethod likelyNonReturningMethod() { result.getReturnType() instanceof VoidType and not exists(ReturnStmt ret | ret.getEnclosingCallable() = result) and diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index a736928361c..39d5bd27311 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -220,7 +220,7 @@ predicate modelCoverage(string package, int pkgs, string kind, string part, int /** Provides a query predicate to check the MaD models for validation errors. */ module ModelValidation { private string getInvalidModelInput() { - exists(string pred, string input, string part | + exists(string pred, AccessPath input, AccessPathToken part | sinkModel(_, _, _, _, _, _, input, _, _) and pred = "sink" or summaryModel(_, _, _, _, _, _, input, _, _, _) and pred = "summary" @@ -229,9 +229,10 @@ module ModelValidation { invalidSpecComponent(input, part) and not part = "" and not (part = "Argument" and pred = "sink") and - not parseArg(part, _) + not parseArg(part, _) and + not part.getName() = "Field" or - part = input.(AccessPath).getToken(0) and + part = input.getToken(0) and parseParam(part, _) or invalidIndexComponent(input, part) @@ -241,7 +242,7 @@ module ModelValidation { } private string getInvalidModelOutput() { - exists(string pred, string output, string part | + exists(string pred, AccessPath output, AccessPathToken part | sourceModel(_, _, _, _, _, _, output, _, _) and pred = "source" or summaryModel(_, _, _, _, _, _, _, output, _, _) and pred = "summary" @@ -249,7 +250,8 @@ module ModelValidation { ( invalidSpecComponent(output, part) and not part = "" and - not (part = ["Argument", "Parameter"] and pred = "source") + not (part = ["Argument", "Parameter"] and pred = "source") and + not part.getName() = "Field" or invalidIndexComponent(output, part) ) and diff --git a/java/ql/lib/semmle/code/java/dataflow/RangeAnalysis.qll b/java/ql/lib/semmle/code/java/dataflow/RangeAnalysis.qll index aeb79ee99e1..95153b58043 100644 --- a/java/ql/lib/semmle/code/java/dataflow/RangeAnalysis.qll +++ b/java/ql/lib/semmle/code/java/dataflow/RangeAnalysis.qll @@ -421,32 +421,6 @@ private predicate boundFlowStep(Expr e2, Expr e1, int delta, boolean upper) { delta = 0 and (upper = true or upper = false) or - exists(Expr x | - e2.(AddExpr).hasOperands(e1, x) - or - exists(AssignAddExpr add | add = e2 | - add.getDest() = e1 and add.getRhs() = x - or - add.getDest() = x and add.getRhs() = e1 - ) - | - // `x instanceof ConstantIntegerExpr` is covered by valueFlowStep - not x instanceof ConstantIntegerExpr and - not e1 instanceof ConstantIntegerExpr and - if strictlyPositiveIntegralExpr(x) - then upper = false and delta = 1 - else - if positive(x) - then upper = false and delta = 0 - else - if strictlyNegativeIntegralExpr(x) - then upper = true and delta = -1 - else - if negative(x) - then upper = true and delta = 0 - else none() - ) - or exists(Expr x | exists(SubExpr sub | e2 = sub and @@ -896,6 +870,20 @@ private predicate bounded( or upper = false and delta = d1.minimum(d2) ) + or + exists( + Bound b1, Bound b2, int d1, int d2, boolean fbe1, boolean fbe2, int od1, int od2, Reason r1, + Reason r2 + | + boundedAddition(e, upper, b1, true, d1, fbe1, od1, r1) and + boundedAddition(e, upper, b2, false, d2, fbe2, od2, r2) and + delta = d1 + d2 and + fromBackEdge = fbe1.booleanOr(fbe2) + | + b = b1 and origdelta = od1 and reason = r1 and b2 instanceof ZeroBound + or + b = b2 and origdelta = od2 and reason = r2 and b1 instanceof ZeroBound + ) } private predicate boundedConditionalExpr( @@ -904,3 +892,37 @@ private predicate boundedConditionalExpr( ) { bounded(cond.getBranchExpr(branch), b, delta, upper, fromBackEdge, origdelta, reason) } + +private predicate nonConstAdd(Expr add, Expr operand, boolean isLeft) { + exists(Expr other | + add.(AddExpr).getLeftOperand() = operand and + add.(AddExpr).getRightOperand() = other and + isLeft = true + or + add.(AddExpr).getLeftOperand() = other and + add.(AddExpr).getRightOperand() = operand and + isLeft = false + or + add.(AssignAddExpr).getDest() = operand and + add.(AssignAddExpr).getRhs() = other and + isLeft = true + or + add.(AssignAddExpr).getDest() = other and + add.(AssignAddExpr).getRhs() = operand and + isLeft = false + | + // `ConstantIntegerExpr` is covered by valueFlowStep + not other instanceof ConstantIntegerExpr and + not operand instanceof ConstantIntegerExpr + ) +} + +private predicate boundedAddition( + Expr add, boolean upper, Bound b, boolean isLeft, int delta, boolean fromBackEdge, int origdelta, + Reason reason +) { + exists(Expr op | + nonConstAdd(add, op, isLeft) and + bounded(op, b, delta, upper, fromBackEdge, origdelta, reason) + ) +} diff --git a/java/ql/lib/semmle/code/java/dataflow/SSA.qll b/java/ql/lib/semmle/code/java/dataflow/SSA.qll index 000d0275819..d4ff7ed0ac7 100644 --- a/java/ql/lib/semmle/code/java/dataflow/SSA.qll +++ b/java/ql/lib/semmle/code/java/dataflow/SSA.qll @@ -451,6 +451,7 @@ private module SsaImpl { * Holds if `f` is live in `b` at index `i`. The rank of `i` is `rankix` as * defined by `callDefUseRank`. */ + pragma[assume_small_delta] private predicate liveAtRank(TrackedField f, BasicBlock b, int rankix, int i) { callDefUseRank(f, b, rankix, i) and ( @@ -564,6 +565,7 @@ private module SsaImpl { } /** Holds if a phi node for `v` is needed at the beginning of basic block `b`. */ + pragma[assume_small_delta] cached predicate phiNode(TrackedVar v, BasicBlock b) { liveAtEntry(v, b) and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll b/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll index f44ed438596..6f53dbd02c1 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll @@ -151,6 +151,7 @@ private module SsaImpl { } /** Holds if a phi node for `v` is needed at the beginning of basic block `b`. */ + pragma[assume_small_delta] cached predicate phiNode(BaseSsaSourceVariable v, BasicBlock b) { liveAtEntry(v, b) and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlow.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlow.qll index 617362ab4f0..865d7b4d6ce 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlow.qll @@ -2,7 +2,7 @@ * Provides an implementation of global (interprocedural) data flow. This file * re-exports the local (intraprocedural) data flow analysis from * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Make` and `MakeWithState` modules. + * through the `Global` and `GlobalWithState` modules. */ private import DataFlowImplCommon @@ -73,10 +73,10 @@ signature module ConfigSig { */ default FlowFeature getAFeature() { none() } - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ default predicate sourceGrouping(Node source, string sourceGroup) { none() } - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ default predicate sinkGrouping(Node sink, string sinkGroup) { none() } /** @@ -166,10 +166,10 @@ signature module StateConfigSig { */ default FlowFeature getAFeature() { none() } - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ default predicate sourceGrouping(Node source, string sourceGroup) { none() } - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ default predicate sinkGrouping(Node sink, string sinkGroup) { none() } /** @@ -182,15 +182,15 @@ signature module StateConfigSig { } /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * Gets the exploration limit for `partialFlow` and `partialFlowRev` * measured in approximate number of interprocedural steps. */ signature int explorationLimitSig(); /** - * The output of a data flow computation. + * The output of a global data flow computation. */ -signature module DataFlowSig { +signature module GlobalFlowSig { /** * A `Node` augmented with a call context (except for sinks) and an access path. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. @@ -203,28 +203,28 @@ signature module DataFlowSig { * The corresponding paths are generated from the end-points and the graph * included in the module `PathGraph`. */ - predicate hasFlowPath(PathNode source, PathNode sink); + predicate flowPath(PathNode source, PathNode sink); /** * Holds if data can flow from `source` to `sink`. */ - predicate hasFlow(Node source, Node sink); + predicate flow(Node source, Node sink); /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowTo(Node sink); + predicate flowTo(Node sink); /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowToExpr(DataFlowExpr sink); + predicate flowToExpr(DataFlowExpr sink); } /** - * Constructs a standard data flow computation. + * Constructs a global data flow computation. */ -module Make implements DataFlowSig { +module Global implements GlobalFlowSig { private module C implements FullStateConfigSig { import DefaultState import Config @@ -233,10 +233,15 @@ module Make implements DataFlowSig { import Impl } +/** DEPRECATED: Use `Global` instead. */ +deprecated module Make implements GlobalFlowSig { + import Global +} + /** - * Constructs a data flow computation using flow state. + * Constructs a global data flow computation using flow state. */ -module MakeWithState implements DataFlowSig { +module GlobalWithState implements GlobalFlowSig { private module C implements FullStateConfigSig { import Config } @@ -244,6 +249,11 @@ module MakeWithState implements DataFlowSig { import Impl } +/** DEPRECATED: Use `GlobalWithState` instead. */ +deprecated module MakeWithState implements GlobalFlowSig { + import GlobalWithState +} + signature class PathNodeSig { /** Gets a textual representation of this element. */ string toString(); diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index c47b0308855..6ea97954bdf 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -8,6 +8,7 @@ private import DataFlowImplCommon private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommonPublic +private import codeql.util.Unit import DataFlow /** @@ -91,10 +92,10 @@ signature module FullStateConfigSig { */ FlowFeature getAFeature(); - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ predicate sourceGrouping(Node source, string sourceGroup); - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ predicate sinkGrouping(Node sink, string sinkGroup); /** @@ -445,11 +446,7 @@ module Impl { } private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } + class Ap = Unit; private class Cc = boolean; @@ -3633,7 +3630,7 @@ module Impl { * The corresponding paths are generated from the end-points and the graph * included in the module `PathGraph`. */ - predicate hasFlowPath(PathNode source, PathNode sink) { + predicate flowPath(PathNode source, PathNode sink) { exists(PathNodeImpl flowsource, PathNodeImpl flowsink | source = flowsource and sink = flowsink | @@ -3643,6 +3640,9 @@ module Impl { ) } + /** DEPRECATED: Use `flowPath` instead. */ + deprecated predicate hasFlowPath = flowPath/2; + private predicate flowsTo(PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink) { flowsource.isSource() and flowsource.getNodeEx().asNode() = source and @@ -3653,17 +3653,26 @@ module Impl { /** * Holds if data can flow from `source` to `sink`. */ - predicate hasFlow(Node source, Node sink) { flowsTo(_, _, source, sink) } + predicate flow(Node source, Node sink) { flowsTo(_, _, source, sink) } + + /** DEPRECATED: Use `flow` instead. */ + deprecated predicate hasFlow = flow/2; /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + predicate flowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + + /** DEPRECATED: Use `flowTo` instead. */ + deprecated predicate hasFlowTo = flowTo/1; /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate flowToExpr(DataFlowExpr sink) { flowTo(exprNode(sink)) } + + /** DEPRECATED: Use `flowToExpr` instead. */ + deprecated predicate hasFlowToExpr = flowToExpr/1; private predicate finalStats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples @@ -4574,7 +4583,7 @@ module Impl { * * To use this in a `path-problem` query, import the module `PartialPathGraph`. */ - predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { + predicate partialFlow(PartialPathNode source, PartialPathNode node, int dist) { partialFlow(source, node) and dist = node.getSourceDistance() } @@ -4594,7 +4603,7 @@ module Impl { * Note that reverse flow has slightly lower precision than the corresponding * forward flow, as reverse flow disregards type pruning among other features. */ - predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { + predicate partialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { revPartialFlow(node, sink) and dist = node.getSinkDistance() } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll index e6bdc74cceb..be70086a93a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index e6bdc74cceb..be70086a93a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index e6bdc74cceb..be70086a93a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index e6bdc74cceb..be70086a93a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index e6bdc74cceb..be70086a93a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll index e6bdc74cceb..be70086a93a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index d09fdcfca3e..e6fce328326 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -140,10 +140,8 @@ private module LambdaFlow { } pragma[nomagic] - private TReturnPositionSimple viableReturnPosLambda( - DataFlowCall call, DataFlowCallOption lastCall, ReturnKind kind - ) { - result = TReturnPositionSimple0(viableCallableLambda(call, lastCall), kind) + private TReturnPositionSimple viableReturnPosLambda(DataFlowCall call, ReturnKind kind) { + result = TReturnPositionSimple0(viableCallableLambda(call, _), kind) } private predicate viableReturnPosOutNonLambda( @@ -155,11 +153,12 @@ private module LambdaFlow { ) } + pragma[nomagic] private predicate viableReturnPosOutLambda( - DataFlowCall call, DataFlowCallOption lastCall, TReturnPositionSimple pos, OutNode out + DataFlowCall call, TReturnPositionSimple pos, OutNode out ) { exists(ReturnKind kind | - pos = viableReturnPosLambda(call, lastCall, kind) and + pos = viableReturnPosLambda(call, kind) and out = getAnOutNode(call, kind) ) } @@ -188,6 +187,7 @@ private module LambdaFlow { else any() } + pragma[assume_small_delta] pragma[nomagic] predicate revLambdaFlow0( DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn, @@ -274,6 +274,7 @@ private module LambdaFlow { ) } + pragma[assume_small_delta] pragma[nomagic] predicate revLambdaFlowOut( DataFlowCall lambdaCall, LambdaCallKind kind, TReturnPositionSimple pos, DataFlowType t, @@ -285,7 +286,7 @@ private module LambdaFlow { or // non-linear recursion revLambdaFlowOutLambdaCall(lambdaCall, kind, out, t, toJump, call, lastCall) and - viableReturnPosOutLambda(call, _, pos, out) + viableReturnPosOutLambda(call, pos, out) ) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll index ba5a1cfacc7..ff064cc8405 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll @@ -14,7 +14,6 @@ private import FlowSummaryImpl as FlowSummaryImpl private import TaintTrackingUtil as TaintTrackingUtil private import DataFlowNodes import DataFlowNodes::Public -import semmle.code.Unit /** Holds if `n` is an access to an unqualified `this` at `cfgnode`. */ private predicate thisAccess(Node n, ControlFlowNode cfgnode) { diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll index 478328d90bf..6665e0e7480 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll @@ -10,6 +10,7 @@ private import FlowSummaryImplSpecific private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommon +private import codeql.util.Unit /** Provides classes and predicates for defining flow summaries. */ module Public { @@ -109,6 +110,7 @@ module Public { } /** Gets the stack obtained by dropping the first `i` elements, if any. */ + pragma[assume_small_delta] SummaryComponentStack drop(int i) { i = 0 and result = this or diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll b/java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll index e44cd40d872..6f0067517f9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SignAnalysisCommon.qll @@ -45,10 +45,6 @@ private Sign certainExprSign(Expr e) { private predicate unknownSign(Expr e) { not exists(certainExprSign(e)) and ( - exists(IntegerLiteral lit | lit = e and not exists(lit.getValue().toInt())) - or - exists(LongLiteral lit | lit = e and not exists(lit.getValue().toFloat())) - or exists(CastingExpr cast, Type fromtyp | cast = e and fromtyp = cast.getSourceType() and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTracking.qll b/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTracking.qll index 7f96fe5e6fb..872ac8d4cb8 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTracking.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTracking.qll @@ -33,9 +33,9 @@ private module AddTaintDefaults imp } /** - * Constructs a standard taint tracking computation. + * Constructs a global taint tracking computation. */ -module Make implements DataFlow::DataFlowSig { +module Global implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import DataFlowInternal::DefaultState import Config @@ -48,10 +48,15 @@ module Make implements DataFlow::DataFlowSig { import DataFlowInternal::Impl } +/** DEPRECATED: Use `Global` instead. */ +deprecated module Make implements DataFlow::GlobalFlowSig { + import Global +} + /** - * Constructs a taint tracking computation using flow state. + * Constructs a global taint tracking computation using flow state. */ -module MakeWithState implements DataFlow::DataFlowSig { +module GlobalWithState implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import Config } @@ -62,3 +67,8 @@ module MakeWithState implements DataFlow::DataF import DataFlowInternal::Impl } + +/** DEPRECATED: Use `GlobalWithState` instead. */ +deprecated module MakeWithState implements DataFlow::GlobalFlowSig { + import GlobalWithState +} diff --git a/java/ql/lib/semmle/code/java/frameworks/JaxWS.qll b/java/ql/lib/semmle/code/java/frameworks/JaxWS.qll index 54b41f28a08..5c20af2f457 100644 --- a/java/ql/lib/semmle/code/java/frameworks/JaxWS.qll +++ b/java/ql/lib/semmle/code/java/frameworks/JaxWS.qll @@ -53,6 +53,7 @@ private predicate hasPathAnnotation(Annotatable annotatable) { * A method which is annotated with one or more JaxRS resource type annotations e.g. `@GET`, `@POST` etc. */ class JaxRsResourceMethod extends Method { + pragma[assume_small_delta] JaxRsResourceMethod() { exists(AnnotationType a | a = this.getAnAnnotation().getType() and @@ -91,6 +92,7 @@ class JaxRsResourceMethod extends Method { * This class contains resource methods, which are executed in response to requests. */ class JaxRsResourceClass extends Class { + pragma[assume_small_delta] JaxRsResourceClass() { // A root resource class has a @Path annotation on the class. hasPathAnnotation(this) diff --git a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll index 8512308f241..c487c6cecc2 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll @@ -28,7 +28,7 @@ class OnActivityResultIncomingIntent extends DataFlow::Node { */ predicate isRemoteSource() { exists(RefType startingType, Expr startActivityForResultArg | - ImplicitStartActivityForResult::hasFlowToExpr(startActivityForResultArg) and + ImplicitStartActivityForResult::flowToExpr(startActivityForResultArg) and // startingType is the class enclosing the method that calls `startActivityForResult`. startingType = startActivityForResultArg.getEnclosingCallable().getDeclaringType() | @@ -104,7 +104,7 @@ private module ImplicitStartActivityForResultConfig implements DataFlow::ConfigS } private module ImplicitStartActivityForResult = - DataFlow::Make; + DataFlow::Global; /** An Android Activity or Fragment. */ private class ActivityOrFragment extends Class { diff --git a/java/ql/lib/semmle/code/java/frameworks/google/GoogleHttpClientApi.qll b/java/ql/lib/semmle/code/java/frameworks/google/GoogleHttpClientApi.qll index 72516e5427e..2793f1980c5 100644 --- a/java/ql/lib/semmle/code/java/frameworks/google/GoogleHttpClientApi.qll +++ b/java/ql/lib/semmle/code/java/frameworks/google/GoogleHttpClientApi.qll @@ -21,10 +21,10 @@ private module TypeLiteralToParseAsFlowConfig implements DataFlow::ConfigSig { } } -private module TypeLiteralToParseAsFlow = DataFlow::Make; +private module TypeLiteralToParseAsFlow = DataFlow::Global; private TypeLiteral getSourceWithFlowToParseAs() { - TypeLiteralToParseAsFlow::hasFlow(DataFlow::exprNode(result), _) + TypeLiteralToParseAsFlow::flow(DataFlow::exprNode(result), _) } /** A field that is deserialized by `HttpResponse.parseAs`. */ diff --git a/java/ql/lib/semmle/code/java/frameworks/jackson/JacksonSerializability.qll b/java/ql/lib/semmle/code/java/frameworks/jackson/JacksonSerializability.qll index e26d2312f1b..79fd19f4ef2 100644 --- a/java/ql/lib/semmle/code/java/frameworks/jackson/JacksonSerializability.qll +++ b/java/ql/lib/semmle/code/java/frameworks/jackson/JacksonSerializability.qll @@ -108,10 +108,10 @@ private module TypeLiteralToJacksonDatabindFlowConfig implements DataFlow::Confi } private module TypeLiteralToJacksonDatabindFlow = - DataFlow::Make; + DataFlow::Global; private TypeLiteral getSourceWithFlowToJacksonDatabind() { - TypeLiteralToJacksonDatabindFlow::hasFlow(DataFlow::exprNode(result), _) + TypeLiteralToJacksonDatabindFlow::flow(DataFlow::exprNode(result), _) } /** A type whose values are explicitly deserialized in a call to a Jackson method. */ diff --git a/java/ql/lib/semmle/code/java/security/AndroidCertificatePinningQuery.qll b/java/ql/lib/semmle/code/java/security/AndroidCertificatePinningQuery.qll index 70dc1a7a328..86779a4a911 100644 --- a/java/ql/lib/semmle/code/java/security/AndroidCertificatePinningQuery.qll +++ b/java/ql/lib/semmle/code/java/security/AndroidCertificatePinningQuery.qll @@ -106,10 +106,8 @@ private class MissingPinningSink extends DataFlow::Node { } /** Configuration for finding uses of non trusted URLs. */ -private class UntrustedUrlConfig extends TaintTracking::Configuration { - UntrustedUrlConfig() { this = "UntrustedUrlConfig" } - - override predicate isSource(DataFlow::Node node) { +private module UntrustedUrlConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { trustedDomain(_) and exists(string lit | lit = node.asExpr().(CompileTimeConstantExpr).getStringValue() | lit.matches("%://%") and // it's a URL @@ -117,9 +115,11 @@ private class UntrustedUrlConfig extends TaintTracking::Configuration { ) } - override predicate isSink(DataFlow::Node node) { node instanceof MissingPinningSink } + predicate isSink(DataFlow::Node node) { node instanceof MissingPinningSink } } +private module UntrustedUrlFlow = TaintTracking::Global; + /** Holds if `node` is a network communication call for which certificate pinning is not implemented. */ predicate missingPinning(DataFlow::Node node, string domain) { isAndroid() and @@ -127,8 +127,8 @@ predicate missingPinning(DataFlow::Node node, string domain) { ( not trustedDomain(_) and domain = "" or - exists(UntrustedUrlConfig conf, DataFlow::Node src | - conf.hasFlow(src, node) and + exists(DataFlow::Node src | + UntrustedUrlFlow::flow(src, node) and domain = getDomain(src.asExpr()) ) ) diff --git a/java/ql/lib/semmle/code/java/security/AndroidIntentRedirectionQuery.qll b/java/ql/lib/semmle/code/java/security/AndroidIntentRedirectionQuery.qll index 9d5a2cb4cf2..87fd5003afb 100644 --- a/java/ql/lib/semmle/code/java/security/AndroidIntentRedirectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/AndroidIntentRedirectionQuery.qll @@ -8,9 +8,11 @@ import semmle.code.java.dataflow.TaintTracking3 import semmle.code.java.security.AndroidIntentRedirection /** + * DEPRECATED: Use `IntentRedirectionFlow` instead. + * * A taint tracking configuration for tainted Intents being used to start Android components. */ -class IntentRedirectionConfiguration extends TaintTracking::Configuration { +deprecated class IntentRedirectionConfiguration extends TaintTracking::Configuration { IntentRedirectionConfiguration() { this = "IntentRedirectionConfiguration" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -26,31 +28,45 @@ class IntentRedirectionConfiguration extends TaintTracking::Configuration { } } +/** A taint tracking configuration for tainted Intents being used to start Android components. */ +module IntentRedirectionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof IntentRedirectionSink } + + predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof IntentRedirectionSanitizer } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(IntentRedirectionAdditionalTaintStep c).step(node1, node2) + } +} + +/** Tracks the flow of tainted Intents being used to start Android components. */ +module IntentRedirectionFlow = TaintTracking::Global; + /** * A sanitizer for sinks that receive the original incoming Intent, * since its component cannot be arbitrarily set. */ private class OriginalIntentSanitizer extends IntentRedirectionSanitizer { - OriginalIntentSanitizer() { any(SameIntentBeingRelaunchedConfiguration c).hasFlowTo(this) } + OriginalIntentSanitizer() { SameIntentBeingRelaunchedFlow::flowTo(this) } } /** * Data flow configuration used to discard incoming Intents * flowing directly to sinks that start Android components. */ -private class SameIntentBeingRelaunchedConfiguration extends DataFlow2::Configuration { - SameIntentBeingRelaunchedConfiguration() { this = "SameIntentBeingRelaunchedConfiguration" } +private module SameIntentBeingRelaunchedConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSink(DataFlow::Node sink) { sink instanceof IntentRedirectionSink } - override predicate isSink(DataFlow::Node sink) { sink instanceof IntentRedirectionSink } - - override predicate isBarrier(DataFlow::Node barrier) { + predicate isBarrier(DataFlow::Node barrier) { // Don't discard the Intent if its original component is tainted barrier instanceof IntentWithTaintedComponent } - override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { // Intents being built with the copy constructor from the original Intent are discarded too exists(ClassInstanceExpr cie | cie.getConstructedType() instanceof TypeIntent and @@ -61,12 +77,14 @@ private class SameIntentBeingRelaunchedConfiguration extends DataFlow2::Configur } } +private module SameIntentBeingRelaunchedFlow = DataFlow::Global; + /** An `Intent` with a tainted component. */ private class IntentWithTaintedComponent extends DataFlow::Node { IntentWithTaintedComponent() { - exists(IntentSetComponent setExpr, TaintedIntentComponentConf conf | + exists(IntentSetComponent setExpr | setExpr.getQualifier() = this.asExpr() and - conf.hasFlowTo(DataFlow::exprNode(setExpr.getSink())) + TaintedIntentComponentFlow::flowTo(DataFlow::exprNode(setExpr.getSink())) ) } } @@ -74,16 +92,16 @@ private class IntentWithTaintedComponent extends DataFlow::Node { /** * A taint tracking configuration for tainted data flowing to an `Intent`'s component. */ -private class TaintedIntentComponentConf extends TaintTracking3::Configuration { - TaintedIntentComponentConf() { this = "TaintedIntentComponentConf" } +private module TaintedIntentComponentConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { any(IntentSetComponent setComponent).getSink() = sink.asExpr() } } +private module TaintedIntentComponentFlow = TaintTracking::Global; + /** A call to a method that changes the component of an `Intent`. */ private class IntentSetComponent extends MethodAccess { int sinkArg; diff --git a/java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll b/java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll index 2855f5989cf..e0c9fbff800 100644 --- a/java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll @@ -173,4 +173,4 @@ private module SensitiveCommunicationConfig implements DataFlow::ConfigSig { /** * Tracks taint flow from variables containing sensitive information to broadcast Intents. */ -module SensitiveCommunicationFlow = TaintTracking::Make; +module SensitiveCommunicationFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/ArbitraryApkInstallationQuery.qll b/java/ql/lib/semmle/code/java/security/ArbitraryApkInstallationQuery.qll index 68b16f7f902..d066f4974a1 100644 --- a/java/ql/lib/semmle/code/java/security/ArbitraryApkInstallationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ArbitraryApkInstallationQuery.qll @@ -17,15 +17,15 @@ private module ApkInstallationConfig implements DataFlow::ConfigSig { ma.getMethod() instanceof SetDataMethod and ma.getArgument(0) = node.asExpr() and ( - PackageArchiveMimeTypeFlow::hasFlowToExpr(ma.getQualifier()) + PackageArchiveMimeTypeFlow::flowToExpr(ma.getQualifier()) or - InstallPackageActionFlow::hasFlowToExpr(ma.getQualifier()) + InstallPackageActionFlow::flowToExpr(ma.getQualifier()) ) ) } } -module ApkInstallationFlow = DataFlow::Make; +module ApkInstallationFlow = DataFlow::Global; private newtype ActionState = ActionUnset() or @@ -72,7 +72,8 @@ private module InstallPackageActionConfig implements DataFlow::StateConfigSig { predicate isBarrier(DataFlow::Node node, FlowState state) { none() } } -private module InstallPackageActionFlow = TaintTracking::MakeWithState; +private module InstallPackageActionFlow = + TaintTracking::GlobalWithState; private newtype MimeTypeState = MimeTypeUnset() or @@ -117,4 +118,4 @@ private module PackageArchiveMimeTypeConfig implements DataFlow::StateConfigSig } private module PackageArchiveMimeTypeFlow = - TaintTracking::MakeWithState; + TaintTracking::GlobalWithState; diff --git a/java/ql/lib/semmle/code/java/security/CommandLineQuery.qll b/java/ql/lib/semmle/code/java/security/CommandLineQuery.qll index 42768d024e8..1f2d9c12b98 100644 --- a/java/ql/lib/semmle/code/java/security/CommandLineQuery.qll +++ b/java/ql/lib/semmle/code/java/security/CommandLineQuery.qll @@ -12,9 +12,11 @@ import semmle.code.java.security.ExternalProcess import semmle.code.java.security.CommandArguments /** + * DEPRECATED: Use `RemoteUserInputToArgumentToExecFlow` instead. + * * A taint-tracking configuration for unvalidated user input that is used to run an external process. */ -class RemoteUserInputToArgumentToExecFlowConfig extends TaintTracking::Configuration { +deprecated class RemoteUserInputToArgumentToExecFlowConfig extends TaintTracking::Configuration { RemoteUserInputToArgumentToExecFlowConfig() { this = "ExecCommon::RemoteUserInputToArgumentToExecFlowConfig" } @@ -33,12 +35,52 @@ class RemoteUserInputToArgumentToExecFlowConfig extends TaintTracking::Configura } /** + * A taint-tracking configuration for unvalidated user input that is used to run an external process. + */ +module RemoteUserInputToArgumentToExecFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof ArgumentToExec } + + predicate isBarrier(DataFlow::Node node) { + node.getType() instanceof PrimitiveType + or + node.getType() instanceof BoxedType + or + isSafeCommandArgument(node.asExpr()) + } +} + +/** + * Taint-tracking flow for unvalidated user input that is used to run an external process. + */ +module RemoteUserInputToArgumentToExecFlow = + TaintTracking::Global; + +/** + * DEPRECATED: Use `execIsTainted` instead. + * * Implementation of `ExecTainted.ql`. It is extracted to a QLL * so that it can be excluded from `ExecUnescaped.ql` to avoid * reporting overlapping results. */ -predicate execTainted(DataFlow::PathNode source, DataFlow::PathNode sink, ArgumentToExec execArg) { +deprecated predicate execTainted( + DataFlow::PathNode source, DataFlow::PathNode sink, ArgumentToExec execArg +) { exists(RemoteUserInputToArgumentToExecFlowConfig conf | conf.hasFlowPath(source, sink) and sink.getNode() = DataFlow::exprNode(execArg) ) } + +/** + * Implementation of `ExecTainted.ql`. It is extracted to a QLL + * so that it can be excluded from `ExecUnescaped.ql` to avoid + * reporting overlapping results. + */ +predicate execIsTainted( + RemoteUserInputToArgumentToExecFlow::PathNode source, + RemoteUserInputToArgumentToExecFlow::PathNode sink, ArgumentToExec execArg +) { + RemoteUserInputToArgumentToExecFlow::flowPath(source, sink) and + sink.getNode() = DataFlow::exprNode(execArg) +} diff --git a/java/ql/lib/semmle/code/java/security/FragmentInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/FragmentInjectionQuery.qll index 7564993c1ed..94b1877a4a3 100644 --- a/java/ql/lib/semmle/code/java/security/FragmentInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/FragmentInjectionQuery.qll @@ -37,4 +37,4 @@ private module FragmentInjectionTaintConfig implements DataFlow::ConfigSig { * Taint-tracking flow for unsafe user input * that is used to create Android fragments dynamically. */ -module FragmentInjectionTaintFlow = TaintTracking::Make; +module FragmentInjectionTaintFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/GroovyInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/GroovyInjectionQuery.qll index d364b8bd834..1d3c55398a5 100644 --- a/java/ql/lib/semmle/code/java/security/GroovyInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/GroovyInjectionQuery.qll @@ -6,10 +6,12 @@ import semmle.code.java.dataflow.TaintTracking import semmle.code.java.security.GroovyInjection /** + * DEPRECATED: Use `GroovyInjectionFlow` instead. + * * A taint-tracking configuration for unsafe user input * that is used to evaluate a Groovy expression. */ -class GroovyInjectionConfig extends TaintTracking::Configuration { +deprecated class GroovyInjectionConfig extends TaintTracking::Configuration { GroovyInjectionConfig() { this = "GroovyInjectionConfig" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -20,3 +22,23 @@ class GroovyInjectionConfig extends TaintTracking::Configuration { any(GroovyInjectionAdditionalTaintStep c).step(fromNode, toNode) } } + +/** + * A taint-tracking configuration for unsafe user input + * that is used to evaluate a Groovy expression. + */ +module GroovyInjectionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof GroovyInjectionSink } + + predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) { + any(GroovyInjectionAdditionalTaintStep c).step(fromNode, toNode) + } +} + +/** + * Detect taint flow of unsafe user input + * that is used to evaluate a Groovy expression. + */ +module GroovyInjectionFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/ImproperIntentVerificationQuery.qll b/java/ql/lib/semmle/code/java/security/ImproperIntentVerificationQuery.qll index 00a6dae69e9..db59c5c5291 100644 --- a/java/ql/lib/semmle/code/java/security/ImproperIntentVerificationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ImproperIntentVerificationQuery.qll @@ -14,14 +14,12 @@ private class OnReceiveMethod extends Method { } /** A configuration to detect whether the `action` of an `Intent` is checked. */ -private class VerifiedIntentConfig extends DataFlow::Configuration { - VerifiedIntentConfig() { this = "VerifiedIntentConfig" } - - override predicate isSource(DataFlow::Node src) { +private module VerifiedIntentConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asParameter() = any(OnReceiveMethod orm).getIntentParameter() } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodAccess ma | ma.getMethod().hasQualifiedName("android.content", "Intent", "getAction") and sink.asExpr() = ma.getQualifier() @@ -29,10 +27,12 @@ private class VerifiedIntentConfig extends DataFlow::Configuration { } } +private module VerifiedIntentFlow = DataFlow::Global; + /** An `onReceive` method that doesn't verify the action of the intent it receives. */ private class UnverifiedOnReceiveMethod extends OnReceiveMethod { UnverifiedOnReceiveMethod() { - not any(VerifiedIntentConfig c).hasFlow(DataFlow::parameterNode(this.getIntentParameter()), _) + not VerifiedIntentFlow::flow(DataFlow::parameterNode(this.getIntentParameter()), _) } } diff --git a/java/ql/lib/semmle/code/java/security/InsecureLdapAuth.qll b/java/ql/lib/semmle/code/java/security/InsecureLdapAuth.qll new file mode 100644 index 00000000000..80007650c63 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/InsecureLdapAuth.qll @@ -0,0 +1,128 @@ +/** Provides classes to reason about insecure LDAP authentication. */ + +import java +private import semmle.code.java.dataflow.DataFlow +private import semmle.code.java.frameworks.Networking +private import semmle.code.java.frameworks.Jndi + +/** + * An expression that represents an insecure (non-SSL, non-private) LDAP URL. + */ +class InsecureLdapUrl extends Expr { + InsecureLdapUrl() { + this instanceof InsecureLdapUrlLiteral + or + // Concatentation of insecure protcol and non-private host: + // protocol + host + ... + exists(AddExpr e, CompileTimeConstantExpr protocol, Expr rest, Expr host | + e = this and + protocol = e.getLeftOperand() and + rest = e.getRightOperand() and + if rest instanceof AddExpr then host = rest.(AddExpr).getLeftOperand() else host = rest + | + protocol.getStringValue() = "ldap://" and + not exists(string hostString | hostString = getHostname(host) | + hostString.length() = 0 or // Empty host is loopback address + hostString instanceof PrivateHostName + ) + ) + } +} + +/** + * A sink representing the construction of a `DirContextEnvironment`. + */ +class InsecureLdapUrlSink extends DataFlow::Node { + InsecureLdapUrlSink() { + exists(ConstructorCall cc | + cc.getConstructedType().getAnAncestor() instanceof TypeDirContext and + this.asExpr() = cc.getArgument(0) + ) + } +} + +/** + * Holds if `ma` sets `java.naming.security.authentication` (also known as `Context.SECURITY_AUTHENTICATION`) to `simple` in some `Hashtable`. + */ +predicate isBasicAuthEnv(MethodAccess ma) { + hasFieldValueEnv(ma, "java.naming.security.authentication", "simple") or + hasFieldNameEnv(ma, "SECURITY_AUTHENTICATION", "simple") +} + +/** + * Holds if `ma` sets `java.naming.security.protocol` (also known as `Context.SECURITY_PROTOCOL`) to `ssl` in some `Hashtable`. + */ +predicate isSslEnv(MethodAccess ma) { + hasFieldValueEnv(ma, "java.naming.security.protocol", "ssl") or + hasFieldNameEnv(ma, "SECURITY_PROTOCOL", "ssl") +} + +/** + * Holds if `ma` writes the `java.naming.provider.url` (also known as `Context.PROVIDER_URL`) key of a `Hashtable`. + */ +predicate isProviderUrlSetter(MethodAccess ma) { + ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and + ma.getMethod().hasName(["put", "setProperty"]) and + ( + ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "java.naming.provider.url" + or + exists(Field f | + ma.getArgument(0) = f.getAnAccess() and + f.hasName("PROVIDER_URL") and + f.getDeclaringType() instanceof TypeNamingContext + ) + ) +} + +/** + * An insecure (non-SSL, non-private) LDAP URL string literal. + */ +private class InsecureLdapUrlLiteral extends StringLiteral { + InsecureLdapUrlLiteral() { + // Match connection strings with the LDAP protocol and without private IP addresses to reduce false positives. + exists(string s | this.getValue() = s | + s.regexpMatch("(?i)ldap://[\\[a-zA-Z0-9].*") and + not s.substring(7, s.length()) instanceof PrivateHostName + ) + } +} + +/** The class `java.util.Hashtable`. */ +private class TypeHashtable extends Class { + TypeHashtable() { this.getSourceDeclaration().hasQualifiedName("java.util", "Hashtable") } +} + +/** Get the string value of an expression representing a hostname. */ +private string getHostname(Expr expr) { + result = expr.(CompileTimeConstantExpr).getStringValue() or + result = + expr.(VarAccess).getVariable().getAnAssignedValue().(CompileTimeConstantExpr).getStringValue() +} + +/** + * Holds if `ma` sets `fieldValue` to `envValue` in some `Hashtable`. + */ +bindingset[fieldValue, envValue] +private predicate hasFieldValueEnv(MethodAccess ma, string fieldValue, string envValue) { + // environment.put("java.naming.security.authentication", "simple") + ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and + ma.getMethod().hasName(["put", "setProperty"]) and + ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = fieldValue and + ma.getArgument(1).(CompileTimeConstantExpr).getStringValue() = envValue +} + +/** + * Holds if `ma` sets attribute name `fieldName` to `envValue` in some `Hashtable`. + */ +bindingset[fieldName, envValue] +private predicate hasFieldNameEnv(MethodAccess ma, string fieldName, string envValue) { + // environment.put(Context.SECURITY_AUTHENTICATION, "simple") + ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and + ma.getMethod().hasName(["put", "setProperty"]) and + exists(Field f | + ma.getArgument(0) = f.getAnAccess() and + f.hasName(fieldName) and + f.getDeclaringType() instanceof TypeNamingContext + ) and + ma.getArgument(1).(CompileTimeConstantExpr).getStringValue() = envValue +} diff --git a/java/ql/lib/semmle/code/java/security/InsecureLdapAuthQuery.qll b/java/ql/lib/semmle/code/java/security/InsecureLdapAuthQuery.qll new file mode 100644 index 00000000000..6fb53b769e4 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/InsecureLdapAuthQuery.qll @@ -0,0 +1,59 @@ +/** Provides dataflow configurations to reason about insecure LDAP authentication. */ + +import java +import semmle.code.java.dataflow.DataFlow +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.frameworks.Jndi +import semmle.code.java.security.InsecureLdapAuth + +/** + * A taint-tracking configuration for `ldap://` URL in LDAP authentication. + */ +module InsecureLdapUrlConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof InsecureLdapUrl } + + predicate isSink(DataFlow::Node sink) { sink instanceof InsecureLdapUrlSink } + + /** Method call of `env.put()`. */ + predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(MethodAccess ma | + pred.asExpr() = ma.getArgument(1) and + isProviderUrlSetter(ma) and + succ.asExpr() = ma.getQualifier() + ) + } +} + +module InsecureLdapUrlFlow = TaintTracking::Global; + +/** + * A taint-tracking configuration for `simple` basic-authentication in LDAP configuration. + */ +private module BasicAuthConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + exists(MethodAccess ma | + isBasicAuthEnv(ma) and + ma.getQualifier() = src.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() + ) + } + + predicate isSink(DataFlow::Node sink) { sink instanceof InsecureLdapUrlSink } +} + +module BasicAuthFlow = DataFlow::Global; + +/** + * A taint-tracking configuration for `ssl` configuration in LDAP authentication. + */ +private module RequiresSslConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + exists(MethodAccess ma | + isSslEnv(ma) and + ma.getQualifier() = src.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() + ) + } + + predicate isSink(DataFlow::Node sink) { sink instanceof InsecureLdapUrlSink } +} + +module RequiresSslFlow = DataFlow::Global; diff --git a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll index d23a0c8ae4b..970cb4867fd 100644 --- a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll @@ -53,4 +53,4 @@ private module IntentUriPermissionManipulationConfig implements DataFlow::Config * Taint tracking flow for user-provided Intents being returned to third party apps. */ module IntentUriPermissionManipulationFlow = - TaintTracking::Make; + TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/JexlInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/JexlInjectionQuery.qll index 655f78abcba..4138b851e85 100644 --- a/java/ql/lib/semmle/code/java/security/JexlInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/JexlInjectionQuery.qll @@ -39,11 +39,13 @@ private class DefaultJexlInjectionAdditionalTaintStep extends JexlInjectionAddit } /** + * DEPRECATED: Use `JexlInjectionFlow` instead. + * * A taint-tracking configuration for unsafe user input * that is used to construct and evaluate a JEXL expression. * It supports both JEXL 2 and 3. */ -class JexlInjectionConfig extends TaintTracking::Configuration { +deprecated class JexlInjectionConfig extends TaintTracking::Configuration { JexlInjectionConfig() { this = "JexlInjectionConfig" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -55,6 +57,27 @@ class JexlInjectionConfig extends TaintTracking::Configuration { } } +/** + * A taint-tracking configuration for unsafe user input + * that is used to construct and evaluate a JEXL expression. + * It supports both JEXL 2 and 3. + */ +module JexlInjectionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof JexlEvaluationSink } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(JexlInjectionAdditionalTaintStep c).step(node1, node2) + } +} + +/** + * Tracks unsafe user input that is used to construct and evaluate a JEXL expression. + * It supports both JEXL 2 and 3. + */ +module JexlInjectionFlow = TaintTracking::Global; + /** * Holds if `n1` to `n2` is a dataflow step that creates a JEXL script using an unsafe engine * by calling `tainted.createScript(jexlExpr)`. @@ -99,19 +122,15 @@ private predicate createJexlTemplateStep(DataFlow::Node n1, DataFlow::Node n2) { /** * Holds if `expr` is a JEXL engine that is configured with a sandbox. */ -private predicate isSafeEngine(Expr expr) { - exists(SandboxedJexlFlowConfig config | config.hasFlowTo(DataFlow::exprNode(expr))) -} +private predicate isSafeEngine(Expr expr) { SandboxedJexlFlow::flowToExpr(expr) } /** * A configuration for tracking sandboxed JEXL engines. */ -private class SandboxedJexlFlowConfig extends DataFlow2::Configuration { - SandboxedJexlFlowConfig() { this = "JexlInjection::SandboxedJexlFlowConfig" } +private module SandboxedJexlFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node instanceof SandboxedJexlSource } - override predicate isSource(DataFlow::Node node) { node instanceof SandboxedJexlSource } - - override predicate isSink(DataFlow::Node node) { + predicate isSink(DataFlow::Node node) { exists(MethodAccess ma, Method m | m instanceof CreateJexlScriptMethod or m instanceof CreateJexlExpressionMethod or @@ -121,11 +140,13 @@ private class SandboxedJexlFlowConfig extends DataFlow2::Configuration { ) } - override predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) { + predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) { createJexlEngineStep(fromNode, toNode) } } +private module SandboxedJexlFlow = DataFlow::Global; + /** * Defines a data flow source for JEXL engines configured with a sandbox. */ diff --git a/java/ql/lib/semmle/code/java/security/JndiInjection.qll b/java/ql/lib/semmle/code/java/security/JndiInjection.qll index cacf725cc99..6a05bbfdc2c 100644 --- a/java/ql/lib/semmle/code/java/security/JndiInjection.qll +++ b/java/ql/lib/semmle/code/java/security/JndiInjection.qll @@ -9,6 +9,9 @@ private import semmle.code.java.frameworks.SpringLdap /** A data flow sink for unvalidated user input that is used in JNDI lookup. */ abstract class JndiInjectionSink extends DataFlow::Node { } +/** A sanitizer for JNDI injection vulnerabilities. */ +abstract class JndiInjectionSanitizer extends DataFlow::Node { } + /** * A unit class for adding additional taint steps. * diff --git a/java/ql/lib/semmle/code/java/security/JndiInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/JndiInjectionQuery.qll index 9130bb6c7a2..d189c119080 100644 --- a/java/ql/lib/semmle/code/java/security/JndiInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/JndiInjectionQuery.qll @@ -7,9 +7,11 @@ import semmle.code.java.frameworks.SpringLdap import semmle.code.java.security.JndiInjection /** + * DEPRECATED: Use `JndiInjectionFlow` instead. + * * A taint-tracking configuration for unvalidated user input that is used in JNDI lookup. */ -class JndiInjectionFlowConfig extends TaintTracking::Configuration { +deprecated class JndiInjectionFlowConfig extends TaintTracking::Configuration { JndiInjectionFlowConfig() { this = "JndiInjectionFlowConfig" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -17,7 +19,9 @@ class JndiInjectionFlowConfig extends TaintTracking::Configuration { override predicate isSink(DataFlow::Node sink) { sink instanceof JndiInjectionSink } override predicate isSanitizer(DataFlow::Node node) { - node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType + node.getType() instanceof PrimitiveType or + node.getType() instanceof BoxedType or + node instanceof JndiInjectionSanitizer } override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { @@ -25,14 +29,34 @@ class JndiInjectionFlowConfig extends TaintTracking::Configuration { } } +/** + * A taint-tracking configuration for unvalidated user input that is used in JNDI lookup. + */ +module JndiInjectionFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof JndiInjectionSink } + + predicate isBarrier(DataFlow::Node node) { + node.getType() instanceof PrimitiveType or + node.getType() instanceof BoxedType or + node instanceof JndiInjectionSanitizer + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(JndiInjectionAdditionalTaintStep c).step(node1, node2) + } +} + +/** Tracks flow of unvalidated user input that is used in JNDI lookup */ +module JndiInjectionFlow = TaintTracking::Global; + /** * A method that does a JNDI lookup when it receives a `SearchControls` argument with `setReturningObjFlag` = `true` */ private class UnsafeSearchControlsSink extends JndiInjectionSink { UnsafeSearchControlsSink() { - exists(UnsafeSearchControlsConf conf, MethodAccess ma | - conf.hasFlowTo(DataFlow::exprNode(ma.getAnArgument())) - | + exists(MethodAccess ma | UnsafeSearchControlsFlow::flowToExpr(ma.getAnArgument()) | this.asExpr() = ma.getArgument(0) ) } @@ -42,14 +66,14 @@ private class UnsafeSearchControlsSink extends JndiInjectionSink { * Find flows between a `SearchControls` object with `setReturningObjFlag` = `true` * and an argument of an `LdapOperations.search` or `DirContext.search` call. */ -private class UnsafeSearchControlsConf extends DataFlow2::Configuration { - UnsafeSearchControlsConf() { this = "UnsafeSearchControlsConf" } +private module UnsafeSearchControlsConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof UnsafeSearchControls } - override predicate isSource(DataFlow::Node source) { source instanceof UnsafeSearchControls } - - override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeSearchControlsArgument } + predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeSearchControlsArgument } } +private module UnsafeSearchControlsFlow = DataFlow::Global; + /** * An argument of type `SearchControls` of an `LdapOperations.search` or `DirContext.search` call. */ diff --git a/java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll index a706da71e50..a26e08d3edc 100644 --- a/java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll @@ -38,4 +38,4 @@ private module LogInjectionConfig implements DataFlow::ConfigSig { /** * Taint-tracking flow for tracking untrusted user input used in log entries. */ -module LogInjectionFlow = TaintTracking::Make; +module LogInjectionFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/MvelInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/MvelInjectionQuery.qll index 332ea387e6b..a87d7554dd7 100644 --- a/java/ql/lib/semmle/code/java/security/MvelInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/MvelInjectionQuery.qll @@ -6,10 +6,12 @@ import semmle.code.java.dataflow.TaintTracking import semmle.code.java.security.MvelInjection /** + * DEPRECATED: Use `MvelInjectionFlow` instead. + * * A taint-tracking configuration for unsafe user input * that is used to construct and evaluate a MVEL expression. */ -class MvelInjectionFlowConfig extends TaintTracking::Configuration { +deprecated class MvelInjectionFlowConfig extends TaintTracking::Configuration { MvelInjectionFlowConfig() { this = "MvelInjectionFlowConfig" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -24,3 +26,22 @@ class MvelInjectionFlowConfig extends TaintTracking::Configuration { any(MvelInjectionAdditionalTaintStep c).step(node1, node2) } } + +/** + * A taint-tracking configuration for unsafe user input + * that is used to construct and evaluate a MVEL expression. + */ +module MvelInjectionFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof MvelEvaluationSink } + + predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof MvelInjectionSanitizer } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(MvelInjectionAdditionalTaintStep c).step(node1, node2) + } +} + +/** Tracks flow of unsafe user input that is used to construct and evaluate a MVEL expression. */ +module MvelInjectionFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/OgnlInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/OgnlInjectionQuery.qll index 46a886ed65c..d0dfdda94a4 100644 --- a/java/ql/lib/semmle/code/java/security/OgnlInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/OgnlInjectionQuery.qll @@ -5,9 +5,11 @@ import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.OgnlInjection /** + * DEPRECATED: Use `OgnlInjectionFlow` instead. + * * A taint-tracking configuration for unvalidated user input that is used in OGNL EL evaluation. */ -class OgnlInjectionFlowConfig extends TaintTracking::Configuration { +deprecated class OgnlInjectionFlowConfig extends TaintTracking::Configuration { OgnlInjectionFlowConfig() { this = "OgnlInjectionFlowConfig" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -22,3 +24,23 @@ class OgnlInjectionFlowConfig extends TaintTracking::Configuration { any(OgnlInjectionAdditionalTaintStep c).step(node1, node2) } } + +/** + * A taint-tracking configuration for unvalidated user input that is used in OGNL EL evaluation. + */ +module OgnlInjectionFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof OgnlInjectionSink } + + predicate isBarrier(DataFlow::Node node) { + node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(OgnlInjectionAdditionalTaintStep c).step(node1, node2) + } +} + +/** Tracks flow of unvalidated user input that is used in OGNL EL evaluation. */ +module OgnlInjectionFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/RequestForgeryConfig.qll b/java/ql/lib/semmle/code/java/security/RequestForgeryConfig.qll index 1f19d9640e2..0e3afacb83f 100644 --- a/java/ql/lib/semmle/code/java/security/RequestForgeryConfig.qll +++ b/java/ql/lib/semmle/code/java/security/RequestForgeryConfig.qll @@ -35,7 +35,7 @@ deprecated class RequestForgeryConfiguration extends TaintTracking::Configuratio /** * A taint-tracking configuration characterising request-forgery risks. */ -private module RequestForgeryConfig implements DataFlow::ConfigSig { +module RequestForgeryConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource and // Exclude results of remote HTTP requests: fetching something else based on that result @@ -53,4 +53,4 @@ private module RequestForgeryConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node node) { node instanceof RequestForgerySanitizer } } -module RequestForgeryFlow = TaintTracking::Make; +module RequestForgeryFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll b/java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll index e7888afba5d..0d9df09bb74 100644 --- a/java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll +++ b/java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll @@ -42,4 +42,4 @@ private module RsaWithoutOaepConfig implements DataFlow::ConfigSig { } /** Flow for finding RSA ciphers initialized without using OAEP padding. */ -module RsaWithoutOaepFlow = DataFlow::Make; +module RsaWithoutOaepFlow = DataFlow::Global; diff --git a/java/ql/lib/semmle/code/java/security/SensitiveKeyboardCacheQuery.qll b/java/ql/lib/semmle/code/java/security/SensitiveKeyboardCacheQuery.qll index 5a78932a7cd..2a41d2da08c 100644 --- a/java/ql/lib/semmle/code/java/security/SensitiveKeyboardCacheQuery.qll +++ b/java/ql/lib/semmle/code/java/security/SensitiveKeyboardCacheQuery.qll @@ -91,16 +91,14 @@ private predicate inputTypeFieldNotCached(Field f) { } /** Configuration that finds uses of `setInputType` for non cached fields. */ -private class GoodInputTypeConf extends DataFlow::Configuration { - GoodInputTypeConf() { this = "GoodInputTypeConf" } - - override predicate isSource(DataFlow::Node node) { +private module GoodInputTypeConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { inputTypeFieldNotCached(node.asExpr().(FieldAccess).getField()) } - override predicate isSink(DataFlow::Node node) { node.asExpr() = setInputTypeForId(_) } + predicate isSink(DataFlow::Node node) { node.asExpr() = setInputTypeForId(_) } - override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { exists(OrBitwiseExpr bitOr | node1.asExpr() = bitOr.getAChildExpr() and node2.asExpr() = bitOr @@ -108,6 +106,8 @@ private class GoodInputTypeConf extends DataFlow::Configuration { } } +private module GoodInputTypeFlow = DataFlow::Global; + /** Gets a regex indicating that an input field may contain sensitive data. */ private string getInputSensitiveInfoRegex() { result = @@ -130,8 +130,8 @@ AndroidEditableXmlElement getASensitiveCachedInput() { result.getId().regexpMatch(getInputSensitiveInfoRegex()) and ( not inputTypeNotCached(result.getInputType()) and - not exists(GoodInputTypeConf conf, DataFlow::Node sink | - conf.hasFlowTo(sink) and + not exists(DataFlow::Node sink | + GoodInputTypeFlow::flowTo(sink) and sink.asExpr() = setInputTypeForId(result.getId()) ) ) diff --git a/java/ql/lib/semmle/code/java/security/SensitiveLoggingQuery.qll b/java/ql/lib/semmle/code/java/security/SensitiveLoggingQuery.qll index 2ca0c4b69c0..ea687d32a0a 100644 --- a/java/ql/lib/semmle/code/java/security/SensitiveLoggingQuery.qll +++ b/java/ql/lib/semmle/code/java/security/SensitiveLoggingQuery.qll @@ -65,4 +65,4 @@ private module SensitiveLoggerConfig implements DataFlow::ConfigSig { predicate isBarrierIn(Node node) { isSource(node) } } -module SensitiveLoggerFlow = TaintTracking::Make; +module SensitiveLoggerFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/SpelInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/SpelInjectionQuery.qll index 0d9cdc853bb..e54515f4827 100644 --- a/java/ql/lib/semmle/code/java/security/SpelInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/SpelInjectionQuery.qll @@ -7,10 +7,12 @@ private import semmle.code.java.frameworks.spring.SpringExpression private import semmle.code.java.security.SpelInjection /** + * DEPRECATED: Use `SpelInjectionFlow` instead. + * * A taint-tracking configuration for unsafe user input * that is used to construct and evaluate a SpEL expression. */ -class SpelInjectionConfig extends TaintTracking::Configuration { +deprecated class SpelInjectionConfig extends TaintTracking::Configuration { SpelInjectionConfig() { this = "SpelInjectionConfig" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -22,15 +24,30 @@ class SpelInjectionConfig extends TaintTracking::Configuration { } } +/** + * A taint-tracking configuration for unsafe user input + * that is used to construct and evaluate a SpEL expression. + */ +module SpelInjectionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof SpelExpressionEvaluationSink } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(SpelExpressionInjectionAdditionalTaintStep c).step(node1, node2) + } +} + +/** Tracks flow of unsafe user input that is used to construct and evaluate a SpEL expression. */ +module SpelInjectionFlow = TaintTracking::Global; + /** Default sink for SpEL injection vulnerabilities. */ private class DefaultSpelExpressionEvaluationSink extends SpelExpressionEvaluationSink { DefaultSpelExpressionEvaluationSink() { exists(MethodAccess ma | ma.getMethod() instanceof ExpressionEvaluationMethod and ma.getQualifier() = this.asExpr() and - not exists(SafeEvaluationContextFlowConfig config | - config.hasFlowTo(DataFlow::exprNode(ma.getArgument(0))) - ) + not SafeEvaluationContextFlow::flowToExpr(ma.getArgument(0)) ) } } @@ -38,21 +55,21 @@ private class DefaultSpelExpressionEvaluationSink extends SpelExpressionEvaluati /** * A configuration for safe evaluation context that may be used in expression evaluation. */ -private class SafeEvaluationContextFlowConfig extends DataFlow2::Configuration { - SafeEvaluationContextFlowConfig() { this = "SpelInjection::SafeEvaluationContextFlowConfig" } +private module SafeEvaluationContextFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof SafeContextSource } - override predicate isSource(DataFlow::Node source) { source instanceof SafeContextSource } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodAccess ma | ma.getMethod() instanceof ExpressionEvaluationMethod and ma.getArgument(0) = sink.asExpr() ) } - override int fieldFlowBranchLimit() { result = 0 } + int fieldFlowBranchLimit() { result = 0 } } +private module SafeEvaluationContextFlow = DataFlow::Global; + /** * A `ContextSource` that is safe from SpEL injection. */ diff --git a/java/ql/lib/semmle/code/java/security/SqlInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/SqlInjectionQuery.qll index 245c9146b2d..18f3c01571e 100644 --- a/java/ql/lib/semmle/code/java/security/SqlInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/SqlInjectionQuery.qll @@ -11,9 +11,11 @@ import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.QueryInjection /** + * DEPRECATED: Use `QueryInjectionFlow` instead. + * * A taint-tracking configuration for unvalidated user input that is used in SQL queries. */ -class QueryInjectionFlowConfig extends TaintTracking::Configuration { +deprecated class QueryInjectionFlowConfig extends TaintTracking::Configuration { QueryInjectionFlowConfig() { this = "SqlInjectionLib::QueryInjectionFlowConfig" } override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } @@ -31,12 +33,44 @@ class QueryInjectionFlowConfig extends TaintTracking::Configuration { } } +/** + * A taint-tracking configuration for unvalidated user input that is used in SQL queries. + */ +module QueryInjectionFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink } + + predicate isBarrier(DataFlow::Node node) { + node.getType() instanceof PrimitiveType or + node.getType() instanceof BoxedType or + node.getType() instanceof NumberType + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(AdditionalQueryInjectionTaintStep s).step(node1, node2) + } +} + +/** Tracks flow of unvalidated user input that is used in SQL queries. */ +module QueryInjectionFlow = TaintTracking::Global; + /** * Implementation of `SqlTainted.ql`. This is extracted to a QLL so that it * can be excluded from `SqlConcatenated.ql` to avoid overlapping results. */ -predicate queryTaintedBy( +deprecated predicate queryTaintedBy( QueryInjectionSink query, DataFlow::PathNode source, DataFlow::PathNode sink ) { - exists(QueryInjectionFlowConfig conf | conf.hasFlowPath(source, sink) and sink.getNode() = query) + any(QueryInjectionFlowConfig c).hasFlowPath(source, sink) and sink.getNode() = query +} + +/** + * Implementation of `SqlTainted.ql`. This is extracted to a QLL so that it + * can be excluded from `SqlConcatenated.ql` to avoid overlapping results. + */ +predicate queryIsTaintedBy( + QueryInjectionSink query, QueryInjectionFlow::PathNode source, QueryInjectionFlow::PathNode sink +) { + QueryInjectionFlow::flowPath(source, sink) and sink.getNode() = query } diff --git a/java/ql/lib/semmle/code/java/security/TemplateInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/TemplateInjectionQuery.qll index e8ed6f5aea9..783c368482c 100644 --- a/java/ql/lib/semmle/code/java/security/TemplateInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/TemplateInjectionQuery.qll @@ -5,8 +5,12 @@ import semmle.code.java.dataflow.TaintTracking import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.TemplateInjection -/** A taint tracking configuration to reason about server-side template injection (SST) vulnerabilities */ -class TemplateInjectionFlowConfig extends TaintTracking::Configuration { +/** + * DEPRECATED: Use `TemplateInjectionFlow` instead. + * + * A taint tracking configuration to reason about server-side template injection (SST) vulnerabilities + */ +deprecated class TemplateInjectionFlowConfig extends TaintTracking::Configuration { TemplateInjectionFlowConfig() { this = "TemplateInjectionFlowConfig" } override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { @@ -36,3 +40,35 @@ class TemplateInjectionFlowConfig extends TaintTracking::Configuration { any(TemplateInjectionAdditionalTaintStep a).isAdditionalTaintStep(node1, state1, node2, state2) } } + +/** A taint tracking configuration to reason about server-side template injection (SST) vulnerabilities */ +module TemplateInjectionFlowConfig implements DataFlow::StateConfigSig { + class FlowState = DataFlow::FlowState; + + predicate isSource(DataFlow::Node source, FlowState state) { + source.(TemplateInjectionSource).hasState(state) + } + + predicate isSink(DataFlow::Node sink, FlowState state) { + sink.(TemplateInjectionSink).hasState(state) + } + + predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof TemplateInjectionSanitizer } + + predicate isBarrier(DataFlow::Node sanitizer, FlowState state) { + sanitizer.(TemplateInjectionSanitizerWithState).hasState(state) + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(TemplateInjectionAdditionalTaintStep a).isAdditionalTaintStep(node1, node2) + } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 + ) { + any(TemplateInjectionAdditionalTaintStep a).isAdditionalTaintStep(node1, state1, node2, state2) + } +} + +/** Tracks server-side template injection (SST) vulnerabilities */ +module TemplateInjectionFlow = TaintTracking::GlobalWithState; diff --git a/java/ql/lib/semmle/code/java/security/UnsafeAndroidAccessQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeAndroidAccessQuery.qll index 6bd9833047d..267bfd6bf39 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeAndroidAccessQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeAndroidAccessQuery.qll @@ -7,9 +7,11 @@ import semmle.code.java.security.RequestForgery import semmle.code.java.security.UnsafeAndroidAccess /** + * DEPRECATED: Use `FetchUntrustedResourceFlow` instead. + * * A taint configuration tracking flow from untrusted inputs to a resource fetching call. */ -class FetchUntrustedResourceConfiguration extends TaintTracking::Configuration { +deprecated class FetchUntrustedResourceConfiguration extends TaintTracking::Configuration { FetchUntrustedResourceConfiguration() { this = "FetchUntrustedResourceConfiguration" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -20,3 +22,19 @@ class FetchUntrustedResourceConfiguration extends TaintTracking::Configuration { sanitizer instanceof RequestForgerySanitizer } } + +/** + * A taint configuration tracking flow from untrusted inputs to a resource fetching call. + */ +module FetchUntrustedResourceConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof UrlResourceSink } + + predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof RequestForgerySanitizer } +} + +/** + * Detects taint flow from untrusted inputs to a resource fetching call. + */ +module FetchUntrustedResourceFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/UnsafeContentUriResolutionQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeContentUriResolutionQuery.qll index f347f98c9c3..b59c4b79655 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeContentUriResolutionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeContentUriResolutionQuery.qll @@ -41,4 +41,4 @@ private module UnsafeContentResolutionConfig implements DataFlow::ConfigSig { } /** Taint-tracking flow to find paths from remote sources to content URI resolutions. */ -module UnsafeContentResolutionFlow = TaintTracking::Make; +module UnsafeContentResolutionFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/WebviewDebuggingEnabledQuery.qll b/java/ql/lib/semmle/code/java/security/WebviewDebuggingEnabledQuery.qll new file mode 100644 index 00000000000..d5aaf92f412 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/WebviewDebuggingEnabledQuery.qll @@ -0,0 +1,70 @@ +/** Definitions for the Android Webview Debugging Enabled query */ + +import java +import semmle.code.java.dataflow.DataFlow +import semmle.code.java.controlflow.Guards +import semmle.code.java.security.SecurityTests + +/** Holds if `ex` looks like a check that this is a debug build. */ +private predicate isDebugCheck(Expr ex) { + exists(Expr subex, string debug | + debug.toLowerCase().matches(["%debug%", "%test%"]) and + subex.getParent*() = ex + | + subex.(VarAccess).getVariable().getName() = debug + or + subex.(MethodAccess).getMethod().hasName("getProperty") and + subex.(MethodAccess).getAnArgument().(CompileTimeConstantExpr).getStringValue() = debug + ) +} + +/** + * DEPRECATED: Use `WebviewDebugEnabledFlow` instead. + * + * A configuration to find instances of `setWebContentDebuggingEnabled` called with `true` values. + */ +deprecated class WebviewDebugEnabledConfig extends DataFlow::Configuration { + WebviewDebugEnabledConfig() { this = "WebviewDebugEnabledConfig" } + + override predicate isSource(DataFlow::Node node) { + node.asExpr().(BooleanLiteral).getBooleanValue() = true + } + + override predicate isSink(DataFlow::Node node) { + exists(MethodAccess ma | + ma.getMethod().hasQualifiedName("android.webkit", "WebView", "setWebContentsDebuggingEnabled") and + node.asExpr() = ma.getArgument(0) + ) + } + + override predicate isBarrier(DataFlow::Node node) { + exists(Guard debug | isDebugCheck(debug) and debug.controls(node.asExpr().getBasicBlock(), _)) + or + node.getEnclosingCallable().getDeclaringType() instanceof NonSecurityTestClass + } +} + +/** A configuration to find instances of `setWebContentDebuggingEnabled` called with `true` values. */ +module WebviewDebugEnabledConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { + node.asExpr().(BooleanLiteral).getBooleanValue() = true + } + + predicate isSink(DataFlow::Node node) { + exists(MethodAccess ma | + ma.getMethod().hasQualifiedName("android.webkit", "WebView", "setWebContentsDebuggingEnabled") and + node.asExpr() = ma.getArgument(0) + ) + } + + predicate isBarrier(DataFlow::Node node) { + exists(Guard debug | isDebugCheck(debug) and debug.controls(node.asExpr().getBasicBlock(), _)) + or + node.getEnclosingCallable().getDeclaringType() instanceof NonSecurityTestClass + } +} + +/** + * Tracks instances of `setWebContentDebuggingEnabled` with `true` values. + */ +module WebviewDebugEnabledFlow = DataFlow::Global; diff --git a/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll b/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll index 92071c2af1a..f315c55291e 100644 --- a/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll +++ b/java/ql/lib/semmle/code/java/security/WebviewDubuggingEnabledQuery.qll @@ -1,41 +1,11 @@ -/** Definitions for the Android Webview Debugging Enabled query */ +/** + * DEPRECATED: Use `semmle.code.java.security.WebviewDebuggingEnabledQuery` instead. + * + * Definitions for the Android Webview Debugging Enabled query + */ import java -import semmle.code.java.dataflow.DataFlow -import semmle.code.java.controlflow.Guards -import semmle.code.java.security.SecurityTests +private import semmle.code.java.security.WebviewDebuggingEnabledQuery as WebviewDebuggingEnabledQuery -/** Holds if `ex` looks like a check that this is a debug build. */ -private predicate isDebugCheck(Expr ex) { - exists(Expr subex, string debug | - debug.toLowerCase().matches(["%debug%", "%test%"]) and - subex.getParent*() = ex - | - subex.(VarAccess).getVariable().getName() = debug - or - subex.(MethodAccess).getMethod().hasName("getProperty") and - subex.(MethodAccess).getAnArgument().(CompileTimeConstantExpr).getStringValue() = debug - ) -} - -/** A configuration to find instances of `setWebContentDebuggingEnabled` called with `true` values. */ -class WebviewDebugEnabledConfig extends DataFlow::Configuration { - WebviewDebugEnabledConfig() { this = "WebviewDebugEnabledConfig" } - - override predicate isSource(DataFlow::Node node) { - node.asExpr().(BooleanLiteral).getBooleanValue() = true - } - - override predicate isSink(DataFlow::Node node) { - exists(MethodAccess ma | - ma.getMethod().hasQualifiedName("android.webkit", "WebView", "setWebContentsDebuggingEnabled") and - node.asExpr() = ma.getArgument(0) - ) - } - - override predicate isBarrier(DataFlow::Node node) { - exists(Guard debug | isDebugCheck(debug) and debug.controls(node.asExpr().getBasicBlock(), _)) - or - node.getEnclosingCallable().getDeclaringType() instanceof NonSecurityTestClass - } -} +deprecated class WebviewDebugEnabledConfig = + WebviewDebuggingEnabledQuery::WebviewDebugEnabledConfig; diff --git a/java/ql/lib/semmle/code/java/security/XSS.qll b/java/ql/lib/semmle/code/java/security/XSS.qll index a2efc852fd2..2680631318f 100644 --- a/java/ql/lib/semmle/code/java/security/XSS.qll +++ b/java/ql/lib/semmle/code/java/security/XSS.qll @@ -43,7 +43,7 @@ private class DefaultXssSink extends XssSink { or exists(MethodAccess ma | ma.getMethod() instanceof WritingMethod and - XssVulnerableWriterSourceToWritingMethodFlow::hasFlowToExpr(ma.getQualifier()) and + XssVulnerableWriterSourceToWritingMethodFlow::flowToExpr(ma.getQualifier()) and this.asExpr() = ma.getArgument(_) ) } @@ -71,7 +71,7 @@ private module XssVulnerableWriterSourceToWritingMethodFlowConfig implements Dat } private module XssVulnerableWriterSourceToWritingMethodFlow = - TaintTracking::Make; + TaintTracking::Global; /** A method that can be used to output data to an output stream or writer. */ private class WritingMethod extends Method { diff --git a/java/ql/lib/semmle/code/java/security/XsltInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/XsltInjectionQuery.qll index 3cfe91f7408..5622ef60a84 100644 --- a/java/ql/lib/semmle/code/java/security/XsltInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/XsltInjectionQuery.qll @@ -7,9 +7,11 @@ import semmle.code.java.security.XmlParsers import semmle.code.java.security.XsltInjection /** + * DEPRECATED: Use `XsltInjectionFlow` instead. + * * A taint-tracking configuration for unvalidated user input that is used in XSLT transformation. */ -class XsltInjectionFlowConfig extends TaintTracking::Configuration { +deprecated class XsltInjectionFlowConfig extends TaintTracking::Configuration { XsltInjectionFlowConfig() { this = "XsltInjectionFlowConfig" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -25,6 +27,28 @@ class XsltInjectionFlowConfig extends TaintTracking::Configuration { } } +/** + * A taint-tracking configuration for unvalidated user input that is used in XSLT transformation. + */ +module XsltInjectionFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof XsltInjectionSink } + + predicate isBarrier(DataFlow::Node node) { + node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(XsltInjectionAdditionalTaintStep c).step(node1, node2) + } +} + +/** + * Tracks flow from unvalidated user input to XSLT transformation. + */ +module XsltInjectionFlow = TaintTracking::Global; + /** * A set of additional taint steps to consider when taint tracking XSLT related data flows. * These steps use data flow logic themselves. @@ -46,22 +70,17 @@ private predicate newTransformerOrTemplatesStep(DataFlow::Node n1, DataFlow::Nod n2.asExpr() = ma and m.getDeclaringType() instanceof TransformerFactory and m.hasName(["newTransformer", "newTemplates"]) and - not exists(TransformerFactoryWithSecureProcessingFeatureFlowConfig conf | - conf.hasFlowToExpr(ma.getQualifier()) - ) + not TransformerFactoryWithSecureProcessingFeatureFlow::flowToExpr(ma.getQualifier()) ) } /** * A data flow configuration for secure processing feature that is enabled on `TransformerFactory`. */ -private class TransformerFactoryWithSecureProcessingFeatureFlowConfig extends DataFlow2::Configuration +private module TransformerFactoryWithSecureProcessingFeatureFlowConfig implements + DataFlow::ConfigSig { - TransformerFactoryWithSecureProcessingFeatureFlowConfig() { - this = "TransformerFactoryWithSecureProcessingFeatureFlowConfig" - } - - override predicate isSource(DataFlow::Node src) { + predicate isSource(DataFlow::Node src) { exists(Variable v | v = src.asExpr().(VarAccess).getVariable() | exists(TransformerFactoryFeatureConfig config | config.getQualifier() = v.getAnAccess() | config.enables(configSecureProcessing()) @@ -69,16 +88,19 @@ private class TransformerFactoryWithSecureProcessingFeatureFlowConfig extends Da ) } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodAccess ma | sink.asExpr() = ma.getQualifier() and ma.getMethod().getDeclaringType() instanceof TransformerFactory ) } - override int fieldFlowBranchLimit() { result = 0 } + int fieldFlowBranchLimit() { result = 0 } } +private module TransformerFactoryWithSecureProcessingFeatureFlow = + DataFlow::Global; + /** A `ParserConfig` specific to `TransformerFactory`. */ private class TransformerFactoryFeatureConfig extends ParserConfig { TransformerFactoryFeatureConfig() { diff --git a/java/ql/lib/semmle/code/java/security/XxeLocalQuery.qll b/java/ql/lib/semmle/code/java/security/XxeLocalQuery.qll index 02d68fceb5c..d3ac09798a6 100644 --- a/java/ql/lib/semmle/code/java/security/XxeLocalQuery.qll +++ b/java/ql/lib/semmle/code/java/security/XxeLocalQuery.qll @@ -42,4 +42,4 @@ module XxeLocalConfig implements DataFlow::ConfigSig { /** * Detect taint flow of unvalidated local user input that is used in XML external entity expansion. */ -module XxeLocalFlow = TaintTracking::Make; +module XxeLocalFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/XxeRemoteQuery.qll b/java/ql/lib/semmle/code/java/security/XxeRemoteQuery.qll index 46108b7a680..06bccc993a4 100644 --- a/java/ql/lib/semmle/code/java/security/XxeRemoteQuery.qll +++ b/java/ql/lib/semmle/code/java/security/XxeRemoteQuery.qll @@ -42,4 +42,4 @@ module XxeConfig implements DataFlow::ConfigSig { /** * Detect taint flow of unvalidated remote user input that is used in XML external entity expansion. */ -module XxeFlow = TaintTracking::Make; +module XxeFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll b/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll index b852c8393fb..e85e130e381 100644 --- a/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll +++ b/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll @@ -81,4 +81,4 @@ private module PolynomialRedosConfig implements DataFlow::ConfigSig { } } -module PolynomialRedosFlow = TaintTracking::Make; +module PolynomialRedosFlow = TaintTracking::Global; diff --git a/java/ql/lib/semmle/code/java/security/regexp/RegexInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/regexp/RegexInjectionQuery.qll index e2453c08dca..409143c18f8 100644 --- a/java/ql/lib/semmle/code/java/security/regexp/RegexInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/regexp/RegexInjectionQuery.qll @@ -5,8 +5,12 @@ import semmle.code.java.dataflow.FlowSources import semmle.code.java.dataflow.TaintTracking import semmle.code.java.security.regexp.RegexInjection -/** A taint-tracking configuration for untrusted user input used to construct regular expressions. */ -class RegexInjectionConfiguration extends TaintTracking::Configuration { +/** + * DEPRECATED: Use `RegexInjectionFlow` instead. + * + * A taint-tracking configuration for untrusted user input used to construct regular expressions. + */ +deprecated class RegexInjectionConfiguration extends TaintTracking::Configuration { RegexInjectionConfiguration() { this = "RegexInjection" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -15,3 +19,19 @@ class RegexInjectionConfiguration extends TaintTracking::Configuration { override predicate isSanitizer(DataFlow::Node node) { node instanceof RegexInjectionSanitizer } } + +/** + * A taint-tracking configuration for untrusted user input used to construct regular expressions. + */ +module RegexInjectionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof RegexInjectionSink } + + predicate isBarrier(DataFlow::Node node) { node instanceof RegexInjectionSanitizer } +} + +/** + * Taint-tracking flow for untrusted user input used to construct regular expressions. + */ +module RegexInjectionFlow = TaintTracking::Global; diff --git a/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql b/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql index c7c3ce0f835..4058978f29a 100644 --- a/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql +++ b/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql @@ -41,7 +41,7 @@ module TaintedPathConfig implements DataFlow::ConfigSig { } } -module TaintedPath = TaintTracking::Make; +module TaintedPath = TaintTracking::Global; import TaintedPath::PathGraph @@ -53,13 +53,13 @@ import TaintedPath::PathGraph * continue to report there; otherwise we report directly at `sink`. */ DataFlow::Node getReportingNode(DataFlow::Node sink) { - TaintedPath::hasFlowTo(sink) and + TaintedPath::flowTo(sink) and if exists(PathCreation pc | pc.getAnInput() = sink.asExpr()) then result.asExpr() = any(PathCreation pc | pc.getAnInput() = sink.asExpr()) else result = sink } from TaintedPath::PathNode source, TaintedPath::PathNode sink -where TaintedPath::hasFlowPath(source, sink) +where TaintedPath::flowPath(source, sink) select getReportingNode(sink.getNode()), source, sink, "This path depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-022/TaintedPathLocal.ql b/java/ql/src/Security/CWE/CWE-022/TaintedPathLocal.ql index fa62e4e6dfd..94c2b0e68a0 100644 --- a/java/ql/src/Security/CWE/CWE-022/TaintedPathLocal.ql +++ b/java/ql/src/Security/CWE/CWE-022/TaintedPathLocal.ql @@ -41,7 +41,7 @@ module TaintedPathLocalConfig implements DataFlow::ConfigSig { } } -module TaintedPathLocalFlow = TaintTracking::Make; +module TaintedPathLocalFlow = TaintTracking::Global; import TaintedPathLocalFlow::PathGraph @@ -53,13 +53,13 @@ import TaintedPathLocalFlow::PathGraph * continue to report there; otherwise we report directly at `sink`. */ DataFlow::Node getReportingNode(DataFlow::Node sink) { - TaintedPathLocalFlow::hasFlowTo(sink) and + TaintedPathLocalFlow::flowTo(sink) and if exists(PathCreation pc | pc.getAnInput() = sink.asExpr()) then result.asExpr() = any(PathCreation pc | pc.getAnInput() = sink.asExpr()) else result = sink } from TaintedPathLocalFlow::PathNode source, TaintedPathLocalFlow::PathNode sink -where TaintedPathLocalFlow::hasFlowPath(source, sink) +where TaintedPathLocalFlow::flowPath(source, sink) select getReportingNode(sink.getNode()), source, sink, "This path depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-022/ZipSlip.ql b/java/ql/src/Security/CWE/CWE-022/ZipSlip.ql index bae6311f362..b1afdfe65a4 100644 --- a/java/ql/src/Security/CWE/CWE-022/ZipSlip.ql +++ b/java/ql/src/Security/CWE/CWE-022/ZipSlip.ql @@ -44,7 +44,7 @@ module ZipSlipConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node node) { node instanceof PathInjectionSanitizer } } -module ZipSlipFlow = TaintTracking::Make; +module ZipSlipFlow = TaintTracking::Global; import ZipSlipFlow::PathGraph @@ -56,7 +56,7 @@ private class FileCreationSink extends DataFlow::Node { } from ZipSlipFlow::PathNode source, ZipSlipFlow::PathNode sink -where ZipSlipFlow::hasFlowPath(source, sink) +where ZipSlipFlow::flowPath(source, sink) select source.getNode(), source, sink, "Unsanitized archive entry, which may contain '..', is used in a $@.", sink.getNode(), "file system operation" diff --git a/java/ql/src/Security/CWE/CWE-074/JndiInjection.ql b/java/ql/src/Security/CWE/CWE-074/JndiInjection.ql index 8a1438eccaf..900f3d923b3 100644 --- a/java/ql/src/Security/CWE/CWE-074/JndiInjection.ql +++ b/java/ql/src/Security/CWE/CWE-074/JndiInjection.ql @@ -13,9 +13,9 @@ import java import semmle.code.java.security.JndiInjectionQuery -import DataFlow::PathGraph +import JndiInjectionFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, JndiInjectionFlowConfig conf -where conf.hasFlowPath(source, sink) +from JndiInjectionFlow::PathNode source, JndiInjectionFlow::PathNode sink +where JndiInjectionFlow::flowPath(source, sink) select sink.getNode(), source, sink, "JNDI lookup might include name from $@.", source.getNode(), "this user input" diff --git a/java/ql/src/Security/CWE/CWE-074/XsltInjection.ql b/java/ql/src/Security/CWE/CWE-074/XsltInjection.ql index 7c4a9b95c96..9cf98aea259 100644 --- a/java/ql/src/Security/CWE/CWE-074/XsltInjection.ql +++ b/java/ql/src/Security/CWE/CWE-074/XsltInjection.ql @@ -13,9 +13,9 @@ import java import semmle.code.java.security.XsltInjectionQuery -import DataFlow::PathGraph +import XsltInjectionFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, XsltInjectionFlowConfig conf -where conf.hasFlowPath(source, sink) +from XsltInjectionFlow::PathNode source, XsltInjectionFlow::PathNode sink +where XsltInjectionFlow::flowPath(source, sink) select sink.getNode(), source, sink, "XSLT transformation might include stylesheet from $@.", source.getNode(), "this user input" diff --git a/java/ql/src/Security/CWE/CWE-078/ExecTainted.ql b/java/ql/src/Security/CWE/CWE-078/ExecTainted.ql index 4c275f1cacd..d631c52201a 100644 --- a/java/ql/src/Security/CWE/CWE-078/ExecTainted.ql +++ b/java/ql/src/Security/CWE/CWE-078/ExecTainted.ql @@ -16,9 +16,11 @@ import java import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.ExternalProcess import semmle.code.java.security.CommandLineQuery -import DataFlow::PathGraph +import RemoteUserInputToArgumentToExecFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, ArgumentToExec execArg -where execTainted(source, sink, execArg) +from + RemoteUserInputToArgumentToExecFlow::PathNode source, + RemoteUserInputToArgumentToExecFlow::PathNode sink, ArgumentToExec execArg +where execIsTainted(source, sink, execArg) select execArg, source, sink, "This command line depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-078/ExecTaintedLocal.ql b/java/ql/src/Security/CWE/CWE-078/ExecTaintedLocal.ql index e8a80e372b7..5289ac39a9b 100644 --- a/java/ql/src/Security/CWE/CWE-078/ExecTaintedLocal.ql +++ b/java/ql/src/Security/CWE/CWE-078/ExecTaintedLocal.ql @@ -32,7 +32,7 @@ module LocalUserInputToArgumentToExecFlowConfig implements DataFlow::ConfigSig { } module LocalUserInputToArgumentToExecFlow = - TaintTracking::Make; + TaintTracking::Global; import LocalUserInputToArgumentToExecFlow::PathGraph @@ -40,7 +40,7 @@ from LocalUserInputToArgumentToExecFlow::PathNode source, LocalUserInputToArgumentToExecFlow::PathNode sink, ArgumentToExec execArg where - LocalUserInputToArgumentToExecFlow::hasFlowPath(source, sink) and + LocalUserInputToArgumentToExecFlow::flowPath(source, sink) and sink.getNode().asExpr() = execArg select execArg, source, sink, "This command line depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.ql b/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.ql index 0890b3b6021..761b497ef77 100644 --- a/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.ql +++ b/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.ql @@ -48,5 +48,5 @@ predicate builtFromUncontrolledConcat(Expr expr) { from StringArgumentToExec argument where builtFromUncontrolledConcat(argument) and - not execTainted(_, _, argument) + not execIsTainted(_, _, argument) select argument, "Command line is built with string concatenation." diff --git a/java/ql/src/Security/CWE/CWE-079/XSS.ql b/java/ql/src/Security/CWE/CWE-079/XSS.ql index f2b0a65f9fe..dbec746eaf6 100644 --- a/java/ql/src/Security/CWE/CWE-079/XSS.ql +++ b/java/ql/src/Security/CWE/CWE-079/XSS.ql @@ -29,11 +29,11 @@ module XssConfig implements DataFlow::ConfigSig { } } -module XssFlow = TaintTracking::Make; +module XssFlow = TaintTracking::Global; import XssFlow::PathGraph from XssFlow::PathNode source, XssFlow::PathNode sink -where XssFlow::hasFlowPath(source, sink) +where XssFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-079/XSSLocal.ql b/java/ql/src/Security/CWE/CWE-079/XSSLocal.ql index fd9c397f812..90bd2dccc44 100644 --- a/java/ql/src/Security/CWE/CWE-079/XSSLocal.ql +++ b/java/ql/src/Security/CWE/CWE-079/XSSLocal.ql @@ -21,11 +21,11 @@ module XssLocalConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { sink instanceof XssSink } } -module XssLocalFlow = TaintTracking::Make; +module XssLocalFlow = TaintTracking::Global; import XssLocalFlow::PathGraph from XssLocalFlow::PathNode source, XssLocalFlow::PathNode sink -where XssLocalFlow::hasFlowPath(source, sink) +where XssLocalFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-089/SqlConcatenated.ql b/java/ql/src/Security/CWE/CWE-089/SqlConcatenated.ql index 209d778dca8..db12b6e7fbb 100644 --- a/java/ql/src/Security/CWE/CWE-089/SqlConcatenated.ql +++ b/java/ql/src/Security/CWE/CWE-089/SqlConcatenated.ql @@ -36,7 +36,7 @@ module UncontrolledStringBuilderSourceFlowConfig implements DataFlow::ConfigSig } module UncontrolledStringBuilderSourceFlow = - TaintTracking::Make; + TaintTracking::Global; from QueryInjectionSink query, Expr uncontrolled where @@ -45,9 +45,9 @@ where or exists(StringBuilderVar sbv | uncontrolledStringBuilderQuery(sbv, uncontrolled) and - UncontrolledStringBuilderSourceFlow::hasFlow(DataFlow::exprNode(sbv.getToStringCall()), query) + UncontrolledStringBuilderSourceFlow::flow(DataFlow::exprNode(sbv.getToStringCall()), query) ) ) and - not queryTaintedBy(query, _, _) + not queryIsTaintedBy(query, _, _) select query, "Query built by concatenation with $@, which may be untrusted.", uncontrolled, "this expression" diff --git a/java/ql/src/Security/CWE/CWE-089/SqlTainted.ql b/java/ql/src/Security/CWE/CWE-089/SqlTainted.ql index 963a927bf93..3549621c48d 100644 --- a/java/ql/src/Security/CWE/CWE-089/SqlTainted.ql +++ b/java/ql/src/Security/CWE/CWE-089/SqlTainted.ql @@ -15,8 +15,9 @@ import java import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.SqlInjectionQuery -import DataFlow::PathGraph +import QueryInjectionFlow::PathGraph -from QueryInjectionSink query, DataFlow::PathNode source, DataFlow::PathNode sink -where queryTaintedBy(query, source, sink) +from + QueryInjectionSink query, QueryInjectionFlow::PathNode source, QueryInjectionFlow::PathNode sink +where queryIsTaintedBy(query, source, sink) select query, source, sink, "This query depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-089/SqlTaintedLocal.ql b/java/ql/src/Security/CWE/CWE-089/SqlTaintedLocal.ql index 0ad803533c5..34e322247c9 100644 --- a/java/ql/src/Security/CWE/CWE-089/SqlTaintedLocal.ql +++ b/java/ql/src/Security/CWE/CWE-089/SqlTaintedLocal.ql @@ -31,13 +31,13 @@ module LocalUserInputToQueryInjectionFlowConfig implements DataFlow::ConfigSig { } module LocalUserInputToQueryInjectionFlow = - TaintTracking::Make; + TaintTracking::Global; import LocalUserInputToQueryInjectionFlow::PathGraph from LocalUserInputToQueryInjectionFlow::PathNode source, LocalUserInputToQueryInjectionFlow::PathNode sink -where LocalUserInputToQueryInjectionFlow::hasFlowPath(source, sink) +where LocalUserInputToQueryInjectionFlow::flowPath(source, sink) select sink.getNode(), source, sink, "This query depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-090/LdapInjection.ql b/java/ql/src/Security/CWE/CWE-090/LdapInjection.ql index 66371f161ca..e879a33051d 100644 --- a/java/ql/src/Security/CWE/CWE-090/LdapInjection.ql +++ b/java/ql/src/Security/CWE/CWE-090/LdapInjection.ql @@ -17,6 +17,6 @@ import LdapInjectionLib import LdapInjectionFlow::PathGraph from LdapInjectionFlow::PathNode source, LdapInjectionFlow::PathNode sink -where LdapInjectionFlow::hasFlowPath(source, sink) +where LdapInjectionFlow::flowPath(source, sink) select sink.getNode(), source, sink, "This LDAP query depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-090/LdapInjectionLib.qll b/java/ql/src/Security/CWE/CWE-090/LdapInjectionLib.qll index d682e4902d8..d6ca8b1169d 100644 --- a/java/ql/src/Security/CWE/CWE-090/LdapInjectionLib.qll +++ b/java/ql/src/Security/CWE/CWE-090/LdapInjectionLib.qll @@ -17,4 +17,4 @@ module LdapInjectionFlowConfig implements DataFlow::ConfigSig { } } -module LdapInjectionFlow = TaintTracking::Make; +module LdapInjectionFlow = TaintTracking::Global; diff --git a/java/ql/src/Security/CWE/CWE-094/ArbitraryApkInstallation.ql b/java/ql/src/Security/CWE/CWE-094/ArbitraryApkInstallation.ql index aab75a8d368..3255ac99bd6 100644 --- a/java/ql/src/Security/CWE/CWE-094/ArbitraryApkInstallation.ql +++ b/java/ql/src/Security/CWE/CWE-094/ArbitraryApkInstallation.ql @@ -15,5 +15,5 @@ import semmle.code.java.security.ArbitraryApkInstallationQuery import ApkInstallationFlow::PathGraph from ApkInstallationFlow::PathNode source, ApkInstallationFlow::PathNode sink -where ApkInstallationFlow::hasFlowPath(source, sink) +where ApkInstallationFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Arbitrary Android APK installation." diff --git a/java/ql/src/Security/CWE/CWE-094/GroovyInjection.ql b/java/ql/src/Security/CWE/CWE-094/GroovyInjection.ql index f1febd7aa2c..98ae9f2fef3 100644 --- a/java/ql/src/Security/CWE/CWE-094/GroovyInjection.ql +++ b/java/ql/src/Security/CWE/CWE-094/GroovyInjection.ql @@ -13,9 +13,9 @@ import java import semmle.code.java.security.GroovyInjectionQuery -import DataFlow::PathGraph +import GroovyInjectionFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, GroovyInjectionConfig conf -where conf.hasFlowPath(source, sink) +from GroovyInjectionFlow::PathNode source, GroovyInjectionFlow::PathNode sink +where GroovyInjectionFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Groovy script depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-094/InsecureBeanValidation.ql b/java/ql/src/Security/CWE/CWE-094/InsecureBeanValidation.ql index c3a991ddcd5..5e957f23793 100644 --- a/java/ql/src/Security/CWE/CWE-094/InsecureBeanValidation.ql +++ b/java/ql/src/Security/CWE/CWE-094/InsecureBeanValidation.ql @@ -61,7 +61,7 @@ module BeanValidationConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { sink instanceof BeanValidationSink } } -module BeanValidationFlow = TaintTracking::Make; +module BeanValidationFlow = TaintTracking::Global; import BeanValidationFlow::PathGraph @@ -80,6 +80,6 @@ where or exists(SetMessageInterpolatorCall c | not c.isSafe()) ) and - BeanValidationFlow::hasFlowPath(source, sink) + BeanValidationFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Custom constraint error message contains an unsanitized $@.", source, "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-094/JexlInjection.ql b/java/ql/src/Security/CWE/CWE-094/JexlInjection.ql index 3e3cd793c05..5335235d748 100644 --- a/java/ql/src/Security/CWE/CWE-094/JexlInjection.ql +++ b/java/ql/src/Security/CWE/CWE-094/JexlInjection.ql @@ -13,9 +13,9 @@ import java import semmle.code.java.security.JexlInjectionQuery -import DataFlow::PathGraph +import JexlInjectionFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, JexlInjectionConfig conf -where conf.hasFlowPath(source, sink) +from JexlInjectionFlow::PathNode source, JexlInjectionFlow::PathNode sink +where JexlInjectionFlow::flowPath(source, sink) select sink.getNode(), source, sink, "JEXL expression depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-094/MvelInjection.ql b/java/ql/src/Security/CWE/CWE-094/MvelInjection.ql index af623ac6ed9..d7b033cabea 100644 --- a/java/ql/src/Security/CWE/CWE-094/MvelInjection.ql +++ b/java/ql/src/Security/CWE/CWE-094/MvelInjection.ql @@ -13,9 +13,9 @@ import java import semmle.code.java.security.MvelInjectionQuery -import DataFlow::PathGraph +import MvelInjectionFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, MvelInjectionFlowConfig conf -where conf.hasFlowPath(source, sink) +from MvelInjectionFlow::PathNode source, MvelInjectionFlow::PathNode sink +where MvelInjectionFlow::flowPath(source, sink) select sink.getNode(), source, sink, "MVEL expression depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-094/SpelInjection.ql b/java/ql/src/Security/CWE/CWE-094/SpelInjection.ql index d6cc8f33c82..fe1a434cd71 100644 --- a/java/ql/src/Security/CWE/CWE-094/SpelInjection.ql +++ b/java/ql/src/Security/CWE/CWE-094/SpelInjection.ql @@ -14,9 +14,9 @@ import java import semmle.code.java.security.SpelInjectionQuery import semmle.code.java.dataflow.DataFlow -import DataFlow::PathGraph +import SpelInjectionFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, SpelInjectionConfig conf -where conf.hasFlowPath(source, sink) +from SpelInjectionFlow::PathNode source, SpelInjectionFlow::PathNode sink +where SpelInjectionFlow::flowPath(source, sink) select sink.getNode(), source, sink, "SpEL expression depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-094/TemplateInjection.ql b/java/ql/src/Security/CWE/CWE-094/TemplateInjection.ql index 8085c3ec314..6e405cf9b82 100644 --- a/java/ql/src/Security/CWE/CWE-094/TemplateInjection.ql +++ b/java/ql/src/Security/CWE/CWE-094/TemplateInjection.ql @@ -13,9 +13,9 @@ import java import semmle.code.java.security.TemplateInjectionQuery -import DataFlow::PathGraph +import TemplateInjectionFlow::PathGraph -from TemplateInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink -where config.hasFlowPath(source, sink) +from TemplateInjectionFlow::PathNode source, TemplateInjectionFlow::PathNode sink +where TemplateInjectionFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Template, which may contain code, depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-113/ResponseSplitting.ql b/java/ql/src/Security/CWE/CWE-113/ResponseSplitting.ql index b1682dd5774..4fef0a620cd 100644 --- a/java/ql/src/Security/CWE/CWE-113/ResponseSplitting.ql +++ b/java/ql/src/Security/CWE/CWE-113/ResponseSplitting.ql @@ -42,12 +42,12 @@ module ResponseSplittingConfig implements DataFlow::ConfigSig { } } -module ResponseSplitting = TaintTracking::Make; +module ResponseSplitting = TaintTracking::Global; import ResponseSplitting::PathGraph from ResponseSplitting::PathNode source, ResponseSplitting::PathNode sink -where ResponseSplitting::hasFlowPath(source, sink) +where ResponseSplitting::flowPath(source, sink) select sink.getNode(), source, sink, "This header depends on a $@, which may cause a response-splitting vulnerability.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-113/ResponseSplittingLocal.ql b/java/ql/src/Security/CWE/CWE-113/ResponseSplittingLocal.ql index 321f5659e27..402ad1ba1bc 100644 --- a/java/ql/src/Security/CWE/CWE-113/ResponseSplittingLocal.ql +++ b/java/ql/src/Security/CWE/CWE-113/ResponseSplittingLocal.ql @@ -26,12 +26,12 @@ module ResponseSplittingLocalConfig implements DataFlow::ConfigSig { } } -module ResponseSplitting = TaintTracking::Make; +module ResponseSplitting = TaintTracking::Global; import ResponseSplitting::PathGraph from ResponseSplitting::PathNode source, ResponseSplitting::PathNode sink -where ResponseSplitting::hasFlowPath(source, sink) +where ResponseSplitting::flowPath(source, sink) select sink.getNode(), source, sink, "This header depends on a $@, which may cause a response-splitting vulnerability.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-117/LogInjection.ql b/java/ql/src/Security/CWE/CWE-117/LogInjection.ql index 61c1db901b0..dd4ffb6a10a 100644 --- a/java/ql/src/Security/CWE/CWE-117/LogInjection.ql +++ b/java/ql/src/Security/CWE/CWE-117/LogInjection.ql @@ -16,6 +16,6 @@ import semmle.code.java.security.LogInjectionQuery import LogInjectionFlow::PathGraph from LogInjectionFlow::PathNode source, LogInjectionFlow::PathNode sink -where LogInjectionFlow::hasFlowPath(source, sink) +where LogInjectionFlow::flowPath(source, sink) select sink.getNode(), source, sink, "This log entry depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayConstruction.ql b/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayConstruction.ql index c723e7d7067..703bb23b6f5 100644 --- a/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayConstruction.ql +++ b/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayConstruction.ql @@ -23,7 +23,7 @@ private module ImproperValidationOfArrayConstructionConfig implements DataFlow:: } module ImproperValidationOfArrayConstructionFlow = - TaintTracking::Make; + TaintTracking::Global; import ImproperValidationOfArrayConstructionFlow::PathGraph @@ -34,7 +34,7 @@ from where arrayAccess.canThrowOutOfBoundsDueToEmptyArray(sizeExpr, arrayCreation) and sizeExpr = sink.getNode().asExpr() and - ImproperValidationOfArrayConstructionFlow::hasFlowPath(source, sink) + ImproperValidationOfArrayConstructionFlow::flowPath(source, sink) select arrayAccess.getIndexExpr(), source, sink, "This accesses the $@, but the array is initialized using a $@ which may be zero.", arrayCreation, "array", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayConstructionCodeSpecified.ql b/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayConstructionCodeSpecified.ql index a4335eeb2fe..8541074c493 100644 --- a/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayConstructionCodeSpecified.ql +++ b/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayConstructionCodeSpecified.ql @@ -27,7 +27,7 @@ module BoundedFlowSourceConfig implements DataFlow::ConfigSig { } } -module BoundedFlowSourceFlow = DataFlow::Make; +module BoundedFlowSourceFlow = DataFlow::Global; import BoundedFlowSourceFlow::PathGraph @@ -39,7 +39,7 @@ where arrayAccess.canThrowOutOfBoundsDueToEmptyArray(sizeExpr, arrayCreation) and sizeExpr = sink.getNode().asExpr() and boundedsource = source.getNode() and - BoundedFlowSourceFlow::hasFlowPath(source, sink) + BoundedFlowSourceFlow::flowPath(source, sink) select arrayAccess.getIndexExpr(), source, sink, "This accesses the $@, but the array is initialized using $@ which may be zero.", arrayCreation, "array", boundedsource, boundedsource.getDescription().toLowerCase() diff --git a/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayConstructionLocal.ql b/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayConstructionLocal.ql index a1d13c3d8db..f5539e4d05b 100644 --- a/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayConstructionLocal.ql +++ b/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayConstructionLocal.ql @@ -24,7 +24,7 @@ module ImproperValidationOfArrayConstructionLocalConfig implements DataFlow::Con } module ImproperValidationOfArrayConstructionLocalFlow = - TaintTracking::Make; + TaintTracking::Global; import ImproperValidationOfArrayConstructionLocalFlow::PathGraph @@ -35,7 +35,7 @@ from where arrayAccess.canThrowOutOfBoundsDueToEmptyArray(sizeExpr, arrayCreation) and sizeExpr = sink.getNode().asExpr() and - ImproperValidationOfArrayConstructionLocalFlow::hasFlowPath(source, sink) + ImproperValidationOfArrayConstructionLocalFlow::flowPath(source, sink) select arrayAccess.getIndexExpr(), source, sink, "This accesses the $@, but the array is initialized using a $@ which may be zero.", arrayCreation, "array", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayIndex.ql b/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayIndex.ql index 70b23e058a5..6c6755dc484 100644 --- a/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayIndex.ql +++ b/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayIndex.ql @@ -25,7 +25,7 @@ module ImproperValidationOfArrayIndexConfig implements DataFlow::ConfigSig { } module ImproperValidationOfArrayIndexFlow = - TaintTracking::Make; + TaintTracking::Global; import ImproperValidationOfArrayIndexFlow::PathGraph @@ -34,7 +34,7 @@ from ImproperValidationOfArrayIndexFlow::PathNode sink, CheckableArrayAccess arrayAccess where arrayAccess.canThrowOutOfBounds(sink.getNode().asExpr()) and - ImproperValidationOfArrayIndexFlow::hasFlowPath(source, sink) + ImproperValidationOfArrayIndexFlow::flowPath(source, sink) select arrayAccess.getIndexExpr(), source, sink, "This index depends on a $@ which can cause an ArrayIndexOutOfBoundsException.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayIndexCodeSpecified.ql b/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayIndexCodeSpecified.ql index fd07e39b6ba..d2f8f6135a9 100644 --- a/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayIndexCodeSpecified.ql +++ b/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayIndexCodeSpecified.ql @@ -24,7 +24,7 @@ module BoundedFlowSourceConfig implements DataFlow::ConfigSig { } } -module BoundedFlowSourceFlow = DataFlow::Make; +module BoundedFlowSourceFlow = DataFlow::Global; import BoundedFlowSourceFlow::PathGraph @@ -34,7 +34,7 @@ from where arrayAccess.canThrowOutOfBounds(sink.getNode().asExpr()) and boundedsource = source.getNode() and - BoundedFlowSourceFlow::hasFlowPath(source, sink) and + BoundedFlowSourceFlow::flowPath(source, sink) and boundedsource != sink.getNode() and not ( ( diff --git a/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayIndexLocal.ql b/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayIndexLocal.ql index d57df422287..51f54eebd79 100644 --- a/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayIndexLocal.ql +++ b/java/ql/src/Security/CWE/CWE-129/ImproperValidationOfArrayIndexLocal.ql @@ -24,7 +24,7 @@ module ImproperValidationOfArrayIndexLocalConfig implements DataFlow::ConfigSig } module ImproperValidationOfArrayIndexLocalFlow = - TaintTracking::Make; + TaintTracking::Global; import ImproperValidationOfArrayIndexLocalFlow::PathGraph @@ -33,7 +33,7 @@ from ImproperValidationOfArrayIndexLocalFlow::PathNode sink, CheckableArrayAccess arrayAccess where arrayAccess.canThrowOutOfBounds(sink.getNode().asExpr()) and - ImproperValidationOfArrayIndexLocalFlow::hasFlowPath(source, sink) + ImproperValidationOfArrayIndexLocalFlow::flowPath(source, sink) select arrayAccess.getIndexExpr(), source, sink, "This index depends on a $@ which can cause an ArrayIndexOutOfBoundsException.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatString.ql b/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatString.ql index da5bc5372a4..a2d2e9005ef 100644 --- a/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatString.ql +++ b/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatString.ql @@ -27,7 +27,7 @@ module ExternallyControlledFormatStringConfig implements DataFlow::ConfigSig { } module ExternallyControlledFormatStringFlow = - TaintTracking::Make; + TaintTracking::Global; import ExternallyControlledFormatStringFlow::PathGraph @@ -35,7 +35,7 @@ from ExternallyControlledFormatStringFlow::PathNode source, ExternallyControlledFormatStringFlow::PathNode sink, StringFormat formatCall where - ExternallyControlledFormatStringFlow::hasFlowPath(source, sink) and + ExternallyControlledFormatStringFlow::flowPath(source, sink) and sink.getNode().asExpr() = formatCall.getFormatArgument() select formatCall.getFormatArgument(), source, sink, "Format string depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatStringLocal.ql b/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatStringLocal.ql index 0300eaea806..56026c61cfa 100644 --- a/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatStringLocal.ql +++ b/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatStringLocal.ql @@ -23,7 +23,7 @@ module ExternallyControlledFormatStringLocalConfig implements DataFlow::ConfigSi } module ExternallyControlledFormatStringLocalFlow = - TaintTracking::Make; + TaintTracking::Global; import ExternallyControlledFormatStringLocalFlow::PathGraph @@ -31,7 +31,7 @@ from ExternallyControlledFormatStringLocalFlow::PathNode source, ExternallyControlledFormatStringLocalFlow::PathNode sink, StringFormat formatCall where - ExternallyControlledFormatStringLocalFlow::hasFlowPath(source, sink) and + ExternallyControlledFormatStringLocalFlow::flowPath(source, sink) and sink.getNode().asExpr() = formatCall.getFormatArgument() select formatCall.getFormatArgument(), source, sink, "Format string depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql b/java/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql index 99d9879d19e..81e572e4c4e 100644 --- a/java/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql +++ b/java/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql @@ -32,22 +32,23 @@ module RemoteUserInputUnderflowConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node n) { underflowBarrier(n) } } -module RemoteUserInputOverflow = TaintTracking::Make; +module RemoteUserInputOverflow = TaintTracking::Global; -module RemoteUserInputUnderflow = TaintTracking::Make; +module RemoteUserInputUnderflow = TaintTracking::Global; module Flow = - DataFlow::MergePathGraph; + DataFlow::MergePathGraph; import Flow::PathGraph from Flow::PathNode source, Flow::PathNode sink, ArithExpr exp, string effect where - RemoteUserInputOverflow::hasFlowPath(source.asPathNode1(), sink.asPathNode1()) and + RemoteUserInputOverflow::flowPath(source.asPathNode1(), sink.asPathNode1()) and overflowSink(exp, sink.getNode().asExpr()) and effect = "overflow" or - RemoteUserInputUnderflow::hasFlowPath(source.asPathNode2(), sink.asPathNode2()) and + RemoteUserInputUnderflow::flowPath(source.asPathNode2(), sink.asPathNode2()) and underflowSink(exp, sink.getNode().asExpr()) and effect = "underflow" select exp, source, sink, diff --git a/java/ql/src/Security/CWE/CWE-190/ArithmeticTaintedLocal.ql b/java/ql/src/Security/CWE/CWE-190/ArithmeticTaintedLocal.ql index 5fae695bf56..21564787f73 100644 --- a/java/ql/src/Security/CWE/CWE-190/ArithmeticTaintedLocal.ql +++ b/java/ql/src/Security/CWE/CWE-190/ArithmeticTaintedLocal.ql @@ -25,7 +25,7 @@ module ArithmeticTaintedLocalOverflowConfig implements DataFlow::ConfigSig { } module ArithmeticTaintedLocalOverflowFlow = - TaintTracking::Make; + TaintTracking::Global; module ArithmeticTaintedLocalUnderflowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput } @@ -36,20 +36,22 @@ module ArithmeticTaintedLocalUnderflowConfig implements DataFlow::ConfigSig { } module ArithmeticTaintedLocalUnderflowFlow = - TaintTracking::Make; + TaintTracking::Global; module Flow = - DataFlow::MergePathGraph; + DataFlow::MergePathGraph; import Flow::PathGraph from Flow::PathNode source, Flow::PathNode sink, ArithExpr exp, string effect where - ArithmeticTaintedLocalOverflowFlow::hasFlowPath(source.asPathNode1(), sink.asPathNode1()) and + ArithmeticTaintedLocalOverflowFlow::flowPath(source.asPathNode1(), sink.asPathNode1()) and overflowSink(exp, sink.getNode().asExpr()) and effect = "overflow" or - ArithmeticTaintedLocalUnderflowFlow::hasFlowPath(source.asPathNode2(), sink.asPathNode2()) and + ArithmeticTaintedLocalUnderflowFlow::flowPath(source.asPathNode2(), sink.asPathNode2()) and underflowSink(exp, sink.getNode().asExpr()) and effect = "underflow" select exp, source, sink, diff --git a/java/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql b/java/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql index 636480f7400..3ab8deec9b2 100644 --- a/java/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql +++ b/java/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql @@ -33,7 +33,7 @@ module ArithmeticUncontrolledOverflowConfig implements DataFlow::ConfigSig { } module ArithmeticUncontrolledOverflowFlow = - TaintTracking::Make; + TaintTracking::Global; module ArithmeticUncontrolledUnderflowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof TaintSource } @@ -44,20 +44,22 @@ module ArithmeticUncontrolledUnderflowConfig implements DataFlow::ConfigSig { } module ArithmeticUncontrolledUnderflowFlow = - TaintTracking::Make; + TaintTracking::Global; module Flow = - DataFlow::MergePathGraph; + DataFlow::MergePathGraph; import Flow::PathGraph from Flow::PathNode source, Flow::PathNode sink, ArithExpr exp, string effect where - ArithmeticUncontrolledOverflowFlow::hasFlowPath(source.asPathNode1(), sink.asPathNode1()) and + ArithmeticUncontrolledOverflowFlow::flowPath(source.asPathNode1(), sink.asPathNode1()) and overflowSink(exp, sink.getNode().asExpr()) and effect = "overflow" or - ArithmeticUncontrolledUnderflowFlow::hasFlowPath(source.asPathNode2(), sink.asPathNode2()) and + ArithmeticUncontrolledUnderflowFlow::flowPath(source.asPathNode2(), sink.asPathNode2()) and underflowSink(exp, sink.getNode().asExpr()) and effect = "underflow" select exp, source, sink, diff --git a/java/ql/src/Security/CWE/CWE-190/ArithmeticWithExtremeValues.ql b/java/ql/src/Security/CWE/CWE-190/ArithmeticWithExtremeValues.ql index 5070283780b..a054f435229 100644 --- a/java/ql/src/Security/CWE/CWE-190/ArithmeticWithExtremeValues.ql +++ b/java/ql/src/Security/CWE/CWE-190/ArithmeticWithExtremeValues.ql @@ -45,7 +45,7 @@ module MaxValueFlowConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node n) { overflowBarrier(n) } } -module MaxValueFlow = DataFlow::Make; +module MaxValueFlow = DataFlow::Global; module MinValueFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { @@ -59,10 +59,11 @@ module MinValueFlowConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node n) { underflowBarrier(n) } } -module MinValueFlow = DataFlow::Make; +module MinValueFlow = DataFlow::Global; module Flow = - DataFlow::MergePathGraph; + DataFlow::MergePathGraph; import Flow::PathGraph @@ -70,11 +71,11 @@ predicate query( Flow::PathNode source, Flow::PathNode sink, ArithExpr exp, string effect, Type srctyp ) { ( - MaxValueFlow::hasFlowPath(source.asPathNode1(), sink.asPathNode1()) and + MaxValueFlow::flowPath(source.asPathNode1(), sink.asPathNode1()) and overflowSink(exp, sink.getNode().asExpr()) and effect = "overflow" or - MinValueFlow::hasFlowPath(source.asPathNode2(), sink.asPathNode2()) and + MinValueFlow::flowPath(source.asPathNode2(), sink.asPathNode2()) and underflowSink(exp, sink.getNode().asExpr()) and effect = "underflow" ) and diff --git a/java/ql/src/Security/CWE/CWE-200/AndroidWebViewSettingsAllowsContentAccess.ql b/java/ql/src/Security/CWE/CWE-200/AndroidWebViewSettingsAllowsContentAccess.ql index 1b1ca51e7cd..c16b8577d73 100644 --- a/java/ql/src/Security/CWE/CWE-200/AndroidWebViewSettingsAllowsContentAccess.ql +++ b/java/ql/src/Security/CWE/CWE-200/AndroidWebViewSettingsAllowsContentAccess.ql @@ -102,7 +102,7 @@ module WebViewDisallowContentAccessConfig implements DataFlow::StateConfigSig { } module WebViewDisallowContentAccessFlow = - TaintTracking::MakeWithState; + TaintTracking::GlobalWithState; from Expr e where @@ -116,7 +116,7 @@ where // implicit: no setAllowContentAccess(false) exists(WebViewSource source | source.asExpr() = e and - not WebViewDisallowContentAccessFlow::hasFlow(source, _) + not WebViewDisallowContentAccessFlow::flow(source, _) ) select e, "Sensitive information may be exposed via a malicious link due to access to content:// links being allowed in this WebView." diff --git a/java/ql/src/Security/CWE/CWE-200/TempDirLocalInformationDisclosure.ql b/java/ql/src/Security/CWE/CWE-200/TempDirLocalInformationDisclosure.ql index 76998b40b50..400d7159b9a 100644 --- a/java/ql/src/Security/CWE/CWE-200/TempDirLocalInformationDisclosure.ql +++ b/java/ql/src/Security/CWE/CWE-200/TempDirLocalInformationDisclosure.ql @@ -133,7 +133,7 @@ module TempDirSystemGetPropertyToCreateConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { sink instanceof FileCreationSink and - not TempDirSystemGetPropertyDirectlyToMkdir::hasFlowTo(sink) + not TempDirSystemGetPropertyDirectlyToMkdir::flowTo(sink) } predicate isBarrier(DataFlow::Node sanitizer) { @@ -146,7 +146,7 @@ module TempDirSystemGetPropertyToCreateConfig implements DataFlow::ConfigSig { } module TempDirSystemGetPropertyToCreate = - TaintTracking::Make; + TaintTracking::Global; /** * Configuration that tracks calls to to `mkdir` or `mkdirs` that are are directly on the temp directory system property. @@ -179,7 +179,7 @@ module TempDirSystemGetPropertyDirectlyToMkdirConfig implements DataFlow::Config } module TempDirSystemGetPropertyDirectlyToMkdir = - TaintTracking::Make; + TaintTracking::Global; // // Begin configuration for tracking single-method calls that are vulnerable. @@ -261,14 +261,16 @@ module InsecureMethodPathGraph implements DataFlow::PathGraphSig; + DataFlow::MergePathGraph; import Flow::PathGraph from Flow::PathNode source, Flow::PathNode sink, string message where ( - TempDirSystemGetPropertyToCreate::hasFlowPath(source.asPathNode1(), sink.asPathNode1()) and + TempDirSystemGetPropertyToCreate::flowPath(source.asPathNode1(), sink.asPathNode1()) and message = "Local information disclosure vulnerability from $@ due to use of file or directory readable by other local users." or diff --git a/java/ql/src/Security/CWE/CWE-209/StackTraceExposure.ql b/java/ql/src/Security/CWE/CWE-209/StackTraceExposure.ql index be5d3dad848..98a342bcb27 100644 --- a/java/ql/src/Security/CWE/CWE-209/StackTraceExposure.ql +++ b/java/ql/src/Security/CWE/CWE-209/StackTraceExposure.ql @@ -42,7 +42,7 @@ module ServletWriterSourceToPrintStackTraceMethodFlowConfig implements DataFlow: } module ServletWriterSourceToPrintStackTraceMethodFlow = - TaintTracking::Make; + TaintTracking::Global; /** * A call that uses `Throwable.printStackTrace()` on a stream that is connected @@ -51,7 +51,7 @@ module ServletWriterSourceToPrintStackTraceMethodFlow = predicate printsStackToWriter(MethodAccess call) { exists(PrintStackTraceMethod printStackTrace | call.getMethod() = printStackTrace and - ServletWriterSourceToPrintStackTraceMethodFlow::hasFlowToExpr(call.getAnArgument()) + ServletWriterSourceToPrintStackTraceMethodFlow::flowToExpr(call.getAnArgument()) ) } @@ -87,7 +87,7 @@ module StackTraceStringToHttpResponseSinkFlowConfig implements DataFlow::ConfigS } module StackTraceStringToHttpResponseSinkFlow = - TaintTracking::Make; + TaintTracking::Global; /** * A write of stack trace data to an external stream. @@ -104,8 +104,7 @@ predicate printsStackExternally(MethodAccess call, Expr stackTrace) { predicate stringifiedStackFlowsExternally(DataFlow::Node externalExpr, Expr stackTrace) { exists(MethodAccess stackTraceString | stackTraceExpr(stackTrace, stackTraceString) and - StackTraceStringToHttpResponseSinkFlow::hasFlow(DataFlow::exprNode(stackTraceString), - externalExpr) + StackTraceStringToHttpResponseSinkFlow::flow(DataFlow::exprNode(stackTraceString), externalExpr) ) } @@ -127,13 +126,13 @@ module GetMessageFlowSourceToHttpResponseSinkFlowConfig implements DataFlow::Con } module GetMessageFlowSourceToHttpResponseSinkFlow = - TaintTracking::Make; + TaintTracking::Global; /** * A call to `getMessage()` that then flows to a servlet response. */ predicate getMessageFlowsExternally(DataFlow::Node externalExpr, GetMessageFlowSource getMessage) { - GetMessageFlowSourceToHttpResponseSinkFlow::hasFlow(DataFlow::exprNode(getMessage), externalExpr) + GetMessageFlowSourceToHttpResponseSinkFlow::flow(DataFlow::exprNode(getMessage), externalExpr) } from Expr externalExpr, Expr errorInformation diff --git a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql index 281415a0d91..d79abd6e417 100644 --- a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql +++ b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql @@ -20,7 +20,7 @@ import IntentUriPermissionManipulationFlow::PathGraph from IntentUriPermissionManipulationFlow::PathNode source, IntentUriPermissionManipulationFlow::PathNode sink -where IntentUriPermissionManipulationFlow::hasFlowPath(source, sink) +where IntentUriPermissionManipulationFlow::flowPath(source, sink) select sink.getNode(), source, sink, "This Intent can be set with arbitrary flags from a $@, " + "and used to give access to internal content providers.", source.getNode(), diff --git a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql index f6663b8e87d..4bea66796b8 100644 --- a/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql +++ b/java/ql/src/Security/CWE/CWE-297/UnsafeHostnameVerification.ql @@ -77,7 +77,7 @@ module TrustAllHostnameVerifierConfig implements DataFlow::ConfigSig { } } -module TrustAllHostnameVerifierFlow = DataFlow::Make; +module TrustAllHostnameVerifierFlow = DataFlow::Global; import TrustAllHostnameVerifierFlow::PathGraph @@ -118,7 +118,7 @@ from TrustAllHostnameVerifierFlow::PathNode source, TrustAllHostnameVerifierFlow::PathNode sink, RefType verifier where - TrustAllHostnameVerifierFlow::hasFlowPath(source, sink) and + TrustAllHostnameVerifierFlow::flowPath(source, sink) and not isNodeGuardedByFlag(sink.getNode()) and verifier = source.getNode().asExpr().(ClassInstanceExpr).getConstructedType() select sink, source, sink, diff --git a/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql b/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql index ec7ffcbccc1..a423eed3d22 100644 --- a/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql +++ b/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql @@ -38,7 +38,7 @@ module InsecureCryptoConfig implements ConfigSig { } } -module InsecureCryptoFlow = TaintTracking::Make; +module InsecureCryptoFlow = TaintTracking::Global; import InsecureCryptoFlow::PathGraph @@ -48,6 +48,6 @@ from where sink.getNode().asExpr() = c.getAlgoSpec() and source.getNode().asExpr() = s and - InsecureCryptoFlow::hasFlowPath(source, sink) + InsecureCryptoFlow::flowPath(source, sink) select c, source, sink, "Cryptographic algorithm $@ is weak and should not be used.", s, s.getValue() diff --git a/java/ql/src/Security/CWE/CWE-327/MaybeBrokenCryptoAlgorithm.ql b/java/ql/src/Security/CWE/CWE-327/MaybeBrokenCryptoAlgorithm.ql index 47446211438..b5f14421894 100644 --- a/java/ql/src/Security/CWE/CWE-327/MaybeBrokenCryptoAlgorithm.ql +++ b/java/ql/src/Security/CWE/CWE-327/MaybeBrokenCryptoAlgorithm.ql @@ -61,7 +61,7 @@ module InsecureCryptoConfig implements ConfigSig { } } -module InsecureCryptoFlow = TaintTracking::Make; +module InsecureCryptoFlow = TaintTracking::Global; import InsecureCryptoFlow::PathGraph @@ -71,7 +71,7 @@ from where sink.getNode().asExpr() = c.getAlgoSpec() and source.getNode().asExpr() = s and - InsecureCryptoFlow::hasFlowPath(source, sink) + InsecureCryptoFlow::flowPath(source, sink) select c, source, sink, "Cryptographic algorithm $@ may not be secure, consider using a different algorithm.", s, s.getValue() diff --git a/java/ql/src/Security/CWE/CWE-441/UnsafeContentUriResolution.ql b/java/ql/src/Security/CWE/CWE-441/UnsafeContentUriResolution.ql index ce90cc5e00f..4a8c9bc3ad1 100644 --- a/java/ql/src/Security/CWE/CWE-441/UnsafeContentUriResolution.ql +++ b/java/ql/src/Security/CWE/CWE-441/UnsafeContentUriResolution.ql @@ -17,7 +17,7 @@ import semmle.code.java.security.UnsafeContentUriResolutionQuery import UnsafeContentResolutionFlow::PathGraph from UnsafeContentResolutionFlow::PathNode src, UnsafeContentResolutionFlow::PathNode sink -where UnsafeContentResolutionFlow::hasFlowPath(src, sink) +where UnsafeContentResolutionFlow::flowPath(src, sink) select sink.getNode(), src, sink, "This ContentResolver method that resolves a URI depends on a $@.", src.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-470/FragmentInjection.ql b/java/ql/src/Security/CWE/CWE-470/FragmentInjection.ql index 5ffa7068980..6ff9a15eca4 100644 --- a/java/ql/src/Security/CWE/CWE-470/FragmentInjection.ql +++ b/java/ql/src/Security/CWE/CWE-470/FragmentInjection.ql @@ -16,7 +16,7 @@ import semmle.code.java.security.FragmentInjectionQuery import FragmentInjectionTaintFlow::PathGraph from FragmentInjectionTaintFlow::PathNode source, FragmentInjectionTaintFlow::PathNode sink -where FragmentInjectionTaintFlow::hasFlowPath(source, sink) +where FragmentInjectionTaintFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Fragment depends on a $@, which may allow a malicious application to bypass access controls.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-489/WebviewDebuggingEnabled.ql b/java/ql/src/Security/CWE/CWE-489/WebviewDebuggingEnabled.ql index a8f7f81d832..c34a40358d9 100644 --- a/java/ql/src/Security/CWE/CWE-489/WebviewDebuggingEnabled.ql +++ b/java/ql/src/Security/CWE/CWE-489/WebviewDebuggingEnabled.ql @@ -11,9 +11,9 @@ */ import java -import semmle.code.java.security.WebviewDubuggingEnabledQuery -import DataFlow::PathGraph +import semmle.code.java.security.WebviewDebuggingEnabledQuery +import WebviewDebugEnabledFlow::PathGraph -from WebviewDebugEnabledConfig conf, DataFlow::PathNode source, DataFlow::PathNode sink -where conf.hasFlowPath(source, sink) +from WebviewDebugEnabledFlow::PathNode source, WebviewDebugEnabledFlow::PathNode sink +where WebviewDebugEnabledFlow::flowPath(source, sink) select sink, source, sink, "Webview debugging is enabled." diff --git a/java/ql/src/Security/CWE/CWE-522/InsecureLdapAuth.qhelp b/java/ql/src/Security/CWE/CWE-522/InsecureLdapAuth.qhelp new file mode 100644 index 00000000000..096fa99c809 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-522/InsecureLdapAuth.qhelp @@ -0,0 +1,51 @@ + + + + +

+ When using the Java LDAP API to perform LDAPv3-style extended operations + and controls, a context with connection properties including user + credentials is started. Transmission of LDAP credentials in cleartext + allows remote attackers to obtain sensitive information by sniffing the + network. +

+
+ + +

+ Use the ldaps:// protocol to send credentials through SSL or + use SASL authentication. +

+
+ + +

+ In the following (bad) example, a ldap:// URL is used and + credentials will be sent in plaintext. +

+ + +

+ In the following (good) example, a ldaps:// URL is used so + credentials will be encrypted with SSL. +

+ + +

+ In the following (good) example, a ldap:// URL is used, but + SASL authentication is enabled so that the credentials will be encrypted. +

+ +
+ + +
  • + Oracle: + LDAP and LDAPS URLs +
  • +
  • + Oracle: + Simple authentication +
  • +
    +
    diff --git a/java/ql/src/Security/CWE/CWE-522/InsecureLdapAuth.ql b/java/ql/src/Security/CWE/CWE-522/InsecureLdapAuth.ql new file mode 100644 index 00000000000..fb7848bb05e --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-522/InsecureLdapAuth.ql @@ -0,0 +1,24 @@ +/** + * @name Insecure LDAP authentication + * @description LDAP authentication with credentials sent in cleartext makes sensitive information vulnerable to remote attackers + * @kind path-problem + * @problem.severity error + * @security-severity 8.8 + * @precision high + * @id java/insecure-ldap-auth + * @tags security + * external/cwe/cwe-522 + * external/cwe/cwe-319 + */ + +import java +import semmle.code.java.security.InsecureLdapAuthQuery +import InsecureLdapUrlFlow::PathGraph + +from InsecureLdapUrlFlow::PathNode source, InsecureLdapUrlFlow::PathNode sink +where + InsecureLdapUrlFlow::flowPath(source, sink) and + BasicAuthFlow::flowTo(sink.getNode()) and + not RequiresSslFlow::flowTo(sink.getNode()) +select sink.getNode(), source, sink, "Insecure LDAP authentication from $@.", source.getNode(), + "LDAP connection string" diff --git a/java/ql/src/Security/CWE/CWE-522/LdapAuthUseLdap.java b/java/ql/src/Security/CWE/CWE-522/LdapAuthUseLdap.java new file mode 100644 index 00000000000..36826bf27b0 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-522/LdapAuthUseLdap.java @@ -0,0 +1,9 @@ +String ldapUrl = "ldap://ad.your-server.com:389"; +Hashtable environment = new Hashtable(); +environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); +environment.put(Context.PROVIDER_URL, ldapUrl); +environment.put(Context.REFERRAL, "follow"); +environment.put(Context.SECURITY_AUTHENTICATION, "simple"); +environment.put(Context.SECURITY_PRINCIPAL, ldapUserName); +environment.put(Context.SECURITY_CREDENTIALS, password); +DirContext dirContext = new InitialDirContext(environment); diff --git a/java/ql/src/Security/CWE/CWE-522/LdapAuthUseLdaps.java b/java/ql/src/Security/CWE/CWE-522/LdapAuthUseLdaps.java new file mode 100644 index 00000000000..e7d8bdefc60 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-522/LdapAuthUseLdaps.java @@ -0,0 +1,9 @@ +String ldapUrl = "ldaps://ad.your-server.com:636"; +Hashtable environment = new Hashtable(); +environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); +environment.put(Context.PROVIDER_URL, ldapUrl); +environment.put(Context.REFERRAL, "follow"); +environment.put(Context.SECURITY_AUTHENTICATION, "simple"); +environment.put(Context.SECURITY_PRINCIPAL, ldapUserName); +environment.put(Context.SECURITY_CREDENTIALS, password); +DirContext dirContext = new InitialDirContext(environment); diff --git a/java/ql/src/Security/CWE/CWE-522/LdapEnableSasl.java b/java/ql/src/Security/CWE/CWE-522/LdapEnableSasl.java new file mode 100644 index 00000000000..2e191c62918 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-522/LdapEnableSasl.java @@ -0,0 +1,9 @@ +String ldapUrl = "ldap://ad.your-server.com:389"; +Hashtable environment = new Hashtable(); +environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); +environment.put(Context.PROVIDER_URL, ldapUrl); +environment.put(Context.REFERRAL, "follow"); +environment.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5 GSSAPI"); +environment.put(Context.SECURITY_PRINCIPAL, ldapUserName); +environment.put(Context.SECURITY_CREDENTIALS, password); +DirContext dirContext = new InitialDirContext(environment); diff --git a/java/ql/src/Security/CWE/CWE-532/SensitiveInfoLog.ql b/java/ql/src/Security/CWE/CWE-532/SensitiveInfoLog.ql index a884ba6c242..9b306bc1bd1 100644 --- a/java/ql/src/Security/CWE/CWE-532/SensitiveInfoLog.ql +++ b/java/ql/src/Security/CWE/CWE-532/SensitiveInfoLog.ql @@ -16,6 +16,6 @@ import semmle.code.java.security.SensitiveLoggingQuery import SensitiveLoggerFlow::PathGraph from SensitiveLoggerFlow::PathNode source, SensitiveLoggerFlow::PathNode sink -where SensitiveLoggerFlow::hasFlowPath(source, sink) +where SensitiveLoggerFlow::flowPath(source, sink) select sink.getNode(), source, sink, "This $@ is written to a log file.", source.getNode(), "potentially sensitive information" diff --git a/java/ql/src/Security/CWE/CWE-601/UrlRedirect.ql b/java/ql/src/Security/CWE/CWE-601/UrlRedirect.ql index cf9393830b0..78c9c86c762 100644 --- a/java/ql/src/Security/CWE/CWE-601/UrlRedirect.ql +++ b/java/ql/src/Security/CWE/CWE-601/UrlRedirect.ql @@ -21,11 +21,11 @@ module UrlRedirectConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { sink instanceof UrlRedirectSink } } -module UrlRedirectFlow = TaintTracking::Make; +module UrlRedirectFlow = TaintTracking::Global; import UrlRedirectFlow::PathGraph from UrlRedirectFlow::PathNode source, UrlRedirectFlow::PathNode sink -where UrlRedirectFlow::hasFlowPath(source, sink) +where UrlRedirectFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Untrusted URL redirection depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-601/UrlRedirectLocal.ql b/java/ql/src/Security/CWE/CWE-601/UrlRedirectLocal.ql index de44173ec57..d8a28f52abb 100644 --- a/java/ql/src/Security/CWE/CWE-601/UrlRedirectLocal.ql +++ b/java/ql/src/Security/CWE/CWE-601/UrlRedirectLocal.ql @@ -21,11 +21,11 @@ module UrlRedirectLocalConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { sink instanceof UrlRedirectSink } } -module UrlRedirectLocalFlow = TaintTracking::Make; +module UrlRedirectLocalFlow = TaintTracking::Global; import UrlRedirectLocalFlow::PathGraph from UrlRedirectLocalFlow::PathNode source, UrlRedirectLocalFlow::PathNode sink -where UrlRedirectLocalFlow::hasFlowPath(source, sink) +where UrlRedirectLocalFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Untrusted URL redirection depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-611/XXE.ql b/java/ql/src/Security/CWE/CWE-611/XXE.ql index 708d4f08ee7..5520d332ed6 100644 --- a/java/ql/src/Security/CWE/CWE-611/XXE.ql +++ b/java/ql/src/Security/CWE/CWE-611/XXE.ql @@ -19,7 +19,7 @@ import semmle.code.java.security.XxeRemoteQuery import XxeFlow::PathGraph from XxeFlow::PathNode source, XxeFlow::PathNode sink -where XxeFlow::hasFlowPath(source, sink) +where XxeFlow::flowPath(source, sink) select sink.getNode(), source, sink, "XML parsing depends on a $@ without guarding against external entity expansion.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-611/XXELocal.ql b/java/ql/src/Security/CWE/CWE-611/XXELocal.ql index 0ab4ddcc106..5e306a65349 100644 --- a/java/ql/src/Security/CWE/CWE-611/XXELocal.ql +++ b/java/ql/src/Security/CWE/CWE-611/XXELocal.ql @@ -19,7 +19,7 @@ import semmle.code.java.security.XxeLocalQuery import XxeLocalFlow::PathGraph from XxeLocalFlow::PathNode source, XxeLocalFlow::PathNode sink -where XxeLocalFlow::hasFlowPath(source, sink) +where XxeLocalFlow::flowPath(source, sink) select sink.getNode(), source, sink, "XML parsing depends on a $@ without guarding against external entity expansion.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-614/InsecureCookie.ql b/java/ql/src/Security/CWE/CWE-614/InsecureCookie.ql index 807ef383dee..0d24e9315c1 100644 --- a/java/ql/src/Security/CWE/CWE-614/InsecureCookie.ql +++ b/java/ql/src/Security/CWE/CWE-614/InsecureCookie.ql @@ -47,10 +47,10 @@ module SecureCookieConfig implements DataFlow::ConfigSig { } } -module SecureCookieFlow = DataFlow::Make; +module SecureCookieFlow = DataFlow::Global; from MethodAccess add where add.getMethod() instanceof ResponseAddCookieMethod and - not SecureCookieFlow::hasFlowToExpr(add.getArgument(0)) + not SecureCookieFlow::flowToExpr(add.getArgument(0)) select add, "Cookie is added to response without the 'secure' flag being set." diff --git a/java/ql/src/Security/CWE/CWE-643/XPathInjection.ql b/java/ql/src/Security/CWE/CWE-643/XPathInjection.ql index eacebd3f098..18a4d76873b 100644 --- a/java/ql/src/Security/CWE/CWE-643/XPathInjection.ql +++ b/java/ql/src/Security/CWE/CWE-643/XPathInjection.ql @@ -22,11 +22,11 @@ module XPathInjectionConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { sink instanceof XPathInjectionSink } } -module XPathInjectionFlow = TaintTracking::Make; +module XPathInjectionFlow = TaintTracking::Global; import XPathInjectionFlow::PathGraph from XPathInjectionFlow::PathNode source, XPathInjectionFlow::PathNode sink -where XPathInjectionFlow::hasFlowPath(source, sink) +where XPathInjectionFlow::flowPath(source, sink) select sink.getNode(), source, sink, "XPath expression depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-681/NumericCastTainted.ql b/java/ql/src/Security/CWE/CWE-681/NumericCastTainted.ql index 3caefe3fd09..3194e0f8e7b 100644 --- a/java/ql/src/Security/CWE/CWE-681/NumericCastTainted.ql +++ b/java/ql/src/Security/CWE/CWE-681/NumericCastTainted.ql @@ -34,14 +34,14 @@ module NumericCastFlowConfig implements DataFlow::ConfigSig { } } -module NumericCastFlow = TaintTracking::Make; +module NumericCastFlow = TaintTracking::Global; import NumericCastFlow::PathGraph from NumericCastFlow::PathNode source, NumericCastFlow::PathNode sink, NumericNarrowingCastExpr exp where sink.getNode().asExpr() = exp.getExpr() and - NumericCastFlow::hasFlowPath(source, sink) + NumericCastFlow::flowPath(source, sink) select exp, source, sink, "This cast to a narrower type depends on a $@, potentially causing truncation.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-681/NumericCastTaintedLocal.ql b/java/ql/src/Security/CWE/CWE-681/NumericCastTaintedLocal.ql index 41757ab419a..b9224769562 100644 --- a/java/ql/src/Security/CWE/CWE-681/NumericCastTaintedLocal.ql +++ b/java/ql/src/Security/CWE/CWE-681/NumericCastTaintedLocal.ql @@ -32,7 +32,7 @@ module NumericCastFlowConfig implements DataFlow::ConfigSig { } } -module NumericCastFlow = TaintTracking::Make; +module NumericCastFlow = TaintTracking::Global; import NumericCastFlow::PathGraph @@ -42,7 +42,7 @@ from where exp.getExpr() = tainted and sink.getNode().asExpr() = tainted and - NumericCastFlow::hasFlowPath(source, sink) and + NumericCastFlow::flowPath(source, sink) and not exists(RightShiftOp e | e.getShiftedVariable() = tainted.getVariable()) select exp, source, sink, "This cast to a narrower type depends on a $@, potentially causing truncation.", source.getNode(), diff --git a/java/ql/src/Security/CWE/CWE-730/PolynomialReDoS.ql b/java/ql/src/Security/CWE/CWE-730/PolynomialReDoS.ql index 8a1244b93d1..2ba45ca083c 100644 --- a/java/ql/src/Security/CWE/CWE-730/PolynomialReDoS.ql +++ b/java/ql/src/Security/CWE/CWE-730/PolynomialReDoS.ql @@ -21,7 +21,7 @@ from PolynomialRedosFlow::PathNode source, PolynomialRedosFlow::PathNode sink, SuperlinearBackTracking::PolynomialBackTrackingTerm regexp where - PolynomialRedosFlow::hasFlowPath(source, sink) and + PolynomialRedosFlow::flowPath(source, sink) and regexp.getRootTerm() = sink.getNode().(PolynomialRedosSink).getRegExp() select sink, source, sink, "This $@ that depends on a $@ may run slow on strings " + regexp.getPrefixMessage() + diff --git a/java/ql/src/Security/CWE/CWE-730/RegexInjection.ql b/java/ql/src/Security/CWE/CWE-730/RegexInjection.ql index 820e0949d22..64fe906658b 100644 --- a/java/ql/src/Security/CWE/CWE-730/RegexInjection.ql +++ b/java/ql/src/Security/CWE/CWE-730/RegexInjection.ql @@ -15,9 +15,9 @@ import java import semmle.code.java.security.regexp.RegexInjectionQuery -import DataFlow::PathGraph +import RegexInjectionFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, RegexInjectionConfiguration c -where c.hasFlowPath(source, sink) +from RegexInjectionFlow::PathNode source, RegexInjectionFlow::PathNode sink +where RegexInjectionFlow::flowPath(source, sink) select sink.getNode(), source, sink, "This regular expression is constructed from a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql b/java/ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql index 277b1b5790e..6cdcab9d4cc 100644 --- a/java/ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql +++ b/java/ql/src/Security/CWE/CWE-749/UnsafeAndroidAccess.ql @@ -14,9 +14,9 @@ import java import semmle.code.java.security.UnsafeAndroidAccessQuery -import DataFlow::PathGraph +import FetchUntrustedResourceFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, FetchUntrustedResourceConfiguration conf -where conf.hasFlowPath(source, sink) +from FetchUntrustedResourceFlow::PathNode source, FetchUntrustedResourceFlow::PathNode sink +where FetchUntrustedResourceFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Unsafe resource fetching in Android WebView due to $@.", source.getNode(), sink.getNode().(UrlResourceSink).getSinkType() diff --git a/java/ql/src/Security/CWE/CWE-780/RsaWithoutOaep.ql b/java/ql/src/Security/CWE/CWE-780/RsaWithoutOaep.ql index a2475202dd8..2191a4a7401 100644 --- a/java/ql/src/Security/CWE/CWE-780/RsaWithoutOaep.ql +++ b/java/ql/src/Security/CWE/CWE-780/RsaWithoutOaep.ql @@ -15,6 +15,6 @@ import semmle.code.java.security.RsaWithoutOaepQuery import RsaWithoutOaepFlow::PathGraph from RsaWithoutOaepFlow::PathNode source, RsaWithoutOaepFlow::PathNode sink -where RsaWithoutOaepFlow::hasFlowPath(source, sink) +where RsaWithoutOaepFlow::flowPath(source, sink) select source, source, sink, "This specification is used to $@ without OAEP padding.", sink, "initialize an RSA cipher" diff --git a/java/ql/src/Security/CWE/CWE-807/TaintedPermissionsCheck.ql b/java/ql/src/Security/CWE/CWE-807/TaintedPermissionsCheck.ql index bb48958443f..87266e0df47 100644 --- a/java/ql/src/Security/CWE/CWE-807/TaintedPermissionsCheck.ql +++ b/java/ql/src/Security/CWE/CWE-807/TaintedPermissionsCheck.ql @@ -60,14 +60,13 @@ module TaintedPermissionsCheckFlowConfig implements DataFlow::ConfigSig { } } -module TaintedPermissionsCheckFlow = TaintTracking::Make; +module TaintedPermissionsCheckFlow = TaintTracking::Global; import TaintedPermissionsCheckFlow::PathGraph from TaintedPermissionsCheckFlow::PathNode source, TaintedPermissionsCheckFlow::PathNode sink, PermissionsConstruction p -where - sink.getNode().asExpr() = p.getInput() and TaintedPermissionsCheckFlow::hasFlowPath(source, sink) +where sink.getNode().asExpr() = p.getInput() and TaintedPermissionsCheckFlow::flowPath(source, sink) select p, source, sink, "Permissions check depends on a $@.", source.getNode(), "user-controlled value" diff --git a/java/ql/src/Security/CWE/CWE-917/OgnlInjection.ql b/java/ql/src/Security/CWE/CWE-917/OgnlInjection.ql index 06fc54ab22a..964360a96bf 100644 --- a/java/ql/src/Security/CWE/CWE-917/OgnlInjection.ql +++ b/java/ql/src/Security/CWE/CWE-917/OgnlInjection.ql @@ -13,9 +13,9 @@ import java import semmle.code.java.security.OgnlInjectionQuery -import DataFlow::PathGraph +import OgnlInjectionFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, OgnlInjectionFlowConfig conf -where conf.hasFlowPath(source, sink) +from OgnlInjectionFlow::PathNode source, OgnlInjectionFlow::PathNode sink +where OgnlInjectionFlow::flowPath(source, sink) select sink.getNode(), source, sink, "OGNL Expression Language statement depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-918/RequestForgery.ql b/java/ql/src/Security/CWE/CWE-918/RequestForgery.ql index c3455dc4beb..570a7af54cc 100644 --- a/java/ql/src/Security/CWE/CWE-918/RequestForgery.ql +++ b/java/ql/src/Security/CWE/CWE-918/RequestForgery.ql @@ -16,6 +16,6 @@ import semmle.code.java.security.RequestForgeryConfig import RequestForgeryFlow::PathGraph from RequestForgeryFlow::PathNode source, RequestForgeryFlow::PathNode sink -where RequestForgeryFlow::hasFlowPath(source, sink) +where RequestForgeryFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Potential server-side request forgery due to a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-927/SensitiveCommunication.ql b/java/ql/src/Security/CWE/CWE-927/SensitiveCommunication.ql index 59a7d827cf6..576927b1d72 100644 --- a/java/ql/src/Security/CWE/CWE-927/SensitiveCommunication.ql +++ b/java/ql/src/Security/CWE/CWE-927/SensitiveCommunication.ql @@ -16,6 +16,6 @@ import semmle.code.java.security.AndroidSensitiveCommunicationQuery import SensitiveCommunicationFlow::PathGraph from SensitiveCommunicationFlow::PathNode source, SensitiveCommunicationFlow::PathNode sink -where SensitiveCommunicationFlow::hasFlowPath(source, sink) +where SensitiveCommunicationFlow::flowPath(source, sink) select sink.getNode(), source, sink, "This call may leak $@.", source.getNode(), "sensitive information" diff --git a/java/ql/src/Security/CWE/CWE-940/AndroidIntentRedirection.ql b/java/ql/src/Security/CWE/CWE-940/AndroidIntentRedirection.ql index 1ace2fc4fcc..5fac8c7ecc1 100644 --- a/java/ql/src/Security/CWE/CWE-940/AndroidIntentRedirection.ql +++ b/java/ql/src/Security/CWE/CWE-940/AndroidIntentRedirection.ql @@ -15,10 +15,10 @@ import java import semmle.code.java.security.AndroidIntentRedirectionQuery -import DataFlow::PathGraph +import IntentRedirectionFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, IntentRedirectionConfiguration conf -where conf.hasFlowPath(source, sink) +from IntentRedirectionFlow::PathNode source, IntentRedirectionFlow::PathNode sink +where IntentRedirectionFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Arbitrary Android activities or services can be started from a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Telemetry/ExtractorInformation.ql b/java/ql/src/Telemetry/ExtractorInformation.ql index 48eb49a1b07..51990878a34 100644 --- a/java/ql/src/Telemetry/ExtractorInformation.ql +++ b/java/ql/src/Telemetry/ExtractorInformation.ql @@ -9,6 +9,8 @@ import java import semmle.code.java.Diagnostics +extensible predicate extractorInformationSkipKey(string key); + predicate compilationInfo(string key, int value) { exists(Compilation c, string infoKey | key = infoKey + ": " + c.getInfo(infoKey) and @@ -85,13 +87,16 @@ predicate extractorTotalDiagnostics(string key, int value) { from string key, int value where - compilationInfo(key, value) or - fileCount(key, value) or - fileCountByExtension(key, value) or - totalNumberOfLines(key, value) or - numberOfLinesOfCode(key, value) or - totalNumberOfLinesByExtension(key, value) or - numberOfLinesOfCodeByExtension(key, value) or - extractorDiagnostics(key, value) or - extractorTotalDiagnostics(key, value) + not extractorInformationSkipKey(key) and + ( + compilationInfo(key, value) or + fileCount(key, value) or + fileCountByExtension(key, value) or + totalNumberOfLines(key, value) or + numberOfLinesOfCode(key, value) or + totalNumberOfLinesByExtension(key, value) or + numberOfLinesOfCodeByExtension(key, value) or + extractorDiagnostics(key, value) or + extractorTotalDiagnostics(key, value) + ) select key, value diff --git a/java/ql/src/Telemetry/ExtractorInformation.yml b/java/ql/src/Telemetry/ExtractorInformation.yml new file mode 100644 index 00000000000..74a7f99520b --- /dev/null +++ b/java/ql/src/Telemetry/ExtractorInformation.yml @@ -0,0 +1,5 @@ +extensions: + - addsTo: + pack: codeql/java-queries + extensible: extractorInformationSkipKey + data: [] diff --git a/java/ql/src/change-notes/2023-03-08-insecure-ldap-authentication.md b/java/ql/src/change-notes/2023-03-08-insecure-ldap-authentication.md new file mode 100644 index 00000000000..8331274891c --- /dev/null +++ b/java/ql/src/change-notes/2023-03-08-insecure-ldap-authentication.md @@ -0,0 +1,4 @@ +--- +category: newQuery +--- +* The query `java/insecure-ldap-auth` has been promoted from experimental to the main query pack. This query detects transmission of cleartext credentials in LDAP authentication. Insecure LDAP authentication causes sensitive information to be vulnerable to remote attackers. This query was originally [submitted as an experimental query by @luchua-bc](https://github.com/github/codeql/pull/4854) \ No newline at end of file diff --git a/java/ql/src/experimental/Security/CWE/CWE-078/ExecTainted.ql b/java/ql/src/experimental/Security/CWE/CWE-078/ExecTainted.ql index e672519d1c7..45fa0982b25 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-078/ExecTainted.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-078/ExecTainted.ql @@ -17,10 +17,12 @@ import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.ExternalProcess import semmle.code.java.security.CommandLineQuery import JSchOSInjection -import DataFlow::PathGraph +import RemoteUserInputToArgumentToExecFlow::PathGraph // This is a clone of query `java/command-line-injection` that also includes experimental sinks. -from DataFlow::PathNode source, DataFlow::PathNode sink, ArgumentToExec execArg -where execTainted(source, sink, execArg) +from + RemoteUserInputToArgumentToExecFlow::PathNode source, + RemoteUserInputToArgumentToExecFlow::PathNode sink, ArgumentToExec execArg +where execIsTainted(source, sink, execArg) select execArg, source, sink, "This command line depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.java b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.java deleted file mode 100644 index 3c5f6555100..00000000000 --- a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.java +++ /dev/null @@ -1,24 +0,0 @@ -public class InsecureLdapAuth { - /** LDAP authentication */ - public DirContext ldapAuth(String ldapUserName, String password) { - { - // BAD: LDAP authentication in cleartext - String ldapUrl = "ldap://ad.your-server.com:389"; - } - - { - // GOOD: LDAPS authentication over SSL - String ldapUrl = "ldaps://ad.your-server.com:636"; - } - - Hashtable environment = new Hashtable(); - environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); - environment.put(Context.PROVIDER_URL, ldapUrl); - environment.put(Context.REFERRAL, "follow"); - environment.put(Context.SECURITY_AUTHENTICATION, "simple"); - environment.put(Context.SECURITY_PRINCIPAL, ldapUserName); - environment.put(Context.SECURITY_CREDENTIALS, password); - DirContext dirContext = new InitialDirContext(environment); - return dirContext; - } -} diff --git a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.qhelp b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.qhelp deleted file mode 100644 index c729759a06e..00000000000 --- a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.qhelp +++ /dev/null @@ -1,27 +0,0 @@ - - - - -

    When using the Java LDAP API to perform LDAPv3-style extended operations and controls, a context with connection properties including user credentials is started. Transmission of LDAP credentials in cleartext allows remote attackers to obtain sensitive information by sniffing the network.

    -
    - - -

    Use LDAPS to send credentials through SSL or use SASL authentication.

    -
    - - -

    The following example shows two ways of using LDAP authentication. In the 'BAD' case, the credentials are transmitted in cleartext. In the 'GOOD' case, the credentials are transmitted over SSL.

    - -
    - - -
  • - Oracle: - LDAP and LDAPS URLs -
  • -
  • - Oracle: - Simple authentication -
  • -
    -
    diff --git a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql b/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql deleted file mode 100644 index 5f2bda49f7c..00000000000 --- a/java/ql/src/experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql +++ /dev/null @@ -1,211 +0,0 @@ -/** - * @name Insecure LDAP authentication - * @description LDAP authentication with credentials sent in cleartext. - * @kind path-problem - * @problem.severity warning - * @precision medium - * @id java/insecure-ldap-auth - * @tags security - * experimental - * external/cwe/cwe-522 - * external/cwe/cwe-319 - */ - -import java -import DataFlow -import semmle.code.java.frameworks.Jndi -import semmle.code.java.frameworks.Networking -import semmle.code.java.dataflow.TaintTracking -import DataFlow::PathGraph - -/** - * Insecure (non-SSL, non-private) LDAP URL string literal. - */ -class InsecureLdapUrlLiteral extends StringLiteral { - InsecureLdapUrlLiteral() { - // Match connection strings with the LDAP protocol and without private IP addresses to reduce false positives. - exists(string s | this.getValue() = s | - s.regexpMatch("(?i)ldap://[\\[a-zA-Z0-9].*") and - not s.substring(7, s.length()) instanceof PrivateHostName - ) - } -} - -/** The class `java.util.Hashtable`. */ -class TypeHashtable extends Class { - TypeHashtable() { this.getSourceDeclaration().hasQualifiedName("java.util", "Hashtable") } -} - -/** - * Holds if a non-private LDAP string is concatenated from both protocol and host. - */ -predicate concatInsecureLdapString(Expr protocol, Expr host) { - protocol.(CompileTimeConstantExpr).getStringValue() = "ldap://" and - not exists(string hostString | - hostString = host.(CompileTimeConstantExpr).getStringValue() or - hostString = - host.(VarAccess).getVariable().getAnAssignedValue().(CompileTimeConstantExpr).getStringValue() - | - hostString.length() = 0 or // Empty host is loopback address - hostString instanceof PrivateHostName - ) -} - -/** Gets the leftmost operand in a concatenated string */ -Expr getLeftmostConcatOperand(Expr expr) { - if expr instanceof AddExpr - then result = getLeftmostConcatOperand(expr.(AddExpr).getLeftOperand()) - else result = expr -} - -/** - * String concatenated with `InsecureLdapUrlLiteral`. - */ -class InsecureLdapUrl extends Expr { - InsecureLdapUrl() { - this instanceof InsecureLdapUrlLiteral - or - concatInsecureLdapString(this.(AddExpr).getLeftOperand(), - getLeftmostConcatOperand(this.(AddExpr).getRightOperand())) - } -} - -/** - * Holds if `ma` writes the `java.naming.provider.url` (also known as `Context.PROVIDER_URL`) key of a `Hashtable`. - */ -predicate isProviderUrlSetter(MethodAccess ma) { - ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and - ma.getMethod().hasName(["put", "setProperty"]) and - ( - ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "java.naming.provider.url" - or - exists(Field f | - ma.getArgument(0) = f.getAnAccess() and - f.hasName("PROVIDER_URL") and - f.getDeclaringType() instanceof TypeNamingContext - ) - ) -} - -/** - * Holds if `ma` sets `fieldValue` to `envValue` in some `Hashtable`. - */ -bindingset[fieldValue, envValue] -predicate hasFieldValueEnv(MethodAccess ma, string fieldValue, string envValue) { - // environment.put("java.naming.security.authentication", "simple") - ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and - ma.getMethod().hasName(["put", "setProperty"]) and - ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = fieldValue and - ma.getArgument(1).(CompileTimeConstantExpr).getStringValue() = envValue -} - -/** - * Holds if `ma` sets attribute name `fieldName` to `envValue` in some `Hashtable`. - */ -bindingset[fieldName, envValue] -predicate hasFieldNameEnv(MethodAccess ma, string fieldName, string envValue) { - // environment.put(Context.SECURITY_AUTHENTICATION, "simple") - ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and - ma.getMethod().hasName(["put", "setProperty"]) and - exists(Field f | - ma.getArgument(0) = f.getAnAccess() and - f.hasName(fieldName) and - f.getDeclaringType() instanceof TypeNamingContext - ) and - ma.getArgument(1).(CompileTimeConstantExpr).getStringValue() = envValue -} - -/** - * Holds if `ma` sets `java.naming.security.authentication` (also known as `Context.SECURITY_AUTHENTICATION`) to `simple` in some `Hashtable`. - */ -predicate isBasicAuthEnv(MethodAccess ma) { - hasFieldValueEnv(ma, "java.naming.security.authentication", "simple") or - hasFieldNameEnv(ma, "SECURITY_AUTHENTICATION", "simple") -} - -/** - * Holds if `ma` sets `java.naming.security.protocol` (also known as `Context.SECURITY_PROTOCOL`) to `ssl` in some `Hashtable`. - */ -predicate isSslEnv(MethodAccess ma) { - hasFieldValueEnv(ma, "java.naming.security.protocol", "ssl") or - hasFieldNameEnv(ma, "SECURITY_PROTOCOL", "ssl") -} - -/** - * A taint-tracking configuration for `ldap://` URL in LDAP authentication. - */ -class InsecureUrlFlowConfig extends TaintTracking::Configuration { - InsecureUrlFlowConfig() { this = "InsecureLdapAuth:InsecureUrlFlowConfig" } - - /** Source of `ldap://` connection string. */ - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof InsecureLdapUrl } - - /** Sink of directory context creation. */ - override predicate isSink(DataFlow::Node sink) { - exists(ConstructorCall cc | - cc.getConstructedType().getAnAncestor() instanceof TypeDirContext and - sink.asExpr() = cc.getArgument(0) - ) - } - - /** Method call of `env.put()`. */ - override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { - exists(MethodAccess ma | - pred.asExpr() = ma.getArgument(1) and - isProviderUrlSetter(ma) and - succ.asExpr() = ma.getQualifier() - ) - } -} - -/** - * A taint-tracking configuration for `simple` basic-authentication in LDAP configuration. - */ -class BasicAuthFlowConfig extends DataFlow::Configuration { - BasicAuthFlowConfig() { this = "InsecureLdapAuth:BasicAuthFlowConfig" } - - /** Source of `simple` configuration. */ - override predicate isSource(DataFlow::Node src) { - exists(MethodAccess ma | - isBasicAuthEnv(ma) and ma.getQualifier() = src.(PostUpdateNode).getPreUpdateNode().asExpr() - ) - } - - /** Sink of directory context creation. */ - override predicate isSink(DataFlow::Node sink) { - exists(ConstructorCall cc | - cc.getConstructedType().getAnAncestor() instanceof TypeDirContext and - sink.asExpr() = cc.getArgument(0) - ) - } -} - -/** - * A taint-tracking configuration for `ssl` configuration in LDAP authentication. - */ -class SslFlowConfig extends DataFlow::Configuration { - SslFlowConfig() { this = "InsecureLdapAuth:SSLFlowConfig" } - - /** Source of `ssl` configuration. */ - override predicate isSource(DataFlow::Node src) { - exists(MethodAccess ma | - isSslEnv(ma) and ma.getQualifier() = src.(PostUpdateNode).getPreUpdateNode().asExpr() - ) - } - - /** Sink of directory context creation. */ - override predicate isSink(DataFlow::Node sink) { - exists(ConstructorCall cc | - cc.getConstructedType().getAnAncestor() instanceof TypeDirContext and - sink.asExpr() = cc.getArgument(0) - ) - } -} - -from DataFlow::PathNode source, DataFlow::PathNode sink, InsecureUrlFlowConfig config -where - config.hasFlowPath(source, sink) and - exists(BasicAuthFlowConfig bc | bc.hasFlowTo(sink.getNode())) and - not exists(SslFlowConfig sc | sc.hasFlowTo(sink.getNode())) -select sink.getNode(), source, sink, "Insecure LDAP authentication from $@.", source.getNode(), - "LDAP connection string" diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml index 6295db39e31..52ed9a30a2d 100644 --- a/java/ql/src/qlpack.yml +++ b/java/ql/src/qlpack.yml @@ -10,3 +10,5 @@ dependencies: codeql/java-all: ${workspace} codeql/suite-helpers: ${workspace} codeql/util: ${workspace} +dataExtensions: + - Telemetry/ExtractorInformation.yml diff --git a/java/ql/src/utils/modelgenerator/CaptureNeutralModels.ql b/java/ql/src/utils/modelgenerator/CaptureNeutralModels.ql index 1f0c9fa5427..06fc24a054c 100644 --- a/java/ql/src/utils/modelgenerator/CaptureNeutralModels.ql +++ b/java/ql/src/utils/modelgenerator/CaptureNeutralModels.ql @@ -7,7 +7,7 @@ */ import internal.CaptureModels -import internal.CaptureSummaryFlow +import internal.CaptureSummaryFlowQuery from DataFlowTargetApi api, string noflow where noflow = captureNoFlow(api) diff --git a/java/ql/src/utils/modelgenerator/CaptureSinkModels.ql b/java/ql/src/utils/modelgenerator/CaptureSinkModels.ql index 8d273ba77f8..4bc621ad6bb 100644 --- a/java/ql/src/utils/modelgenerator/CaptureSinkModels.ql +++ b/java/ql/src/utils/modelgenerator/CaptureSinkModels.ql @@ -8,10 +8,6 @@ import internal.CaptureModels -class Activate extends ActiveConfiguration { - override predicate activateToSinkConfig() { any() } -} - from DataFlowTargetApi api, string sink where sink = captureSink(api) select sink order by sink diff --git a/java/ql/src/utils/modelgenerator/CaptureSourceModels.ql b/java/ql/src/utils/modelgenerator/CaptureSourceModels.ql index f4fc9982797..51e6f68e62c 100644 --- a/java/ql/src/utils/modelgenerator/CaptureSourceModels.ql +++ b/java/ql/src/utils/modelgenerator/CaptureSourceModels.ql @@ -8,10 +8,6 @@ import internal.CaptureModels -class Activate extends ActiveConfiguration { - override predicate activateFromSourceConfig() { any() } -} - from DataFlowTargetApi api, string source where source = captureSource(api) select source order by source diff --git a/java/ql/src/utils/modelgenerator/CaptureSummaryModels.ql b/java/ql/src/utils/modelgenerator/CaptureSummaryModels.ql index 33d07d5f2c1..607ddbe4fb6 100644 --- a/java/ql/src/utils/modelgenerator/CaptureSummaryModels.ql +++ b/java/ql/src/utils/modelgenerator/CaptureSummaryModels.ql @@ -7,7 +7,7 @@ */ import internal.CaptureModels -import internal.CaptureSummaryFlow +import internal.CaptureSummaryFlowQuery from DataFlowTargetApi api, string flow where flow = captureFlow(api) diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll index 893c62191b3..5ca3ffed782 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -5,14 +5,6 @@ private import CaptureModelsSpecific -class ActiveConfiguration extends Unit { - predicate activateThroughFlowConfig() { none() } - - predicate activateFromSourceConfig() { none() } - - predicate activateToSinkConfig() { none() } -} - class DataFlowTargetApi extends TargetApiSpecific { DataFlowTargetApi() { isRelevantForDataFlowModels(this) } } @@ -46,6 +38,20 @@ private predicate isRelevantContent(DataFlow::Content c) { DataFlowPrivate::containerContent(c) } +/** + * Gets the MaD string representation of the parameter node `p`. + */ +string parameterNodeAsInput(DataFlow::ParameterNode p) { + result = parameterAccess(p.asParameter()) + or + result = qualifierString() and p instanceof InstanceParameterNode +} + +/** + * Gets the MaD input string representation of `source`. + */ +string asInputArgument(DataFlow::Node source) { result = asInputArgumentSpecific(source) } + /** * Gets the summary model for `api` with `input`, `output` and `kind`. */ @@ -111,61 +117,70 @@ string captureQualifierFlow(TargetApiSpecific api) { private int accessPathLimit() { result = 2 } +private newtype TTaintState = + TTaintRead(int n) { n in [0 .. accessPathLimit()] } or + TTaintStore(int n) { n in [1 .. accessPathLimit()] } + +abstract private class TaintState extends TTaintState { + abstract string toString(); +} + /** * A FlowState representing a tainted read. */ -private class TaintRead extends DataFlow::FlowState { +private class TaintRead extends TaintState, TTaintRead { private int step; - TaintRead() { this = "TaintRead(" + step + ")" and step in [0 .. accessPathLimit()] } + TaintRead() { this = TTaintRead(step) } /** * Gets the flow state step number. */ int getStep() { result = step } + + override string toString() { result = "TaintRead(" + step + ")" } } /** * A FlowState representing a tainted write. */ -private class TaintStore extends DataFlow::FlowState { +private class TaintStore extends TaintState, TTaintStore { private int step; - TaintStore() { this = "TaintStore(" + step + ")" and step in [1 .. accessPathLimit()] } + TaintStore() { this = TTaintStore(step) } /** * Gets the flow state step number. */ int getStep() { result = step } + + override string toString() { result = "TaintStore(" + step + ")" } } /** - * A TaintTracking Configuration used for tracking flow through APIs. + * A data-flow configuration for tracking flow through APIs. * The sources are the parameters of an API and the sinks are the return values (excluding `this`) and parameters. * * This can be used to generate Flow summaries for APIs from parameter to return. */ -private class ThroughFlowConfig extends TaintTracking::Configuration { - ThroughFlowConfig() { - this = "ThroughFlowConfig" and any(ActiveConfiguration ac).activateThroughFlowConfig() - } +module ThroughFlowConfig implements DataFlow::StateConfigSig { + class FlowState = TaintState; - override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { + predicate isSource(DataFlow::Node source, FlowState state) { source instanceof DataFlow::ParameterNode and source.getEnclosingCallable() instanceof DataFlowTargetApi and state.(TaintRead).getStep() = 0 } - override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { + predicate isSink(DataFlow::Node sink, FlowState state) { sink instanceof DataFlowImplCommon::ReturnNodeExt and not isOwnInstanceAccessNode(sink) and not exists(captureQualifierFlow(sink.asExpr().getEnclosingCallable())) and (state instanceof TaintRead or state instanceof TaintStore) } - override predicate isAdditionalTaintStep( - DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, - DataFlow::FlowState state2 + predicate isAdditionalFlowStep( + DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 ) { exists(DataFlowImplCommon::TypedContent tc | DataFlowImplCommon::store(node1, tc, node2, _) and @@ -184,24 +199,28 @@ private class ThroughFlowConfig extends TaintTracking::Configuration { ) } - override predicate isSanitizer(DataFlow::Node n) { + predicate isBarrier(DataFlow::Node n) { exists(Type t | t = n.getType() and not isRelevantType(t)) } - override DataFlow::FlowFeature getAFeature() { + predicate isBarrier(DataFlow::Node node, FlowState state) { none() } + + DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureEqualSourceSinkCallContext } } +private module ThroughFlow = TaintTracking::GlobalWithState; + /** * Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter. */ string captureThroughFlow(DataFlowTargetApi api) { exists( - ThroughFlowConfig config, DataFlow::ParameterNode p, - DataFlowImplCommon::ReturnNodeExt returnNodeExt, string input, string output + DataFlow::ParameterNode p, DataFlowImplCommon::ReturnNodeExt returnNodeExt, string input, + string output | - config.hasFlow(p, returnNodeExt) and + ThroughFlow::flow(p, returnNodeExt) and returnNodeExt.getEnclosingCallable() = api and input = parameterNodeAsInput(p) and output = returnNodeAsOutput(returnNodeExt) and @@ -211,41 +230,37 @@ string captureThroughFlow(DataFlowTargetApi api) { } /** - * A TaintTracking Configuration used for tracking flow through APIs. + * A dataflow configuration used for finding new sources. * The sources are the already known existing sources and the sinks are the API return nodes. * * This can be used to generate Source summaries for an API, if the API expose an already known source * via its return (then the API itself becomes a source). */ -private class FromSourceConfiguration extends TaintTracking::Configuration { - FromSourceConfiguration() { - this = "FromSourceConfiguration" and any(ActiveConfiguration ac).activateFromSourceConfig() - } +module FromSourceConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) } - override predicate isSource(DataFlow::Node source) { ExternalFlow::sourceNode(source, _) } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(DataFlowTargetApi c | sink instanceof DataFlowImplCommon::ReturnNodeExt and sink.getEnclosingCallable() = c ) } - override DataFlow::FlowFeature getAFeature() { - result instanceof DataFlow::FeatureHasSinkCallContext - } + DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSinkCallContext } - override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { isRelevantTaintStep(node1, node2) } } +private module FromSource = TaintTracking::Global; + /** * Gets the source model(s) of `api`, if there is flow from an existing known source to the return of `api`. */ string captureSource(DataFlowTargetApi api) { - exists(DataFlow::Node source, DataFlow::Node sink, FromSourceConfiguration config, string kind | - config.hasFlow(source, sink) and + exists(DataFlow::Node source, DataFlow::Node sink, string kind | + FromSource::flow(source, sink) and ExternalFlow::sourceNode(source, kind) and api = sink.getEnclosingCallable() and isRelevantSourceKind(kind) and @@ -254,35 +269,30 @@ string captureSource(DataFlowTargetApi api) { } /** - * A TaintTracking Configuration used for tracking flow through APIs. + * A dataflow configuration used for finding new sinks. * The sources are the parameters of the API and the fields of the enclosing type. * * This can be used to generate Sink summaries for APIs, if the API propagates a parameter (or enclosing type field) * into an existing known sink (then the API itself becomes a sink). */ -private class PropagateToSinkConfiguration extends TaintTracking::Configuration { - PropagateToSinkConfiguration() { - this = "parameters or fields flowing into sinks" and - any(ActiveConfiguration ac).activateToSinkConfig() - } +module PropagateToSinkConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { apiSource(source) } - override predicate isSource(DataFlow::Node source) { apiSource(source) } + predicate isSink(DataFlow::Node sink) { ExternalFlow::sinkNode(sink, _) } - override predicate isSink(DataFlow::Node sink) { ExternalFlow::sinkNode(sink, _) } + predicate isBarrier(DataFlow::Node node) { sinkModelSanitizer(node) } - override predicate isSanitizer(DataFlow::Node node) { sinkModelSanitizer(node) } - - override DataFlow::FlowFeature getAFeature() { - result instanceof DataFlow::FeatureHasSourceCallContext - } + DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext } } +private module PropagateToSink = TaintTracking::Global; + /** * Gets the sink model(s) of `api`, if there is flow from a parameter to an existing known sink. */ string captureSink(DataFlowTargetApi api) { - exists(DataFlow::Node src, DataFlow::Node sink, PropagateToSinkConfiguration config, string kind | - config.hasFlow(src, sink) and + exists(DataFlow::Node src, DataFlow::Node sink, string kind | + PropagateToSink::flow(src, sink) and ExternalFlow::sinkNode(sink, kind) and api = src.getEnclosingCallable() and isRelevantSinkKind(kind) and diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll b/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll index bce229d10a6..8823a8977d5 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll @@ -3,7 +3,6 @@ */ private import java as J -private import semmle.code.java.dataflow.internal.DataFlowNodes private import semmle.code.java.dataflow.internal.DataFlowPrivate private import semmle.code.java.dataflow.internal.ContainerFlow as ContainerFlow private import semmle.code.java.dataflow.DataFlow as Df @@ -130,7 +129,7 @@ private predicate partialModel(TargetApiSpecific api, string type, string name, } /** - * Computes the first 6 columns for CSV rows. + * Computes the first 6 columns for MaD rows. */ string asPartialModel(TargetApiSpecific api) { exists(string type, string name, string parameters | @@ -145,7 +144,7 @@ string asPartialModel(TargetApiSpecific api) { } /** - * Computes the first 4 columns for neutral CSV rows. + * Computes the first 4 columns for neutral MaD rows. */ string asPartialNeutralModel(TargetApiSpecific api) { exists(string type, string name, string parameters | @@ -187,11 +186,14 @@ predicate isRelevantType(J::Type t) { } /** - * Gets the CSV string representation of the qualifier. + * Gets the MaD string representation of the qualifier. */ string qualifierString() { result = "Argument[this]" } -private string parameterAccess(J::Parameter p) { +/** + * Gets the MaD string representation of the parameter `p`. + */ +string parameterAccess(J::Parameter p) { if p.getType() instanceof J::Array and not isPrimitiveTypeUsedForBulkData(p.getType().(J::Array).getElementType()) @@ -202,17 +204,10 @@ private string parameterAccess(J::Parameter p) { else result = "Argument[" + p.getPosition() + "]" } -/** - * Gets the CSV string representation of the parameter node `p`. - */ -string parameterNodeAsInput(DataFlow::ParameterNode p) { - result = parameterAccess(p.asParameter()) - or - result = qualifierString() and p instanceof DataFlow::InstanceParameterNode -} +class InstanceParameterNode = DataFlow::InstanceParameterNode; /** - * Gets the CSV string represention of the the return node `node`. + * Gets the MaD string represention of the the return node `node`. */ string returnNodeAsOutput(DataFlowImplCommon::ReturnNodeExt node) { if node.getKind() instanceof DataFlowImplCommon::ValueReturnKind @@ -268,9 +263,9 @@ predicate apiSource(DataFlow::Node source) { } /** - * Gets the CSV input string representation of `source`. + * Gets the MaD input string representation of `source`. */ -string asInputArgument(DataFlow::Node source) { +string asInputArgumentSpecific(DataFlow::Node source) { exists(int pos | source.(DataFlow::ParameterNode).isParameterOf(_, pos) and result = "Argument[" + pos + "]" diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll b/java/ql/src/utils/modelgenerator/internal/CaptureSummaryFlowQuery.qll similarity index 94% rename from java/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll rename to java/ql/src/utils/modelgenerator/internal/CaptureSummaryFlowQuery.qll index b859fef0ebb..65a892262f5 100644 --- a/java/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll +++ b/java/ql/src/utils/modelgenerator/internal/CaptureSummaryFlowQuery.qll @@ -1,9 +1,5 @@ private import CaptureModels -private class Activate extends ActiveConfiguration { - override predicate activateThroughFlowConfig() { any() } -} - /** * Capture fluent APIs that return `this`. * Example of a fluent API: diff --git a/java/ql/test/TestUtilities/InlineFlowTest.qll b/java/ql/test/TestUtilities/InlineFlowTest.qll index bd4ef924da2..efc5a6fab2b 100644 --- a/java/ql/test/TestUtilities/InlineFlowTest.qll +++ b/java/ql/test/TestUtilities/InlineFlowTest.qll @@ -57,9 +57,9 @@ module DefaultFlowConfig implements DataFlow::ConfigSig { int fieldFlowBranchLimit() { result = 1000 } } -private module DefaultValueFlow = DataFlow::Make; +private module DefaultValueFlow = DataFlow::Global; -private module DefaultTaintFlow = TaintTracking::Make; +private module DefaultTaintFlow = TaintTracking::Global; class DefaultValueFlowConf extends DataFlow::Configuration { DefaultValueFlowConf() { this = "qltest:defaultValueFlowConf" } @@ -118,13 +118,13 @@ class InlineFlowTest extends InlineExpectationsTest { predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { if exists(EnableLegacyConfiguration e) then getValueFlowConfig().hasFlow(src, sink) - else DefaultValueFlow::hasFlow(src, sink) + else DefaultValueFlow::flow(src, sink) } predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { if exists(EnableLegacyConfiguration e) then getTaintFlowConfig().hasFlow(src, sink) - else DefaultTaintFlow::hasFlow(src, sink) + else DefaultTaintFlow::flow(src, sink) } DataFlow::Configuration getValueFlowConfig() { result = any(DefaultValueFlowConf config) } diff --git a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected deleted file mode 100644 index 4ae27bd27af..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.expected +++ /dev/null @@ -1,111 +0,0 @@ -edges -| InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:15:41:15:47 | ldapUrl : String | -| InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:20:49:20:59 | environment | -| InsecureLdapAuth.java:15:3:15:13 | environment [post update] [] : String | InsecureLdapAuth.java:20:49:20:59 | environment | -| InsecureLdapAuth.java:15:41:15:47 | ldapUrl : String | InsecureLdapAuth.java:15:3:15:13 | environment [post update] [] : String | -| InsecureLdapAuth.java:17:3:17:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:20:49:20:59 | environment | -| InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:29:41:29:47 | ldapUrl : String | -| InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:34:49:34:59 | environment | -| InsecureLdapAuth.java:29:3:29:13 | environment [post update] [] : String | InsecureLdapAuth.java:34:49:34:59 | environment | -| InsecureLdapAuth.java:29:41:29:47 | ldapUrl : String | InsecureLdapAuth.java:29:3:29:13 | environment [post update] [] : String | -| InsecureLdapAuth.java:31:3:31:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:34:49:34:59 | environment | -| InsecureLdapAuth.java:45:3:45:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:48:49:48:59 | environment | -| InsecureLdapAuth.java:53:20:53:50 | "ldap://ad.your-server.com:636" : String | InsecureLdapAuth.java:57:41:57:47 | ldapUrl : String | -| InsecureLdapAuth.java:53:20:53:50 | "ldap://ad.your-server.com:636" : String | InsecureLdapAuth.java:63:49:63:59 | environment | -| InsecureLdapAuth.java:57:3:57:13 | environment [post update] [] : String | InsecureLdapAuth.java:63:49:63:59 | environment | -| InsecureLdapAuth.java:57:41:57:47 | ldapUrl : String | InsecureLdapAuth.java:57:3:57:13 | environment [post update] [] : String | -| InsecureLdapAuth.java:59:3:59:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:63:49:63:59 | environment | -| InsecureLdapAuth.java:62:3:62:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:63:49:63:59 | environment | -| InsecureLdapAuth.java:68:20:68:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:72:41:72:47 | ldapUrl : String | -| InsecureLdapAuth.java:68:20:68:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:77:49:77:59 | environment | -| InsecureLdapAuth.java:72:3:72:13 | environment [post update] [] : String | InsecureLdapAuth.java:77:49:77:59 | environment | -| InsecureLdapAuth.java:72:41:72:47 | ldapUrl : String | InsecureLdapAuth.java:72:3:72:13 | environment [post update] [] : String | -| InsecureLdapAuth.java:88:3:88:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:91:49:91:59 | environment | -| InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:100:41:100:47 | ldapUrl : String | -| InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:105:59:105:69 | environment | -| InsecureLdapAuth.java:100:3:100:13 | environment [post update] [] : String | InsecureLdapAuth.java:105:59:105:69 | environment | -| InsecureLdapAuth.java:100:41:100:47 | ldapUrl : String | InsecureLdapAuth.java:100:3:100:13 | environment [post update] [] : String | -| InsecureLdapAuth.java:102:3:102:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:105:59:105:69 | environment | -| InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:115:47:115:53 | ldapUrl : String | -| InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:120:49:120:59 | environment | -| InsecureLdapAuth.java:115:3:115:13 | environment [post update] [] : String | InsecureLdapAuth.java:120:49:120:59 | environment | -| InsecureLdapAuth.java:115:47:115:53 | ldapUrl : String | InsecureLdapAuth.java:115:3:115:13 | environment [post update] [] : String | -| InsecureLdapAuth.java:117:3:117:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:120:49:120:59 | environment | -| InsecureLdapAuth.java:124:3:124:5 | env [post update] : Hashtable | InsecureLdapAuth.java:137:10:137:20 | environment [post update] : Hashtable | -| InsecureLdapAuth.java:128:3:128:5 | env [post update] : Hashtable | InsecureLdapAuth.java:141:16:141:26 | environment [post update] : Hashtable | -| InsecureLdapAuth.java:128:3:128:5 | env [post update] : Hashtable | InsecureLdapAuth.java:152:16:152:26 | environment [post update] : Hashtable | -| InsecureLdapAuth.java:135:20:135:39 | ... + ... : String | InsecureLdapAuth.java:140:41:140:47 | ldapUrl : String | -| InsecureLdapAuth.java:135:20:135:39 | ... + ... : String | InsecureLdapAuth.java:142:50:142:60 | environment | -| InsecureLdapAuth.java:137:10:137:20 | environment [post update] : Hashtable | InsecureLdapAuth.java:142:50:142:60 | environment | -| InsecureLdapAuth.java:140:3:140:13 | environment [post update] [] : String | InsecureLdapAuth.java:142:50:142:60 | environment | -| InsecureLdapAuth.java:140:41:140:47 | ldapUrl : String | InsecureLdapAuth.java:140:3:140:13 | environment [post update] [] : String | -| InsecureLdapAuth.java:141:16:141:26 | environment [post update] : Hashtable | InsecureLdapAuth.java:142:50:142:60 | environment | -| InsecureLdapAuth.java:147:20:147:39 | ... + ... : String | InsecureLdapAuth.java:151:41:151:47 | ldapUrl : String | -| InsecureLdapAuth.java:147:20:147:39 | ... + ... : String | InsecureLdapAuth.java:153:50:153:60 | environment | -| InsecureLdapAuth.java:151:3:151:13 | environment [post update] [] : String | InsecureLdapAuth.java:153:50:153:60 | environment | -| InsecureLdapAuth.java:151:41:151:47 | ldapUrl : String | InsecureLdapAuth.java:151:3:151:13 | environment [post update] [] : String | -| InsecureLdapAuth.java:152:16:152:26 | environment [post update] : Hashtable | InsecureLdapAuth.java:153:50:153:60 | environment | -nodes -| InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | -| InsecureLdapAuth.java:15:3:15:13 | environment [post update] [] : String | semmle.label | environment [post update] [] : String | -| InsecureLdapAuth.java:15:41:15:47 | ldapUrl : String | semmle.label | ldapUrl : String | -| InsecureLdapAuth.java:17:3:17:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable | -| InsecureLdapAuth.java:20:49:20:59 | environment | semmle.label | environment | -| InsecureLdapAuth.java:20:49:20:59 | environment | semmle.label | environment | -| InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | semmle.label | ... + ... : String | -| InsecureLdapAuth.java:29:3:29:13 | environment [post update] [] : String | semmle.label | environment [post update] [] : String | -| InsecureLdapAuth.java:29:41:29:47 | ldapUrl : String | semmle.label | ldapUrl : String | -| InsecureLdapAuth.java:31:3:31:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable | -| InsecureLdapAuth.java:34:49:34:59 | environment | semmle.label | environment | -| InsecureLdapAuth.java:34:49:34:59 | environment | semmle.label | environment | -| InsecureLdapAuth.java:45:3:45:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable | -| InsecureLdapAuth.java:48:49:48:59 | environment | semmle.label | environment | -| InsecureLdapAuth.java:53:20:53:50 | "ldap://ad.your-server.com:636" : String | semmle.label | "ldap://ad.your-server.com:636" : String | -| InsecureLdapAuth.java:57:3:57:13 | environment [post update] [] : String | semmle.label | environment [post update] [] : String | -| InsecureLdapAuth.java:57:41:57:47 | ldapUrl : String | semmle.label | ldapUrl : String | -| InsecureLdapAuth.java:59:3:59:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable | -| InsecureLdapAuth.java:62:3:62:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable | -| InsecureLdapAuth.java:63:49:63:59 | environment | semmle.label | environment | -| InsecureLdapAuth.java:63:49:63:59 | environment | semmle.label | environment | -| InsecureLdapAuth.java:63:49:63:59 | environment | semmle.label | environment | -| InsecureLdapAuth.java:68:20:68:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | -| InsecureLdapAuth.java:72:3:72:13 | environment [post update] [] : String | semmle.label | environment [post update] [] : String | -| InsecureLdapAuth.java:72:41:72:47 | ldapUrl : String | semmle.label | ldapUrl : String | -| InsecureLdapAuth.java:77:49:77:59 | environment | semmle.label | environment | -| InsecureLdapAuth.java:88:3:88:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable | -| InsecureLdapAuth.java:91:49:91:59 | environment | semmle.label | environment | -| InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | -| InsecureLdapAuth.java:100:3:100:13 | environment [post update] [] : String | semmle.label | environment [post update] [] : String | -| InsecureLdapAuth.java:100:41:100:47 | ldapUrl : String | semmle.label | ldapUrl : String | -| InsecureLdapAuth.java:102:3:102:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable | -| InsecureLdapAuth.java:105:59:105:69 | environment | semmle.label | environment | -| InsecureLdapAuth.java:105:59:105:69 | environment | semmle.label | environment | -| InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String | -| InsecureLdapAuth.java:115:3:115:13 | environment [post update] [] : String | semmle.label | environment [post update] [] : String | -| InsecureLdapAuth.java:115:47:115:53 | ldapUrl : String | semmle.label | ldapUrl : String | -| InsecureLdapAuth.java:117:3:117:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable | -| InsecureLdapAuth.java:120:49:120:59 | environment | semmle.label | environment | -| InsecureLdapAuth.java:120:49:120:59 | environment | semmle.label | environment | -| InsecureLdapAuth.java:124:3:124:5 | env [post update] : Hashtable | semmle.label | env [post update] : Hashtable | -| InsecureLdapAuth.java:128:3:128:5 | env [post update] : Hashtable | semmle.label | env [post update] : Hashtable | -| InsecureLdapAuth.java:135:20:135:39 | ... + ... : String | semmle.label | ... + ... : String | -| InsecureLdapAuth.java:137:10:137:20 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable | -| InsecureLdapAuth.java:140:3:140:13 | environment [post update] [] : String | semmle.label | environment [post update] [] : String | -| InsecureLdapAuth.java:140:41:140:47 | ldapUrl : String | semmle.label | ldapUrl : String | -| InsecureLdapAuth.java:141:16:141:26 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable | -| InsecureLdapAuth.java:142:50:142:60 | environment | semmle.label | environment | -| InsecureLdapAuth.java:142:50:142:60 | environment | semmle.label | environment | -| InsecureLdapAuth.java:142:50:142:60 | environment | semmle.label | environment | -| InsecureLdapAuth.java:147:20:147:39 | ... + ... : String | semmle.label | ... + ... : String | -| InsecureLdapAuth.java:151:3:151:13 | environment [post update] [] : String | semmle.label | environment [post update] [] : String | -| InsecureLdapAuth.java:151:41:151:47 | ldapUrl : String | semmle.label | ldapUrl : String | -| InsecureLdapAuth.java:152:16:152:26 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable | -| InsecureLdapAuth.java:153:50:153:60 | environment | semmle.label | environment | -| InsecureLdapAuth.java:153:50:153:60 | environment | semmle.label | environment | -subpaths -#select -| InsecureLdapAuth.java:20:49:20:59 | environment | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:20:49:20:59 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" | LDAP connection string | -| InsecureLdapAuth.java:34:49:34:59 | environment | InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:34:49:34:59 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:25:20:25:39 | ... + ... | LDAP connection string | -| InsecureLdapAuth.java:105:59:105:69 | environment | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:105:59:105:69 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" | LDAP connection string | -| InsecureLdapAuth.java:120:49:120:59 | environment | InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:120:49:120:59 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" | LDAP connection string | -| InsecureLdapAuth.java:153:50:153:60 | environment | InsecureLdapAuth.java:147:20:147:39 | ... + ... : String | InsecureLdapAuth.java:153:50:153:60 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:147:20:147:39 | ... + ... | LDAP connection string | diff --git a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.qlref b/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.qlref deleted file mode 100644 index c2baa984177..00000000000 --- a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.qlref +++ /dev/null @@ -1 +0,0 @@ -experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql diff --git a/java/ql/test/ext/TestModels/Test.java b/java/ql/test/ext/TestModels/Test.java index a64f4ec71c0..0f52da636e6 100644 --- a/java/ql/test/ext/TestModels/Test.java +++ b/java/ql/test/ext/TestModels/Test.java @@ -1,14 +1,23 @@ -import java.io.IOException; -import java.io.File; +package generatedtest; // for java.util.ResourceBundle.getString test + +import java.awt.*; +import java.io.*; import java.math.BigDecimal; +import java.net.URL; +import java.nio.file.Path; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.util.EventObject; +import java.util.ResourceBundle; import java.util.StringJoiner; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; import java.util.function.Supplier; +import java.util.logging.Logger; +import java.util.regex.Pattern; import java.util.stream.Collectors; public class Test { @@ -17,6 +26,8 @@ public class Test { Object source() { return null; } + Object newWithMapValueDefault(Object element) { return null; } // for java.util.ResourceBundle.getString test + public void test() throws Exception { // top 100 JDK APIs tests @@ -81,5 +92,107 @@ public class Test { StringJoiner sj2 = (StringJoiner)source(); sink(sj2.add("test")); // $hasTaintFlow } + + // top 300-500 JDK APIs tests + { + + // java.awt + Container container = new Container(); + sink(container.add((Component)source())); // $hasValueFlow + + // java.io + File f1 = (File)source(); + sink(f1.getParentFile()); // $hasTaintFlow + + File f2 = (File)source(); + sink(f2.getPath()); // $hasTaintFlow + + File f3 = (File)source(); + sink(f3.listFiles()); // $hasTaintFlow + + StringWriter sw = (StringWriter)source(); + sink(sw.toString()); // $hasTaintFlow + + Exception e = new UncheckedIOException((IOException)source()); + sink((Throwable)e.getCause()); // $hasValueFlow + + // java.net + URL url = (URL)source(); + sink(url.toURI()); // $hasTaintFlow + + // java.nio.file + Path p = (Path)source(); + sink(p.getFileName()); // $hasTaintFlow + + // java.util.concurrent.atomic + AtomicReference ar = new AtomicReference(); + ar.set(source()); + sink(ar.get()); // $hasValueFlow + + // java.util.concurrent + // `ThreadPoolExecutor` implements the `java.util.concurrent.ExecutorService` interface + ThreadPoolExecutor tpe = new ThreadPoolExecutor(0, 0, 0, null, null); + sink(tpe.submit((Runnable)source())); // $hasTaintFlow + + CompletionStage cs = (CompletionStage)source(); + sink(cs.toCompletableFuture()); // $hasTaintFlow + + CompletableFuture cf1 = new CompletableFuture(); + cf1.complete(source()); + sink(cf1.get()); // $hasValueFlow + sink(cf1.join()); // $hasValueFlow + + CompletableFuture cf2 = CompletableFuture.completedFuture(source()); + sink(cf2.get()); // $hasValueFlow + sink(cf2.join()); // $hasValueFlow + + // java.util.logging + Logger logger = Logger.getLogger((String)source()); + sink(logger.getName()); // $hasValueFlow + + // java.util.regex + Pattern pattern = Pattern.compile((String)source()); + sink(pattern); // $hasTaintFlow + + // java.util + EventObject eventObj = new EventObject(source()); + sink(eventObj.getSource()); // $hasValueFlow + + // "java.util;ResourceBundle;true;getString;(String);;Argument[-1].MapValue;ReturnValue;value;manual" + String out = null; + ResourceBundle in = (ResourceBundle)newWithMapValueDefault(source()); + out = in.getString(null); + sink(out); // $ hasValueFlow + + // java.lang + AssertionError assertErr = new AssertionError(source()); + sink((String)assertErr.getMessage()); // $hasValueFlow + + sink(Test.class.cast(source())); // $hasValueFlow + + Exception excep1 = new Exception((String)source(), (Throwable)source()); + sink((String)excep1.getMessage()); // $hasValueFlow + sink((Throwable)excep1.getCause()); // $hasValueFlow + + Exception excep2 = new NullPointerException((String)source()); + sink((String)excep2.getMessage()); // $hasValueFlow + + StringBuilder sb = (StringBuilder)source(); + sink(sb.delete(0, 1)); // $hasValueFlow + + Thread thread1 = new Thread((Runnable)source()); + sink(thread1); // $hasTaintFlow + + Thread thread2 = new Thread((String)source()); + sink(thread2.getName()); // $hasValueFlow + + ThreadLocal threadloc = new ThreadLocal(); + threadloc.set(source()); + sink(threadloc.get()); // $hasValueFlow + + Throwable th = new Throwable((String)source()); + sink((String)th.getLocalizedMessage()); // $hasValueFlow + sink(th.toString()); // $hasTaintFlow + } } } diff --git a/java/ql/test/ext/TestModels/test.ext.yml b/java/ql/test/ext/TestModels/test.ext.yml new file mode 100644 index 00000000000..4fff7d575a3 --- /dev/null +++ b/java/ql/test/ext/TestModels/test.ext.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["generatedtest", "Test", False, "newWithMapValueDefault", "(Object)", "", "Argument[0]", "ReturnValue.MapValue", "value", "manual"] diff --git a/java/ql/test/ext/TopJdkApis/TopJdkApis.qll b/java/ql/test/ext/TopJdkApis/TopJdkApis.qll index 9bd5e1f9623..b0a8902b12b 100644 --- a/java/ql/test/ext/TopJdkApis/TopJdkApis.qll +++ b/java/ql/test/ext/TopJdkApis/TopJdkApis.qll @@ -111,7 +111,170 @@ predicate topJdkApiName(string apiName) { "java.util.Collection#iterator()", "java.util.Map#computeIfAbsent(Object,Function)", "java.text.SimpleDateFormat#SimpleDateFormat(String)", "java.util.StringJoiner#add(CharSequence)", "java.lang.Long#longValue()", - "java.util.stream.Collectors#joining(CharSequence)" + "java.util.stream.Collectors#joining(CharSequence)", + // top 300 JDK APIs + "java.lang.Math#max(int,int)", "java.util.Map#of(Object,Object)", + "java.lang.Long#valueOf(long)", "java.util.Random#nextInt(int)", + "java.lang.Long#valueOf(String)", "java.util.concurrent.CountDownLatch#await(long,TimeUnit)", + "java.util.Properties#getProperty(String)", "java.util.Optional#isEmpty()", + "java.util.concurrent.CompletableFuture#get()", "java.util.Objects#isNull(Object)", + "java.lang.StringBuilder#append(long)", "java.awt.Container#add(Component,Object)", + "java.math.BigDecimal#add(BigDecimal)", "java.sql.PreparedStatement#executeQuery()", + "java.lang.StringBuilder#StringBuilder(int)", "java.util.Map#forEach(BiConsumer)", + "java.math.BigDecimal#BigDecimal(int)", "java.util.Collections#unmodifiableList(List)", + "java.util.Properties#put(Object,Object)", "java.sql.Timestamp#Timestamp(long)", + "java.util.List#equals(Object)", "java.lang.String#indexOf(int)", + "java.lang.Long#toString(long)", "java.lang.Integer#Integer(int)", + "java.util.concurrent.atomic.AtomicBoolean#get()", + "java.lang.System#setProperty(String,String)", "java.util.concurrent.Future#get()", + "java.lang.Thread#start()", "java.util.Set#of(Object)", "java.util.Calendar#set(int,int)", + "java.time.Duration#ofSeconds(long)", "java.lang.System#arraycopy(Object,int,Object,int,int)", + "java.net.URI#toString()", "java.util.concurrent.atomic.AtomicInteger#incrementAndGet()", + "java.util.Set#remove(Object)", "java.lang.Boolean#parseBoolean(String)", + "java.util.Calendar#getTime()", "java.nio.charset.Charset#name()", + "java.lang.ThreadLocal#get()", "java.lang.Class#getCanonicalName()", + "java.util.List#remove(Object)", "java.lang.Throwable#toString()", + "java.util.stream.Stream#toList()", "java.io.ByteArrayOutputStream#toByteArray()", + "java.util.concurrent.atomic.AtomicLong#get()", + "java.lang.NullPointerException#NullPointerException(String)", "java.util.List#of()", + "java.util.Calendar#getInstance()", "java.util.Calendar#get(int)", + "java.util.Optional#orElseThrow()", "java.lang.System#lineSeparator()", + "java.lang.Boolean#booleanValue()", "java.util.logging.Logger#isLoggable(Level)", + "java.lang.Enum#hashCode()", "java.util.List#hashCode()", + "java.lang.reflect.Method#invoke(Object,Object[])", "java.lang.String#String(byte[],Charset)", + "java.util.Comparator#comparing(Function)", "java.util.Arrays#toString(Object[])", + "java.time.LocalDate#now()", "java.util.function.Function#identity()", + "java.io.OutputStream#write(byte[])", "java.lang.Integer#equals(Object)", + "java.io.BufferedReader#BufferedReader(Reader)", "java.io.DataInput#readInt()", + "java.io.BufferedReader#readLine()", "java.util.Map#entry(Object,Object)", + "java.lang.Runnable#run()", "java.util.ResourceBundle#getString(String)", + "java.util.Iterator#remove()", "java.lang.String#join(CharSequence,Iterable)", + "java.util.concurrent.atomic.AtomicBoolean#set(boolean)", "java.time.LocalDateTime#now()", + "java.sql.ResultSet#getLong(String)", "java.text.DateFormat#parse(String)", + "java.lang.String#toString()", "java.lang.Integer#valueOf(String)", + "java.util.regex.Matcher#find()", "java.io.DataOutput#writeInt(int)", + "java.util.HashMap#HashMap(int)", "java.util.stream.Stream#sorted(Comparator)", + "java.lang.String#toCharArray()", + "java.util.concurrent.atomic.AtomicInteger#AtomicInteger(int)", + "java.lang.String#String(byte[])", "java.lang.reflect.Method#getName()", + "java.sql.ResultSet#getString(int)", "java.net.URI#create(String)", + "java.lang.Enum#ordinal()", "java.util.concurrent.atomic.AtomicReference#set(Object)", + "java.util.concurrent.CompletableFuture#join()", + "java.io.FileInputStream#FileInputStream(File)", "java.io.File#delete()", + "java.util.concurrent.TimeUnit#toMillis(long)", "java.util.List#of(Object,Object,Object)", + "java.lang.String#compareTo(String)", "java.util.stream.IntStream#range(int,int)", + "java.math.BigInteger#valueOf(long)", "java.util.List#remove(int)", + "java.util.HashMap#HashMap(Map)", "java.util.function.BiConsumer#accept(Object,Object)", + // top 400 JDK APIs + "java.util.HashMap#containsKey(Object)", "java.util.Collection#contains(Object)", + "java.lang.Double#parseDouble(String)", "java.lang.Thread#interrupt()", + "java.awt.Container#add(Component)", "java.time.chrono.ChronoZonedDateTime#toInstant()", + "java.util.List#subList(int,int)", "java.util.concurrent.ConcurrentHashMap#get(Object)", + "java.lang.System#getenv(String)", "java.time.Duration#ofMillis(long)", + "java.lang.Integer#toString()", "java.lang.reflect.Constructor#newInstance(Object[])", + "java.util.Hashtable#get(Object)", "java.lang.Class#toString()", + "java.util.Vector#add(Object)", "java.io.StringReader#StringReader(String)", + "java.io.File#getPath()", "java.lang.System#identityHashCode(Object)", + "java.util.stream.Stream#count()", "java.util.concurrent.CompletableFuture#complete(Object)", + "java.nio.file.Files#exists(Path,LinkOption[])", "java.util.List#set(int,Object)", + "java.util.concurrent.atomic.AtomicLong#AtomicLong(long)", + "java.util.Optional#orElseGet(Supplier)", "java.lang.Class#forName(String)", + "java.lang.String#replace(char,char)", "java.util.Enumeration#nextElement()", + "java.lang.Class#getMethod(String,Class[])", "java.nio.file.Path#toAbsolutePath()", + "java.util.Enumeration#hasMoreElements()", "java.lang.Class#cast(Object)", + "java.util.concurrent.atomic.AtomicBoolean#AtomicBoolean(boolean)", + "java.math.BigDecimal#doubleValue()", "java.util.UUID#fromString(String)", + "java.lang.System#exit(int)", "java.util.List#add(int,Object)", + "java.lang.Boolean#valueOf(boolean)", "java.sql.Timestamp#getTime()", + "java.nio.Buffer#remaining()", "java.net.URL#URL(String)", "java.net.URI#URI(String)", + "java.util.Objects#hashCode(Object)", "java.util.Set#clear()", "java.io.File#isDirectory()", + "java.time.Duration#toMillis()", "java.nio.ByteBuffer#allocate(int)", + "java.math.BigDecimal#toString()", "java.lang.Class#getResourceAsStream(String)", + "java.util.logging.Logger#getLogger(String)", "java.lang.String#toLowerCase(Locale)", + "java.util.concurrent.CompletableFuture#completeExceptionally(Throwable)", + "java.util.stream.Stream#findAny()", + "java.util.concurrent.CompletableFuture#completedFuture(Object)", + "java.util.stream.Stream#of(Object)", "java.util.Map#of(Object,Object,Object,Object)", + "java.util.Collections#sort(List,Comparator)", "java.lang.Thread#Thread(Runnable)", + "java.lang.String#lastIndexOf(int)", + "java.io.UncheckedIOException#UncheckedIOException(IOException)", + "java.util.LinkedHashSet#LinkedHashSet(Collection)", + "java.sql.PreparedStatement#executeUpdate()", "java.time.ZoneId#of(String)", + "java.util.concurrent.atomic.AtomicLong#addAndGet(long)", "java.nio.ByteBuffer#wrap(byte[])", + "java.util.List#indexOf(Object)", "java.util.Collections#unmodifiableMap(Map)", + "java.lang.Long#Long(long)", "java.util.StringTokenizer#nextToken()", + "java.lang.String#join(CharSequence,CharSequence[])", "java.io.StringWriter#toString()", + "java.lang.Integer#toHexString(int)", "java.lang.Long#intValue()", + "java.text.MessageFormat#format(String,Object[])", + "java.lang.Exception#Exception(String,Throwable)", + "java.util.stream.Stream#toArray(IntFunction)", "java.util.List#sort(Comparator)", + "java.util.LinkedHashMap#get(Object)", "java.sql.PreparedStatement#setLong(int,long)", + "java.lang.Iterable#iterator()", "java.math.BigInteger#or(BigInteger)", + "java.time.LocalDateTime#of(int,int,int,int,int,int)", "java.time.Instant#toEpochMilli()", + "java.math.BigDecimal#setScale(int,RoundingMode)", "java.lang.Class#isInstance(Object)", + "java.util.regex.Pattern#compile(String)", "java.util.Calendar#getTimeInMillis()", + "java.lang.Class#getResource(String)", "java.util.concurrent.Executor#execute(Runnable)", + "java.util.concurrent.locks.Lock#unlock()", "java.lang.AssertionError#AssertionError(Object)", + "java.util.ArrayList#addAll(Collection)", "java.io.File#mkdirs()", + "java.time.Duration#ofMinutes(long)", "java.time.format.DateTimeFormatter#ofPattern(String)", + "java.lang.Throwable#getLocalizedMessage()", "java.lang.StringBuilder#delete(int,int)", + "java.util.Vector#size()", "java.lang.String#String(String)", "java.util.ArrayList#isEmpty()", + "java.util.Collection#removeIf(Predicate)", + // top 500 JDK APIs + "java.util.HashSet#HashSet(int)", "java.util.Set#of(Object,Object)", + "java.util.Collections#unmodifiableSet(Set)", "java.sql.Connection#createStatement()", + "java.math.BigDecimal#subtract(BigDecimal)", "java.util.Date#from(Instant)", + "java.lang.StringBuffer#append(char)", "java.util.Locale#forLanguageTag(String)", + "java.io.DataInput#readLong()", "java.util.Collections#sort(List)", + "java.io.DataOutput#writeLong(long)", "java.util.function.BiFunction#apply(Object,Object)", + "java.lang.String#lastIndexOf(String)", "java.util.Optional#filter(Predicate)", + "java.lang.StringBuffer#append(Object)", "java.io.File#getParentFile()", + "java.util.stream.Stream#allMatch(Predicate)", "java.sql.ResultSet#getTimestamp(String)", + "java.util.Calendar#setTime(Date)", + "java.util.concurrent.CompletionStage#toCompletableFuture()", + "java.util.concurrent.locks.Lock#lock()", "java.lang.reflect.Field#get(Object)", + "java.io.InputStream#close()", "java.math.BigInteger#BigInteger(String)", + "java.lang.Class#getDeclaredField(String)", + "java.io.InputStreamReader#InputStreamReader(InputStream)", "java.lang.Runtime#getRuntime()", + "java.lang.Class#getDeclaredConstructor(Class[])", + "java.lang.AbstractStringBuilder#setLength(int)", "java.nio.Buffer#position()", + "java.nio.file.Path#getFileName()", "java.util.List#toArray()", + "java.lang.CharSequence#length()", "java.util.stream.Stream#distinct()", + "java.net.URL#toURI()", "java.util.Queue#poll()", "java.lang.Thread#getContextClassLoader()", + "java.lang.String#valueOf(boolean)", "java.util.Calendar#add(int,int)", + "java.util.HashMap#entrySet()", "java.util.stream.IntStream#mapToObj(IntFunction)", + "java.util.concurrent.atomic.AtomicLong#incrementAndGet()", + "java.util.concurrent.ExecutorService#shutdown()", + "java.util.concurrent.ExecutorService#submit(Runnable)", "java.math.BigDecimal#intValue()", + "java.math.BigDecimal#toBigInteger()", "java.util.LinkedList#add(Object)", + "java.lang.AbstractStringBuilder#charAt(int)", "java.lang.Thread#getName()", + "java.lang.Math#max(long,long)", "java.util.HashMap#size()", + "java.time.LocalDate#plusDays(long)", "java.nio.ByteBuffer#array()", + "java.lang.StringBuilder#append(CharSequence)", "java.util.Vector#addElement(Object)", + "java.lang.ClassLoader#getResource(String)", "java.awt.Insets#Insets(int,int,int,int)", + "java.util.TimeZone#getTimeZone(String)", "java.time.ZoneId#systemDefault()", + "java.lang.Number#doubleValue()", "java.util.stream.Stream#reduce(Object,BinaryOperator)", + "java.lang.CharSequence#toString()", "java.time.Instant#parse(CharSequence)", + "java.text.Format#format(Object)", "java.io.File#toURI()", "java.sql.ResultSet#getInt(int)", + "java.lang.Number#longValue()", "java.lang.Double#doubleToLongBits(double)", + "java.lang.Math#min(long,long)", "java.lang.Double#valueOf(double)", + "java.lang.invoke.MethodHandles#lookup()", "java.util.concurrent.CompletableFuture#isDone()", + "java.time.LocalDate#parse(CharSequence)", "java.lang.StringBuilder#append(boolean)", + "java.util.concurrent.CountDownLatch#await()", + "java.util.concurrent.ConcurrentHashMap#put(Object,Object)", + "java.util.stream.Stream#mapToInt(ToIntFunction)", + "java.math.BigDecimal#multiply(BigDecimal)", "java.util.stream.Stream#concat(Stream,Stream)", + "java.time.Instant#ofEpochMilli(long)", "java.nio.file.Path#getParent()", + "java.util.stream.Stream#sorted()", + "java.util.concurrent.atomic.AtomicBoolean#compareAndSet(boolean,boolean)", + "java.util.UUID#equals(Object)", "java.io.OutputStream#flush()", + "java.time.format.DateTimeFormatter#format(TemporalAccessor)", "java.io.Closeable#close()", + "java.util.EventObject#getSource()", "java.io.File#File(String,String)", + "java.lang.Number#intValue()", "java.io.File#length()", + "java.lang.AbstractStringBuilder#setCharAt(int,char)", "java.util.Set#removeAll(Collection)", + "java.io.File#listFiles()", "java.lang.ClassLoader#getResourceAsStream(String)", + "java.util.Date#toInstant()", "java.util.Queue#add(Object)", "java.io.File#isFile()", + "java.sql.Statement#close()", "java.io.DataOutput#writeBoolean(boolean)" ] } @@ -145,7 +308,13 @@ class TopJdkApi extends SummarizedCallableBase { * Note: the following top JDK APIs are not modeled with MaD: * `java.lang.String#valueOf(Object)`: a complex case; an alias for `Object.toString`, except the dispatch is hidden * `java.lang.System#getProperty(String)`: needs to be modeled by regular CodeQL matching the get and set keys to reduce FPs + * `java.lang.System#setProperty(String,String)`: needs to be modeled by regular CodeQL matching the get and set keys to reduce FPs * `java.lang.Throwable#printStackTrace()`: should probably not be a general step, but there might be specialised queries that care + * `java.text.Format#format(Object)`: similar issue as `Object.toString`; depends on the object being passed as the argument + * `java.text.MessageFormat#format(String,Object[])`: similar issue as `Object.toString`; depends on the object being passed as the argument + * `java.util.Comparator#comparing(Function)`: lambda flow + * `java.util.function.BiConsumer#accept(Object,Object)`: specialized lambda flow + * `java.util.function.BiFunction#apply(Object,Object)`: specialized lambda flow * `java.util.function.Consumer#accept(Object)`: specialized lambda flow * `java.util.function.Function#apply(Object)`: specialized lambda flow * `java.util.function.Supplier#get()`: lambda flow diff --git a/java/ql/test/ext/TopJdkApis/TopJdkApisTest.expected b/java/ql/test/ext/TopJdkApis/TopJdkApisTest.expected index 3ef93396b3b..2e0ace91209 100644 --- a/java/ql/test/ext/TopJdkApis/TopJdkApisTest.expected +++ b/java/ql/test/ext/TopJdkApis/TopJdkApisTest.expected @@ -1,6 +1,12 @@ | java.lang.String#valueOf(Object) | no manual model | | java.lang.System#getProperty(String) | no manual model | +| java.lang.System#setProperty(String,String) | no manual model | | java.lang.Throwable#printStackTrace() | no manual model | +| java.text.Format#format(Object) | no manual model | +| java.text.MessageFormat#format(String,Object[]) | no manual model | +| java.util.Comparator#comparing(Function) | no manual model | +| java.util.function.BiConsumer#accept(Object,Object) | no manual model | +| java.util.function.BiFunction#apply(Object,Object) | no manual model | | java.util.function.Consumer#accept(Object) | no manual model | | java.util.function.Function#apply(Object) | no manual model | | java.util.function.Supplier#get() | no manual model | diff --git a/java/ql/test/ext/TopJdkApis/TopJdkApisTest.java b/java/ql/test/ext/TopJdkApis/TopJdkApisTest.java index 49a7396ad64..90797502198 100644 --- a/java/ql/test/ext/TopJdkApis/TopJdkApisTest.java +++ b/java/ql/test/ext/TopJdkApis/TopJdkApisTest.java @@ -1,25 +1,43 @@ +import java.awt.Container; +import java.io.BufferedReader; import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.UncheckedIOException; +import java.lang.AssertionError; import java.lang.IllegalStateException; import java.lang.IndexOutOfBoundsException; +import java.lang.NullPointerException; import java.lang.Math; +import java.lang.Runtime; import java.lang.System; import java.math.BigDecimal; +import java.nio.file.Files; import java.nio.file.Paths; import java.sql.ResultSet; import java.text.DateFormat; +import java.text.MessageFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; import java.util.Map; import java.util.Objects; import java.util.StringJoiner; +import java.util.StringTokenizer; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; +import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; diff --git a/java/ql/test/library-tests/dataflow/external-models/validatemodels.expected b/java/ql/test/library-tests/dataflow/external-models/validatemodels.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/dataflow/external-models/validatemodels.ql b/java/ql/test/library-tests/dataflow/external-models/validatemodels.ql new file mode 100644 index 00000000000..84312d3d4e4 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/external-models/validatemodels.ql @@ -0,0 +1,15 @@ +import java +import semmle.code.java.dataflow.ExternalFlow +import semmle.code.java.dataflow.internal.AccessPathSyntax +import ModelValidation + +private predicate getRelevantAccessPath(string path) { + summaryModel(_, _, _, _, _, _, path, _, _, _) or + summaryModel(_, _, _, _, _, _, _, path, _, _) or + sinkModel(_, _, _, _, _, _, path, _, _) or + sourceModel(_, _, _, _, _, _, path, _, _) +} + +private class AccessPathsExternal extends AccessPath::Range { + AccessPathsExternal() { getRelevantAccessPath(this) } +} diff --git a/java/ql/test/library-tests/dataflow/inoutbarriers/test.ql b/java/ql/test/library-tests/dataflow/inoutbarriers/test.ql index a582f5b2456..7635dae3820 100644 --- a/java/ql/test/library-tests/dataflow/inoutbarriers/test.ql +++ b/java/ql/test/library-tests/dataflow/inoutbarriers/test.ql @@ -47,13 +47,13 @@ module Conf4 implements ConfigSig { } predicate flow(Node src, Node sink, string s) { - Make::hasFlow(src, sink) and s = "nobarrier" + Global::flow(src, sink) and s = "nobarrier" or - Make::hasFlow(src, sink) and s = "srcbarrier" + Global::flow(src, sink) and s = "srcbarrier" or - Make::hasFlow(src, sink) and s = "sinkbarrier" + Global::flow(src, sink) and s = "sinkbarrier" or - Make::hasFlow(src, sink) and s = "both" + Global::flow(src, sink) and s = "both" } from Node src, Node sink, string s diff --git a/java/ql/test/library-tests/dataflow/partial/test.ql b/java/ql/test/library-tests/dataflow/partial/test.ql index 399a876e9a9..4b2e5e71ff4 100644 --- a/java/ql/test/library-tests/dataflow/partial/test.ql +++ b/java/ql/test/library-tests/dataflow/partial/test.ql @@ -10,10 +10,10 @@ module Config implements ConfigSig { int explorationLimit() { result = 10 } -module PartialFlow = Make::FlowExploration; +module PartialFlow = Global::FlowExploration; import PartialFlow::PartialPathGraph from PartialFlow::PartialPathNode n, int dist -where PartialFlow::hasPartialFlow(_, n, dist) +where PartialFlow::partialFlow(_, n, dist) select dist, n diff --git a/java/ql/test/library-tests/dataflow/partial/testRev.ql b/java/ql/test/library-tests/dataflow/partial/testRev.ql index c869cb4f915..f3f71d69e3b 100644 --- a/java/ql/test/library-tests/dataflow/partial/testRev.ql +++ b/java/ql/test/library-tests/dataflow/partial/testRev.ql @@ -10,10 +10,10 @@ module Config implements ConfigSig { int explorationLimit() { result = 10 } -module PartialFlow = Make::FlowExploration; +module PartialFlow = Global::FlowExploration; import PartialFlow::PartialPathGraph from PartialFlow::PartialPathNode n, int dist -where PartialFlow::hasPartialFlowRev(n, _, dist) +where PartialFlow::partialFlowRev(n, _, dist) select dist, n diff --git a/java/ql/test/library-tests/dataflow/range-analysis/RangeAnalysis.expected b/java/ql/test/library-tests/dataflow/range-analysis/RangeAnalysis.expected index d66a35bf397..9fbe076dfe9 100644 --- a/java/ql/test/library-tests/dataflow/range-analysis/RangeAnalysis.expected +++ b/java/ql/test/library-tests/dataflow/range-analysis/RangeAnalysis.expected @@ -33,9 +33,17 @@ | A.java:9:16:9:16 | x | SSA init(x) | 0 | upper | NoReason | | A.java:9:16:9:16 | x | SSA init(y) | -2 | lower | ... == ... | | A.java:9:16:9:16 | x | SSA init(y) | -2 | upper | ... == ... | -| A.java:9:16:9:20 | ... + ... | 0 | 300 | lower | ... > ... | -| A.java:9:16:9:20 | ... + ... | SSA init(x) | 1 | lower | NoReason | -| A.java:9:16:9:20 | ... + ... | SSA init(y) | -1 | lower | ... == ... | +| A.java:9:16:9:20 | ... + ... | 0 | 600 | lower | ... > ... | +| A.java:9:16:9:20 | ... + ... | 0 | 802 | upper | ... == ... | +| A.java:9:16:9:20 | ... + ... | 0 | 802 | upper | ... > ... | +| A.java:9:16:9:20 | ... + ... | SSA init(x) | 301 | lower | ... == ... | +| A.java:9:16:9:20 | ... + ... | SSA init(x) | 301 | lower | NoReason | +| A.java:9:16:9:20 | ... + ... | SSA init(x) | 402 | upper | ... == ... | +| A.java:9:16:9:20 | ... + ... | SSA init(x) | 402 | upper | NoReason | +| A.java:9:16:9:20 | ... + ... | SSA init(y) | 299 | lower | ... == ... | +| A.java:9:16:9:20 | ... + ... | SSA init(y) | 299 | lower | NoReason | +| A.java:9:16:9:20 | ... + ... | SSA init(y) | 400 | upper | ... == ... | +| A.java:9:16:9:20 | ... + ... | SSA init(y) | 400 | upper | NoReason | | A.java:9:20:9:20 | y | 0 | 301 | lower | ... > ... | | A.java:9:20:9:20 | y | 0 | 402 | upper | ... == ... | | A.java:9:20:9:20 | y | SSA init(x) | 2 | lower | ... == ... | @@ -54,6 +62,7 @@ | A.java:13:19:13:19 | x | 0 | 400 | upper | ... > ... | | A.java:13:19:13:19 | x | SSA init(x) | 0 | lower | NoReason | | A.java:13:19:13:19 | x | SSA init(x) | 0 | upper | NoReason | +| A.java:13:19:13:23 | ... + ... | SSA init(y) | 400 | upper | NoReason | | A.java:13:23:13:23 | y | SSA init(y) | 0 | lower | NoReason | | A.java:13:23:13:23 | y | SSA init(y) | 0 | upper | NoReason | | A.java:15:13:15:13 | y | 0 | 399 | upper | ... != ... | @@ -69,9 +78,17 @@ | A.java:16:21:16:21 | x | SSA init(x) | 0 | upper | NoReason | | A.java:16:21:16:21 | x | SSA init(y) | 1 | lower | ... != ... | | A.java:16:21:16:21 | x | SSA init(y) | 1 | upper | ... != ... | -| A.java:16:21:16:25 | ... + ... | 0 | 303 | lower | ... > ... | -| A.java:16:21:16:25 | ... + ... | SSA init(x) | 1 | lower | NoReason | -| A.java:16:21:16:25 | ... + ... | SSA init(y) | 2 | lower | ... != ... | +| A.java:16:21:16:25 | ... + ... | 0 | 603 | lower | ... > ... | +| A.java:16:21:16:25 | ... + ... | 0 | 799 | upper | ... != ... | +| A.java:16:21:16:25 | ... + ... | 0 | 799 | upper | ... > ... | +| A.java:16:21:16:25 | ... + ... | SSA init(x) | 301 | lower | ... != ... | +| A.java:16:21:16:25 | ... + ... | SSA init(x) | 301 | lower | NoReason | +| A.java:16:21:16:25 | ... + ... | SSA init(x) | 399 | upper | ... != ... | +| A.java:16:21:16:25 | ... + ... | SSA init(x) | 399 | upper | NoReason | +| A.java:16:21:16:25 | ... + ... | SSA init(y) | 302 | lower | ... != ... | +| A.java:16:21:16:25 | ... + ... | SSA init(y) | 302 | lower | NoReason | +| A.java:16:21:16:25 | ... + ... | SSA init(y) | 400 | upper | ... != ... | +| A.java:16:21:16:25 | ... + ... | SSA init(y) | 400 | upper | NoReason | | A.java:16:25:16:25 | y | 0 | 301 | lower | ... > ... | | A.java:16:25:16:25 | y | 0 | 399 | upper | ... != ... | | A.java:16:25:16:25 | y | SSA init(x) | -1 | lower | ... != ... | @@ -153,14 +170,36 @@ | A.java:35:16:35:16 | x | SSA init(y) | 1 | upper | ... == ... | | A.java:35:16:35:16 | x | SSA init(z) | -1 | lower | ... == ... | | A.java:35:16:35:16 | x | SSA init(z) | -1 | upper | ... == ... | -| A.java:35:16:35:20 | ... + ... | 0 | 350 | lower | ... == ... | -| A.java:35:16:35:20 | ... + ... | SSA init(x) | 1 | lower | NoReason | -| A.java:35:16:35:20 | ... + ... | SSA init(y) | 2 | lower | ... == ... | -| A.java:35:16:35:20 | ... + ... | SSA init(z) | 0 | lower | ... == ... | -| A.java:35:16:35:24 | ... + ... | 0 | 351 | lower | ... == ... | -| A.java:35:16:35:24 | ... + ... | SSA init(x) | 2 | lower | NoReason | -| A.java:35:16:35:24 | ... + ... | SSA init(y) | 3 | lower | ... == ... | -| A.java:35:16:35:24 | ... + ... | SSA init(z) | 1 | lower | ... == ... | +| A.java:35:16:35:20 | ... + ... | 0 | 697 | lower | ... == ... | +| A.java:35:16:35:20 | ... + ... | 0 | 697 | upper | ... == ... | +| A.java:35:16:35:20 | ... + ... | SSA init(x) | 348 | lower | ... == ... | +| A.java:35:16:35:20 | ... + ... | SSA init(x) | 348 | lower | NoReason | +| A.java:35:16:35:20 | ... + ... | SSA init(x) | 348 | upper | ... == ... | +| A.java:35:16:35:20 | ... + ... | SSA init(x) | 348 | upper | NoReason | +| A.java:35:16:35:20 | ... + ... | SSA init(y) | 349 | lower | ... == ... | +| A.java:35:16:35:20 | ... + ... | SSA init(y) | 349 | lower | NoReason | +| A.java:35:16:35:20 | ... + ... | SSA init(y) | 349 | upper | ... == ... | +| A.java:35:16:35:20 | ... + ... | SSA init(y) | 349 | upper | NoReason | +| A.java:35:16:35:20 | ... + ... | SSA init(z) | 347 | lower | ... == ... | +| A.java:35:16:35:20 | ... + ... | SSA init(z) | 347 | upper | ... == ... | +| A.java:35:16:35:24 | ... + ... | 0 | 1047 | lower | ... == ... | +| A.java:35:16:35:24 | ... + ... | 0 | 1047 | upper | ... == ... | +| A.java:35:16:35:24 | ... + ... | SSA init(x) | 698 | lower | ... == ... | +| A.java:35:16:35:24 | ... + ... | SSA init(x) | 698 | lower | ... == ... | +| A.java:35:16:35:24 | ... + ... | SSA init(x) | 698 | lower | NoReason | +| A.java:35:16:35:24 | ... + ... | SSA init(x) | 698 | upper | ... == ... | +| A.java:35:16:35:24 | ... + ... | SSA init(x) | 698 | upper | ... == ... | +| A.java:35:16:35:24 | ... + ... | SSA init(x) | 698 | upper | NoReason | +| A.java:35:16:35:24 | ... + ... | SSA init(y) | 699 | lower | ... == ... | +| A.java:35:16:35:24 | ... + ... | SSA init(y) | 699 | lower | ... == ... | +| A.java:35:16:35:24 | ... + ... | SSA init(y) | 699 | lower | NoReason | +| A.java:35:16:35:24 | ... + ... | SSA init(y) | 699 | upper | ... == ... | +| A.java:35:16:35:24 | ... + ... | SSA init(y) | 699 | upper | ... == ... | +| A.java:35:16:35:24 | ... + ... | SSA init(y) | 699 | upper | NoReason | +| A.java:35:16:35:24 | ... + ... | SSA init(z) | 697 | lower | ... == ... | +| A.java:35:16:35:24 | ... + ... | SSA init(z) | 697 | lower | NoReason | +| A.java:35:16:35:24 | ... + ... | SSA init(z) | 697 | upper | ... == ... | +| A.java:35:16:35:24 | ... + ... | SSA init(z) | 697 | upper | NoReason | | A.java:35:20:35:20 | y | 0 | 348 | lower | ... == ... | | A.java:35:20:35:20 | y | 0 | 348 | upper | ... == ... | | A.java:35:20:35:20 | y | SSA init(x) | -1 | lower | ... == ... | diff --git a/java/ql/test/library-tests/dataflow/state/test.ql b/java/ql/test/library-tests/dataflow/state/test.ql index afd7ed9a97e..b82dd95c0b1 100644 --- a/java/ql/test/library-tests/dataflow/state/test.ql +++ b/java/ql/test/library-tests/dataflow/state/test.ql @@ -55,7 +55,7 @@ module Config implements DataFlow::StateConfigSig { int explorationLimit() { result = 0 } -module Flow = TaintTracking::MakeWithState; +module Flow = TaintTracking::GlobalWithState; module PartialFlow = Flow::FlowExploration; @@ -67,7 +67,7 @@ class HasFlowTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "flow" and exists(Flow::PathNode src, Flow::PathNode sink | - Flow::hasFlowPath(src, sink) and + Flow::flowPath(src, sink) and sink.getNode().getLocation() = location and element = sink.toString() and value = src.getState() @@ -75,7 +75,7 @@ class HasFlowTest extends InlineExpectationsTest { or tag = "pFwd" and exists(PartialFlow::PartialPathNode src, PartialFlow::PartialPathNode node | - PartialFlow::hasPartialFlow(src, node, _) and + PartialFlow::partialFlow(src, node, _) and checkNode(node.getNode()) and node.getNode().getLocation() = location and element = node.toString() and @@ -84,7 +84,7 @@ class HasFlowTest extends InlineExpectationsTest { or tag = "pRev" and exists(PartialFlow::PartialPathNode node, PartialFlow::PartialPathNode sink | - PartialFlow::hasPartialFlowRev(node, sink, _) and + PartialFlow::partialFlowRev(node, sink, _) and checkNode(node.getNode()) and node.getNode().getLocation() = location and element = node.toString() and diff --git a/java/ql/test/library-tests/frameworks/netty/generated/Test.java b/java/ql/test/library-tests/frameworks/netty/generated/Test.java new file mode 100644 index 00000000000..ab38ecbe53c --- /dev/null +++ b/java/ql/test/library-tests/frameworks/netty/generated/Test.java @@ -0,0 +1,7895 @@ +package generatedtest; + +import io.netty.buffer.AbstractByteBuf; +import io.netty.buffer.AbstractReferenceCountedByteBuf; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.ByteBufConvertible; +import io.netty.buffer.ByteBufHolder; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.buffer.ByteBufUtil; +import io.netty.buffer.CompositeByteBuf; +import io.netty.buffer.DefaultByteBufHolder; +import io.netty.buffer.SwappedByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.DefaultFileRegion; +import io.netty.channel.FileRegion; +import io.netty.handler.codec.ByteToMessageDecoder; +import io.netty.handler.codec.Headers; +import io.netty.handler.codec.HeadersUtils; +// import io.netty.handler.codec.V; // testgen bug? +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.handler.codec.http.FullHttpMessage; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpContent; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpMessage; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; +import io.netty.handler.codec.http.LastHttpContent; +import io.netty.handler.codec.http.QueryStringDecoder; +import io.netty.handler.codec.http.cookie.Cookie; +import io.netty.handler.codec.http.cookie.DefaultCookie; +import io.netty.handler.codec.http.cookie.ServerCookieDecoder; +import io.netty.handler.codec.http.cookie.ServerCookieEncoder; +import io.netty.handler.codec.http.multipart.Attribute; +import io.netty.handler.codec.http.multipart.FileUpload; +import io.netty.handler.codec.http.multipart.HttpData; +import io.netty.handler.codec.http.multipart.HttpPostMultipartRequestDecoder; +import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder; +import io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder; +import io.netty.handler.codec.http.multipart.InterfaceHttpData; +import io.netty.handler.codec.http.multipart.InterfaceHttpPostRequestDecoder; +import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; +import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; +import io.netty.handler.codec.http.websocketx.ContinuationWebSocketFrame; +import io.netty.handler.codec.http.websocketx.PingWebSocketFrame; +import io.netty.handler.codec.http.websocketx.PongWebSocketFrame; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import io.netty.handler.codec.http.websocketx.WebSocketCloseStatus; +import io.netty.handler.codec.http.websocketx.WebSocketFrame; +import io.netty.handler.codec.http2.Http2Headers; +import io.netty.handler.codec.http2.Http2HeadersFrame; +import io.netty.handler.codec.http2.Http2PushPromiseFrame; +import io.netty.handler.codec.http2.HttpConversionUtil; +import io.netty.util.AbstractReferenceCounted; +import io.netty.util.AsciiString; +import io.netty.util.ReferenceCounted; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.GatheringByteChannel; +import java.nio.channels.ScatteringByteChannel; +import java.nio.charset.Charset; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +// Test case generated by GenerateFlowTestCase.ql +public class Test { + + T getElement(Iterable it) { return it.iterator().next(); } + T getElement(Iterator it) { return it.next(); } + Object getElementDefault(Object container) { return null; } + Object getMapKeyDefault(Object container) { return null; } + Object getMapValueDefault(Object container) { return null; } + Object newWithElementDefault(Object element) { return null; } + Object newWithMapKeyDefault(Object element) { return null; } + Object newWithMapValueDefault(Object element) { return null; } + Object source() { return null; } + void sink(Object o) { } + + public void test() throws Exception { + + { + // "io.netty.buffer;ByteBuf;true;array;();;Argument[-1];ReturnValue;taint;manual" + byte[] out = null; + ByteBuf in = (ByteBuf)source(); + out = in.array(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;array;();;Argument[-1];ReturnValue;taint;manual" + byte[] out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.array(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;array;();;Argument[-1];ReturnValue;taint;manual" + byte[] out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.array(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;asReadOnly;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.asReadOnly(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;asReadOnly;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.asReadOnly(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;asReadOnly;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.asReadOnly(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;capacity;(int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.capacity(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;capacity;(int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.capacity(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;capacity;(int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.capacity(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;copy;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;copy;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;copy;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.copy(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;copy;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.copy(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;copy;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;copy;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.copy(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;discardReadBytes;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.discardReadBytes(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;discardReadBytes;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.discardReadBytes(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;discardReadBytes;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.discardReadBytes(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;discardReadBytes;();;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.discardReadBytes(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;discardSomeReadBytes;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.discardSomeReadBytes(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;discardSomeReadBytes;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.discardSomeReadBytes(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;discardSomeReadBytes;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.discardSomeReadBytes(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;discardSomeReadBytes;();;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.discardSomeReadBytes(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;ensureWritable;(int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.ensureWritable(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;ensureWritable;(int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.ensureWritable(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;ensureWritable;(int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.ensureWritable(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;ensureWritable;(int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.ensureWritable(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf);;Argument[-1];Argument[1];taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + in.getBytes(0, out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf);;Argument[-1];Argument[1];taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + in.getBytes(0, out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf);;Argument[-1];Argument[1];taint;manual" + ByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + in.getBytes(0, out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf);;Argument[-1];Argument[1];taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.getBytes(0, out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.getBytes(0, (ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.getBytes(0, (ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.getBytes(0, (ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.getBytes(0, (ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf,int);;Argument[-1];Argument[1];taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + in.getBytes(0, out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf,int);;Argument[-1];Argument[1];taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + in.getBytes(0, out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf,int);;Argument[-1];Argument[1];taint;manual" + ByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + in.getBytes(0, out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf,int);;Argument[-1];Argument[1];taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.getBytes(0, out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.getBytes(0, (ByteBuf)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.getBytes(0, (ByteBuf)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.getBytes(0, (ByteBuf)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf,int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.getBytes(0, (ByteBuf)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf,int,int);;Argument[-1];Argument[1];taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + in.getBytes(0, out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf,int,int);;Argument[-1];Argument[1];taint;manual" + ByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + in.getBytes(0, out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf,int,int);;Argument[-1];Argument[1];taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.getBytes(0, out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf,int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.getBytes(0, (ByteBuf)null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf,int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.getBytes(0, (ByteBuf)null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuf,int,int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.getBytes(0, (ByteBuf)null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuffer);;Argument[-1];Argument[1];taint;manual" + ByteBuffer out = null; + ByteBuf in = (ByteBuf)source(); + in.getBytes(0, out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuffer);;Argument[-1];Argument[1];taint;manual" + ByteBuffer out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + in.getBytes(0, out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuffer);;Argument[-1];Argument[1];taint;manual" + ByteBuffer out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.getBytes(0, out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuffer);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.getBytes(0, (ByteBuffer)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuffer);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.getBytes(0, (ByteBuffer)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,ByteBuffer);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.getBytes(0, (ByteBuffer)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,FileChannel,long,int);;Argument[-1];Argument[1];taint;manual" + FileChannel out = null; + ByteBuf in = (ByteBuf)source(); + in.getBytes(0, out, 0L, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,FileChannel,long,int);;Argument[-1];Argument[1];taint;manual" + FileChannel out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + in.getBytes(0, out, 0L, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,FileChannel,long,int);;Argument[-1];Argument[1];taint;manual" + FileChannel out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.getBytes(0, out, 0L, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,GatheringByteChannel,int);;Argument[-1];Argument[1];taint;manual" + GatheringByteChannel out = null; + ByteBuf in = (ByteBuf)source(); + in.getBytes(0, out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,GatheringByteChannel,int);;Argument[-1];Argument[1];taint;manual" + GatheringByteChannel out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + in.getBytes(0, out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,GatheringByteChannel,int);;Argument[-1];Argument[1];taint;manual" + GatheringByteChannel out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.getBytes(0, out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,OutputStream,int);;Argument[-1];Argument[1];taint;manual" + OutputStream out = null; + ByteBuf in = (ByteBuf)source(); + in.getBytes(0, out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,OutputStream,int);;Argument[-1];Argument[1];taint;manual" + OutputStream out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + in.getBytes(0, out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,OutputStream,int);;Argument[-1];Argument[1];taint;manual" + OutputStream out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.getBytes(0, out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,OutputStream,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.getBytes(0, (OutputStream)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,OutputStream,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.getBytes(0, (OutputStream)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,OutputStream,int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.getBytes(0, (OutputStream)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,byte[]);;Argument[-1];Argument[1];taint;manual" + byte[] out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + in.getBytes(0, out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,byte[]);;Argument[-1];Argument[1];taint;manual" + byte[] out = null; + ByteBuf in = (ByteBuf)source(); + in.getBytes(0, out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,byte[]);;Argument[-1];Argument[1];taint;manual" + byte[] out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + in.getBytes(0, out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,byte[]);;Argument[-1];Argument[1];taint;manual" + byte[] out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.getBytes(0, out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,byte[]);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.getBytes(0, (byte[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,byte[]);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.getBytes(0, (byte[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,byte[]);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.getBytes(0, (byte[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,byte[]);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.getBytes(0, (byte[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,byte[],int,int);;Argument[-1];Argument[1];taint;manual" + byte[] out = null; + ByteBuf in = (ByteBuf)source(); + in.getBytes(0, out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,byte[],int,int);;Argument[-1];Argument[1];taint;manual" + byte[] out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + in.getBytes(0, out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,byte[],int,int);;Argument[-1];Argument[1];taint;manual" + byte[] out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.getBytes(0, out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,byte[],int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.getBytes(0, (byte[])null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,byte[],int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.getBytes(0, (byte[])null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getBytes;(int,byte[],int,int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.getBytes(0, (byte[])null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;getChar;;;Argument[-1];ReturnValue;taint;manual" + char out = 'a'; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.getChar(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getChar;;;Argument[-1];ReturnValue;taint;manual" + char out = 'a'; + ByteBuf in = (ByteBuf)source(); + out = in.getChar(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getChar;;;Argument[-1];ReturnValue;taint;manual" + char out = 'a'; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.getChar(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getCharSequence;;;Argument[-1];ReturnValue;taint;manual" + CharSequence out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.getCharSequence(0, 0, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getCharSequence;;;Argument[-1];ReturnValue;taint;manual" + CharSequence out = null; + ByteBuf in = (ByteBuf)source(); + out = in.getCharSequence(0, 0, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;getCharSequence;;;Argument[-1];ReturnValue;taint;manual" + CharSequence out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.getCharSequence(0, 0, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;markReaderIndex;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.markReaderIndex(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;markReaderIndex;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.markReaderIndex(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;markReaderIndex;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.markReaderIndex(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;markReaderIndex;();;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.markReaderIndex(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;markWriterIndex;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.markWriterIndex(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;markWriterIndex;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.markWriterIndex(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;markWriterIndex;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.markWriterIndex(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;markWriterIndex;();;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.markWriterIndex(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;nioBuffer;;;Argument[-1];ReturnValue;taint;manual" + ByteBuffer out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.nioBuffer(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;nioBuffer;;;Argument[-1];ReturnValue;taint;manual" + ByteBuffer out = null; + ByteBuf in = (ByteBuf)source(); + out = in.nioBuffer(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;nioBuffer;;;Argument[-1];ReturnValue;taint;manual" + ByteBuffer out = null; + ByteBuf in = (ByteBuf)source(); + out = in.nioBuffer(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;nioBuffer;;;Argument[-1];ReturnValue;taint;manual" + ByteBuffer out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.nioBuffer(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;nioBuffer;;;Argument[-1];ReturnValue;taint;manual" + ByteBuffer out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.nioBuffer(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;nioBuffer;;;Argument[-1];ReturnValue;taint;manual" + ByteBuffer out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.nioBuffer(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;nioBuffers;;;Argument[-1];ReturnValue;taint;manual" + ByteBuffer[] out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.nioBuffers(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;nioBuffers;;;Argument[-1];ReturnValue;taint;manual" + ByteBuffer[] out = null; + ByteBuf in = (ByteBuf)source(); + out = in.nioBuffers(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;nioBuffers;;;Argument[-1];ReturnValue;taint;manual" + ByteBuffer[] out = null; + ByteBuf in = (ByteBuf)source(); + out = in.nioBuffers(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;nioBuffers;;;Argument[-1];ReturnValue;taint;manual" + ByteBuffer[] out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.nioBuffers(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;nioBuffers;;;Argument[-1];ReturnValue;taint;manual" + ByteBuffer[] out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.nioBuffers(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;nioBuffers;;;Argument[-1];ReturnValue;taint;manual" + ByteBuffer[] out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.nioBuffers(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;nioBuffers;;;Argument[-1];ReturnValue;taint;manual" + ByteBuffer[] out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.nioBuffers(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;order;(ByteOrder);;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.order(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;order;(ByteOrder);;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.order(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;order;(ByteOrder);;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.order(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf);;Argument[-1];Argument[0];taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + in.readBytes(out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf);;Argument[-1];Argument[0];taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + in.readBytes(out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf);;Argument[-1];Argument[0];taint;manual" + ByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + in.readBytes(out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf);;Argument[-1];Argument[0];taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.readBytes(out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.readBytes((ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.readBytes((ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.readBytes((ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.readBytes((ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf,int);;Argument[-1];Argument[0];taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + in.readBytes(out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf,int);;Argument[-1];Argument[0];taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + in.readBytes(out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf,int);;Argument[-1];Argument[0];taint;manual" + ByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + in.readBytes(out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf,int);;Argument[-1];Argument[0];taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.readBytes(out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.readBytes((ByteBuf)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.readBytes((ByteBuf)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.readBytes((ByteBuf)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf,int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.readBytes((ByteBuf)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf,int,int);;Argument[-1];Argument[0];taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + in.readBytes(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf,int,int);;Argument[-1];Argument[0];taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + in.readBytes(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf,int,int);;Argument[-1];Argument[0];taint;manual" + ByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + in.readBytes(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf,int,int);;Argument[-1];Argument[0];taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.readBytes(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf,int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.readBytes((ByteBuf)null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf,int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.readBytes((ByteBuf)null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf,int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.readBytes((ByteBuf)null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuf,int,int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.readBytes((ByteBuf)null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuffer);;Argument[-1];Argument[0];taint;manual" + ByteBuffer out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + in.readBytes(out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuffer);;Argument[-1];Argument[0];taint;manual" + ByteBuffer out = null; + ByteBuf in = (ByteBuf)source(); + in.readBytes(out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuffer);;Argument[-1];Argument[0];taint;manual" + ByteBuffer out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + in.readBytes(out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuffer);;Argument[-1];Argument[0];taint;manual" + ByteBuffer out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.readBytes(out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuffer);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.readBytes((ByteBuffer)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuffer);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.readBytes((ByteBuffer)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuffer);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.readBytes((ByteBuffer)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(ByteBuffer);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.readBytes((ByteBuffer)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(FileChannel,long,int);;Argument[-1];Argument[0];taint;manual" + FileChannel out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + in.readBytes(out, 0L, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(FileChannel,long,int);;Argument[-1];Argument[0];taint;manual" + FileChannel out = null; + ByteBuf in = (ByteBuf)source(); + in.readBytes(out, 0L, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(FileChannel,long,int);;Argument[-1];Argument[0];taint;manual" + FileChannel out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.readBytes(out, 0L, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(GatheringByteChannel,int);;Argument[-1];Argument[0];taint;manual" + GatheringByteChannel out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + in.readBytes(out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(GatheringByteChannel,int);;Argument[-1];Argument[0];taint;manual" + GatheringByteChannel out = null; + ByteBuf in = (ByteBuf)source(); + in.readBytes(out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(GatheringByteChannel,int);;Argument[-1];Argument[0];taint;manual" + GatheringByteChannel out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.readBytes(out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(OutputStream,int);;Argument[-1];Argument[0];taint;manual" + OutputStream out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + in.readBytes(out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(OutputStream,int);;Argument[-1];Argument[0];taint;manual" + OutputStream out = null; + ByteBuf in = (ByteBuf)source(); + in.readBytes(out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(OutputStream,int);;Argument[-1];Argument[0];taint;manual" + OutputStream out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + in.readBytes(out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(OutputStream,int);;Argument[-1];Argument[0];taint;manual" + OutputStream out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.readBytes(out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(OutputStream,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.readBytes((OutputStream)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(OutputStream,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.readBytes((OutputStream)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(OutputStream,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.readBytes((OutputStream)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(OutputStream,int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.readBytes((OutputStream)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(byte[]);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + in.readBytes(out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(byte[]);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + ByteBuf in = (ByteBuf)source(); + in.readBytes(out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(byte[]);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + in.readBytes(out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(byte[]);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.readBytes(out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(byte[]);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.readBytes((byte[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(byte[]);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.readBytes((byte[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(byte[]);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.readBytes((byte[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(byte[]);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.readBytes((byte[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(byte[],int,int);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + in.readBytes(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(byte[],int,int);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + ByteBuf in = (ByteBuf)source(); + in.readBytes(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(byte[],int,int);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + in.readBytes(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(byte[],int,int);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + in.readBytes(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(byte[],int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.readBytes((byte[])null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(byte[],int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.readBytes((byte[])null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(byte[],int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.readBytes((byte[])null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(byte[],int,int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.readBytes((byte[])null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(int);;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.readBytes(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(int);;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.readBytes(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readBytes;(int);;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.readBytes(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readChar;;;Argument[-1];ReturnValue;taint;manual" + char out = 'a'; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.readChar(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readChar;;;Argument[-1];ReturnValue;taint;manual" + char out = 'a'; + ByteBuf in = (ByteBuf)source(); + out = in.readChar(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readChar;;;Argument[-1];ReturnValue;taint;manual" + char out = 'a'; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.readChar(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readCharSequence;;;Argument[-1];ReturnValue;taint;manual" + CharSequence out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.readCharSequence(0, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readCharSequence;;;Argument[-1];ReturnValue;taint;manual" + CharSequence out = null; + ByteBuf in = (ByteBuf)source(); + out = in.readCharSequence(0, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readCharSequence;;;Argument[-1];ReturnValue;taint;manual" + CharSequence out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.readCharSequence(0, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readRetainedSlice;(int);;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.readRetainedSlice(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readRetainedSlice;(int);;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.readRetainedSlice(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readRetainedSlice;(int);;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.readRetainedSlice(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readSlice;(int);;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.readSlice(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readSlice;(int);;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.readSlice(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readSlice;(int);;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.readSlice(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;readerIndex;(int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.readerIndex(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readerIndex;(int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.readerIndex(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readerIndex;(int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.readerIndex(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;readerIndex;(int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.readerIndex(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;resetReaderIndex;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.resetReaderIndex(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;resetReaderIndex;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.resetReaderIndex(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;resetReaderIndex;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.resetReaderIndex(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;resetReaderIndex;();;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.resetReaderIndex(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;resetWriterIndex;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.resetWriterIndex(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;resetWriterIndex;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.resetWriterIndex(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;resetWriterIndex;();;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.resetWriterIndex(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;resetWriterIndex;();;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.resetWriterIndex(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;retainedSlice;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.retainedSlice(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;retainedSlice;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.retainedSlice(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;retainedSlice;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.retainedSlice(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;retainedSlice;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.retainedSlice(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;retainedSlice;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.retainedSlice(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;retainedSlice;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.retainedSlice(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBoolean;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setBoolean(0, false); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBoolean;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setBoolean(0, false); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBoolean;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setBoolean(0, false); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBoolean;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setBoolean(0, false); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setByte;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setByte(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setByte;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setByte(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setByte;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setByte(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setByte;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setByte(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setBytes(0, (ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setBytes(0, (ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setBytes(0, (ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setBytes(0, (ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf);;Argument[1];Argument[-1];taint;manual" + AbstractByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.setBytes(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf);;Argument[1];Argument[-1];taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.setBytes(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf);;Argument[1];Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.setBytes(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf);;Argument[1];Argument[-1];taint;manual" + SwappedByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.setBytes(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setBytes(0, (ByteBuf)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setBytes(0, (ByteBuf)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setBytes(0, (ByteBuf)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf,int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setBytes(0, (ByteBuf)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf,int);;Argument[1];Argument[-1];taint;manual" + AbstractByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.setBytes(0, in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf,int);;Argument[1];Argument[-1];taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.setBytes(0, in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf,int);;Argument[1];Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.setBytes(0, in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf,int);;Argument[1];Argument[-1];taint;manual" + SwappedByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.setBytes(0, in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf,int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setBytes(0, (ByteBuf)null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf,int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setBytes(0, (ByteBuf)null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf,int,int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setBytes(0, (ByteBuf)null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf,int,int);;Argument[1];Argument[-1];taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.setBytes(0, in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf,int,int);;Argument[1];Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.setBytes(0, in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuf,int,int);;Argument[1];Argument[-1];taint;manual" + SwappedByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.setBytes(0, in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuffer);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setBytes(0, (ByteBuffer)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuffer);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setBytes(0, (ByteBuffer)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuffer);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setBytes(0, (ByteBuffer)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuffer);;Argument[1];Argument[-1];taint;manual" + ByteBuf out = null; + ByteBuffer in = (ByteBuffer)source(); + out.setBytes(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuffer);;Argument[1];Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuffer in = (ByteBuffer)source(); + out.setBytes(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ByteBuffer);;Argument[1];Argument[-1];taint;manual" + SwappedByteBuf out = null; + ByteBuffer in = (ByteBuffer)source(); + out.setBytes(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,FileChannel,long,int);;Argument[1];Argument[-1];taint;manual" + ByteBuf out = null; + FileChannel in = (FileChannel)source(); + out.setBytes(0, in, 0L, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,FileChannel,long,int);;Argument[1];Argument[-1];taint;manual" + CompositeByteBuf out = null; + FileChannel in = (FileChannel)source(); + out.setBytes(0, in, 0L, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,FileChannel,long,int);;Argument[1];Argument[-1];taint;manual" + SwappedByteBuf out = null; + FileChannel in = (FileChannel)source(); + out.setBytes(0, in, 0L, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,InputStream,int);;Argument[1];Argument[-1];taint;manual" + ByteBuf out = null; + InputStream in = (InputStream)source(); + out.setBytes(0, in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,InputStream,int);;Argument[1];Argument[-1];taint;manual" + CompositeByteBuf out = null; + InputStream in = (InputStream)source(); + out.setBytes(0, in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,InputStream,int);;Argument[1];Argument[-1];taint;manual" + SwappedByteBuf out = null; + InputStream in = (InputStream)source(); + out.setBytes(0, in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ScatteringByteChannel,int);;Argument[1];Argument[-1];taint;manual" + ByteBuf out = null; + ScatteringByteChannel in = (ScatteringByteChannel)source(); + out.setBytes(0, in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ScatteringByteChannel,int);;Argument[1];Argument[-1];taint;manual" + CompositeByteBuf out = null; + ScatteringByteChannel in = (ScatteringByteChannel)source(); + out.setBytes(0, in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,ScatteringByteChannel,int);;Argument[1];Argument[-1];taint;manual" + SwappedByteBuf out = null; + ScatteringByteChannel in = (ScatteringByteChannel)source(); + out.setBytes(0, in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,byte[]);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setBytes(0, (byte[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,byte[]);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setBytes(0, (byte[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,byte[]);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setBytes(0, (byte[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,byte[]);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setBytes(0, (byte[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,byte[]);;Argument[1];Argument[-1];taint;manual" + AbstractByteBuf out = null; + byte[] in = (byte[])source(); + out.setBytes(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,byte[]);;Argument[1];Argument[-1];taint;manual" + ByteBuf out = null; + byte[] in = (byte[])source(); + out.setBytes(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,byte[]);;Argument[1];Argument[-1];taint;manual" + CompositeByteBuf out = null; + byte[] in = (byte[])source(); + out.setBytes(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,byte[]);;Argument[1];Argument[-1];taint;manual" + SwappedByteBuf out = null; + byte[] in = (byte[])source(); + out.setBytes(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,byte[],int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setBytes(0, (byte[])null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,byte[],int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setBytes(0, (byte[])null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,byte[],int,int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setBytes(0, (byte[])null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,byte[],int,int);;Argument[1];Argument[-1];taint;manual" + ByteBuf out = null; + byte[] in = (byte[])source(); + out.setBytes(0, in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,byte[],int,int);;Argument[1];Argument[-1];taint;manual" + CompositeByteBuf out = null; + byte[] in = (byte[])source(); + out.setBytes(0, in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setBytes;(int,byte[],int,int);;Argument[1];Argument[-1];taint;manual" + SwappedByteBuf out = null; + byte[] in = (byte[])source(); + out.setBytes(0, in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setChar;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setChar(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setChar;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setChar(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setChar;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setChar(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setChar;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setChar(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setChar;;;Argument[1];Argument[-1];taint;manual" + AbstractByteBuf out = null; + int in = (int)source(); + out.setChar(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setChar;;;Argument[1];Argument[-1];taint;manual" + ByteBuf out = null; + int in = (int)source(); + out.setChar(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setChar;;;Argument[1];Argument[-1];taint;manual" + CompositeByteBuf out = null; + int in = (int)source(); + out.setChar(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setChar;;;Argument[1];Argument[-1];taint;manual" + SwappedByteBuf out = null; + int in = (int)source(); + out.setChar(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setCharSequence;;;Argument[1];Argument[-1];taint;manual" + AbstractByteBuf out = null; + CharSequence in = (CharSequence)source(); + out.setCharSequence(0, in, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setCharSequence;;;Argument[1];Argument[-1];taint;manual" + ByteBuf out = null; + CharSequence in = (CharSequence)source(); + out.setCharSequence(0, in, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setCharSequence;;;Argument[1];Argument[-1];taint;manual" + SwappedByteBuf out = null; + CharSequence in = (CharSequence)source(); + out.setCharSequence(0, in, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;setDouble;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setDouble(0, 0.0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setDouble;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setDouble(0, 0.0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setDouble;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setDouble(0, 0.0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setDouble;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setDouble(0, 0.0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setDoubleLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setDoubleLE(0, 0.0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setFloat;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setFloat(0, 0.0f); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setFloat;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setFloat(0, 0.0f); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setFloat;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setFloat(0, 0.0f); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setFloat;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setFloat(0, 0.0f); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setFloatLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setFloatLE(0, 0.0f); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setIndex;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setIndex(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setIndex;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setIndex(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setIndex;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setIndex(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setIndex;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setIndex(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setInt;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setInt(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setInt;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setInt(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setInt;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setInt(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setInt;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setInt(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setIntLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setIntLE(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setIntLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setIntLE(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setIntLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setIntLE(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setLong;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setLong(0, 0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setLong;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setLong(0, 0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setLong;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setLong(0, 0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setLong;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setLong(0, 0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setLongLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setLongLE(0, 0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setLongLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setLongLE(0, 0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setLongLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setLongLE(0, 0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setMedium;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setMedium(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setMedium;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setMedium(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setMedium;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setMedium(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setMedium;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setMedium(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setMediumLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setMediumLE(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setMediumLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setMediumLE(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setMediumLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setMediumLE(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setShort;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setShort(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setShort;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setShort(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setShort;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setShort(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setShort;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setShort(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setShortLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setShortLE(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setShortLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setShortLE(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setShortLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setShortLE(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setZero;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.setZero(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setZero;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.setZero(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setZero;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.setZero(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;setZero;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.setZero(0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;skipBytes;(int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.skipBytes(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;skipBytes;(int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.skipBytes(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;skipBytes;(int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.skipBytes(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;skipBytes;(int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.skipBytes(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;slice;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.slice(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;slice;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.slice(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;slice;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.slice(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;slice;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.slice(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;slice;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.slice(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;slice;;;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.slice(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.toString(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.toString(0, 0, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.toString(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + ByteBuf in = (ByteBuf)source(); + out = in.toString(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + ByteBuf in = (ByteBuf)source(); + out = in.toString(0, 0, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + ByteBuf in = (ByteBuf)source(); + out = in.toString(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.toString(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.toString(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.toString(0, 0, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.toString(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;unwrap;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.unwrap(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;unwrap;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.unwrap(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;unwrap;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.unwrap(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBoolean;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeBoolean(false); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBoolean;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeBoolean(false); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBoolean;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeBoolean(false); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBoolean;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writeBoolean(false); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeByte;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeByte(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeByte;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeByte(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeByte;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeByte(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeByte;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writeByte(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeByte;;;Argument[0];Argument[-1];taint;manual" + AbstractByteBuf out = null; + int in = (int)source(); + out.writeByte(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeByte;;;Argument[0];Argument[-1];taint;manual" + ByteBuf out = null; + int in = (int)source(); + out.writeByte(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeByte;;;Argument[0];Argument[-1];taint;manual" + CompositeByteBuf out = null; + int in = (int)source(); + out.writeByte(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeByte;;;Argument[0];Argument[-1];taint;manual" + SwappedByteBuf out = null; + int in = (int)source(); + out.writeByte(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeBytes((ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeBytes((ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeBytes((ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writeBytes((ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf);;Argument[0];Argument[-1];taint;manual" + AbstractByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.writeBytes(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf);;Argument[0];Argument[-1];taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.writeBytes(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf);;Argument[0];Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.writeBytes(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf);;Argument[0];Argument[-1];taint;manual" + SwappedByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.writeBytes(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeBytes((ByteBuf)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeBytes((ByteBuf)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeBytes((ByteBuf)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf,int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writeBytes((ByteBuf)null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf,int);;Argument[0];Argument[-1];taint;manual" + AbstractByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.writeBytes(in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf,int);;Argument[0];Argument[-1];taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.writeBytes(in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf,int);;Argument[0];Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.writeBytes(in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf,int);;Argument[0];Argument[-1];taint;manual" + SwappedByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.writeBytes(in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf,int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeBytes((ByteBuf)null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf,int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeBytes((ByteBuf)null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf,int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeBytes((ByteBuf)null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf,int,int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writeBytes((ByteBuf)null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf,int,int);;Argument[0];Argument[-1];taint;manual" + AbstractByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.writeBytes(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf,int,int);;Argument[0];Argument[-1];taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.writeBytes(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf,int,int);;Argument[0];Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.writeBytes(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuf,int,int);;Argument[0];Argument[-1];taint;manual" + SwappedByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.writeBytes(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuffer);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeBytes((ByteBuffer)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuffer);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeBytes((ByteBuffer)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuffer);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeBytes((ByteBuffer)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuffer);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writeBytes((ByteBuffer)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuffer);;Argument[0];Argument[-1];taint;manual" + AbstractByteBuf out = null; + ByteBuffer in = (ByteBuffer)source(); + out.writeBytes(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuffer);;Argument[0];Argument[-1];taint;manual" + ByteBuf out = null; + ByteBuffer in = (ByteBuffer)source(); + out.writeBytes(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuffer);;Argument[0];Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuffer in = (ByteBuffer)source(); + out.writeBytes(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ByteBuffer);;Argument[0];Argument[-1];taint;manual" + SwappedByteBuf out = null; + ByteBuffer in = (ByteBuffer)source(); + out.writeBytes(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(FileChannel,long,int);;Argument[0];Argument[-1];taint;manual" + AbstractByteBuf out = null; + FileChannel in = (FileChannel)source(); + out.writeBytes(in, 0L, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(FileChannel,long,int);;Argument[0];Argument[-1];taint;manual" + ByteBuf out = null; + FileChannel in = (FileChannel)source(); + out.writeBytes(in, 0L, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(FileChannel,long,int);;Argument[0];Argument[-1];taint;manual" + SwappedByteBuf out = null; + FileChannel in = (FileChannel)source(); + out.writeBytes(in, 0L, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(InputStream,int);;Argument[0];Argument[-1];taint;manual" + AbstractByteBuf out = null; + InputStream in = (InputStream)source(); + out.writeBytes(in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(InputStream,int);;Argument[0];Argument[-1];taint;manual" + ByteBuf out = null; + InputStream in = (InputStream)source(); + out.writeBytes(in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(InputStream,int);;Argument[0];Argument[-1];taint;manual" + SwappedByteBuf out = null; + InputStream in = (InputStream)source(); + out.writeBytes(in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ScatteringByteChannel,int);;Argument[0];Argument[-1];taint;manual" + AbstractByteBuf out = null; + ScatteringByteChannel in = (ScatteringByteChannel)source(); + out.writeBytes(in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ScatteringByteChannel,int);;Argument[0];Argument[-1];taint;manual" + ByteBuf out = null; + ScatteringByteChannel in = (ScatteringByteChannel)source(); + out.writeBytes(in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(ScatteringByteChannel,int);;Argument[0];Argument[-1];taint;manual" + SwappedByteBuf out = null; + ScatteringByteChannel in = (ScatteringByteChannel)source(); + out.writeBytes(in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(byte[]);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeBytes((byte[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(byte[]);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeBytes((byte[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(byte[]);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeBytes((byte[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(byte[]);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writeBytes((byte[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(byte[]);;Argument[0];Argument[-1];taint;manual" + AbstractByteBuf out = null; + byte[] in = (byte[])source(); + out.writeBytes(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(byte[]);;Argument[0];Argument[-1];taint;manual" + ByteBuf out = null; + byte[] in = (byte[])source(); + out.writeBytes(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(byte[]);;Argument[0];Argument[-1];taint;manual" + CompositeByteBuf out = null; + byte[] in = (byte[])source(); + out.writeBytes(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(byte[]);;Argument[0];Argument[-1];taint;manual" + SwappedByteBuf out = null; + byte[] in = (byte[])source(); + out.writeBytes(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(byte[],int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeBytes((byte[])null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(byte[],int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeBytes((byte[])null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(byte[],int,int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeBytes((byte[])null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(byte[],int,int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writeBytes((byte[])null, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(byte[],int,int);;Argument[0];Argument[-1];taint;manual" + AbstractByteBuf out = null; + byte[] in = (byte[])source(); + out.writeBytes(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(byte[],int,int);;Argument[0];Argument[-1];taint;manual" + ByteBuf out = null; + byte[] in = (byte[])source(); + out.writeBytes(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(byte[],int,int);;Argument[0];Argument[-1];taint;manual" + CompositeByteBuf out = null; + byte[] in = (byte[])source(); + out.writeBytes(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeBytes;(byte[],int,int);;Argument[0];Argument[-1];taint;manual" + SwappedByteBuf out = null; + byte[] in = (byte[])source(); + out.writeBytes(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeChar;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeChar(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeChar;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeChar(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeChar;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeChar(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeChar;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writeChar(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeChar;;;Argument[0];Argument[-1];taint;manual" + AbstractByteBuf out = null; + int in = (int)source(); + out.writeChar(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeChar;;;Argument[0];Argument[-1];taint;manual" + ByteBuf out = null; + int in = (int)source(); + out.writeChar(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeChar;;;Argument[0];Argument[-1];taint;manual" + CompositeByteBuf out = null; + int in = (int)source(); + out.writeChar(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeChar;;;Argument[0];Argument[-1];taint;manual" + SwappedByteBuf out = null; + int in = (int)source(); + out.writeChar(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeCharSequence;;;Argument[0];Argument[-1];taint;manual" + AbstractByteBuf out = null; + CharSequence in = (CharSequence)source(); + out.writeCharSequence(in, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeCharSequence;;;Argument[0];Argument[-1];taint;manual" + ByteBuf out = null; + CharSequence in = (CharSequence)source(); + out.writeCharSequence(in, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeCharSequence;;;Argument[0];Argument[-1];taint;manual" + SwappedByteBuf out = null; + CharSequence in = (CharSequence)source(); + out.writeCharSequence(in, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeDouble;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeDouble(0.0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeDouble;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeDouble(0.0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeDouble;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeDouble(0.0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeDouble;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writeDouble(0.0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeDoubleLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeDoubleLE(0.0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeFloat;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeFloat(0.0f); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeFloat;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeFloat(0.0f); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeFloat;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeFloat(0.0f); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeFloat;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writeFloat(0.0f); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeFloatLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeFloatLE(0.0f); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeInt;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeInt(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeInt;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeInt(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeInt;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeInt(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeInt;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writeInt(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeIntLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeIntLE(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeIntLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeIntLE(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeIntLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeIntLE(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeLong;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeLong(0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeLong;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeLong(0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeLong;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeLong(0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeLong;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writeLong(0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeLongLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeLongLE(0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeLongLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeLongLE(0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeLongLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeLongLE(0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeMedium;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeMedium(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeMedium;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeMedium(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeMedium;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeMedium(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeMedium;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writeMedium(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeMediumLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeMediumLE(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeMediumLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeMediumLE(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeMediumLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeMediumLE(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeShort;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeShort(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeShort;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeShort(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeShort;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeShort(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeShort;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writeShort(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeShortLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeShortLE(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeShortLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeShortLE(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeShortLE;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeShortLE(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeZero;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writeZero(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeZero;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writeZero(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeZero;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writeZero(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writeZero;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writeZero(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writerIndex;(int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractByteBuf in = (AbstractByteBuf)source(); + out = in.writerIndex(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writerIndex;(int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.writerIndex(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writerIndex;(int);;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.writerIndex(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBuf;true;writerIndex;(int);;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.writerIndex(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBufConvertible;true;asByteBuf;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.asByteBuf(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufConvertible;true;asByteBuf;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBufConvertible in = (ByteBufConvertible)source(); + out = in.asByteBuf(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;content;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBufHolder in = (ByteBufHolder)source(); + out = in.content(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;content;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + DefaultByteBufHolder in = (DefaultByteBufHolder)source(); + out = in.content(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + Attribute out = null; + Attribute in = (Attribute)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + BinaryWebSocketFrame out = null; + BinaryWebSocketFrame in = (BinaryWebSocketFrame)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + ByteBufHolder out = null; + ByteBufHolder in = (ByteBufHolder)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + ByteBufHolder out = null; + DefaultByteBufHolder in = (DefaultByteBufHolder)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + CloseWebSocketFrame out = null; + CloseWebSocketFrame in = (CloseWebSocketFrame)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + ContinuationWebSocketFrame out = null; + ContinuationWebSocketFrame in = (ContinuationWebSocketFrame)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + FileUpload out = null; + FileUpload in = (FileUpload)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + FullHttpMessage out = null; + FullHttpMessage in = (FullHttpMessage)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + FullHttpRequest out = null; + FullHttpRequest in = (FullHttpRequest)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + FullHttpResponse out = null; + FullHttpResponse in = (FullHttpResponse)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + HttpContent out = null; + HttpContent in = (HttpContent)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + HttpData out = null; + HttpData in = (HttpData)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + LastHttpContent out = null; + LastHttpContent in = (LastHttpContent)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + PingWebSocketFrame out = null; + PingWebSocketFrame in = (PingWebSocketFrame)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + PongWebSocketFrame out = null; + PongWebSocketFrame in = (PongWebSocketFrame)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + TextWebSocketFrame out = null; + TextWebSocketFrame in = (TextWebSocketFrame)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;copy;();;Argument[-1];ReturnValue;taint;manual" + WebSocketFrame out = null; + WebSocketFrame in = (WebSocketFrame)source(); + out = in.copy(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + Attribute out = null; + Attribute in = (Attribute)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + BinaryWebSocketFrame out = null; + BinaryWebSocketFrame in = (BinaryWebSocketFrame)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + ByteBufHolder out = null; + ByteBufHolder in = (ByteBufHolder)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + ByteBufHolder out = null; + DefaultByteBufHolder in = (DefaultByteBufHolder)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + CloseWebSocketFrame out = null; + CloseWebSocketFrame in = (CloseWebSocketFrame)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + ContinuationWebSocketFrame out = null; + ContinuationWebSocketFrame in = (ContinuationWebSocketFrame)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + FileUpload out = null; + FileUpload in = (FileUpload)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + FullHttpMessage out = null; + FullHttpMessage in = (FullHttpMessage)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + FullHttpRequest out = null; + FullHttpRequest in = (FullHttpRequest)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + FullHttpResponse out = null; + FullHttpResponse in = (FullHttpResponse)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + HttpContent out = null; + HttpContent in = (HttpContent)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + HttpData out = null; + HttpData in = (HttpData)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + LastHttpContent out = null; + LastHttpContent in = (LastHttpContent)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + PingWebSocketFrame out = null; + PingWebSocketFrame in = (PingWebSocketFrame)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + PongWebSocketFrame out = null; + PongWebSocketFrame in = (PongWebSocketFrame)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + TextWebSocketFrame out = null; + TextWebSocketFrame in = (TextWebSocketFrame)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;duplicate;();;Argument[-1];ReturnValue;taint;manual" + WebSocketFrame out = null; + WebSocketFrame in = (WebSocketFrame)source(); + out = in.duplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + Attribute out = null; + ByteBuf in = (ByteBuf)source(); + Attribute instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + BinaryWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + BinaryWebSocketFrame instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + ByteBufHolder out = null; + ByteBuf in = (ByteBuf)source(); + ByteBufHolder instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + ByteBufHolder out = null; + ByteBuf in = (ByteBuf)source(); + DefaultByteBufHolder instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + CloseWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + CloseWebSocketFrame instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + ContinuationWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + ContinuationWebSocketFrame instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + FileUpload out = null; + ByteBuf in = (ByteBuf)source(); + FileUpload instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + FullHttpMessage out = null; + ByteBuf in = (ByteBuf)source(); + FullHttpMessage instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + FullHttpRequest out = null; + ByteBuf in = (ByteBuf)source(); + FullHttpRequest instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + FullHttpResponse out = null; + ByteBuf in = (ByteBuf)source(); + FullHttpResponse instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + HttpContent out = null; + ByteBuf in = (ByteBuf)source(); + HttpContent instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + HttpData out = null; + ByteBuf in = (ByteBuf)source(); + HttpData instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + LastHttpContent out = null; + ByteBuf in = (ByteBuf)source(); + LastHttpContent instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + PingWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + PingWebSocketFrame instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + PongWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + PongWebSocketFrame instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + TextWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + TextWebSocketFrame instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;replace;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + WebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + WebSocketFrame instance = null; + out = instance.replace(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + Attribute out = null; + Attribute in = (Attribute)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + BinaryWebSocketFrame out = null; + BinaryWebSocketFrame in = (BinaryWebSocketFrame)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + ByteBufHolder out = null; + ByteBufHolder in = (ByteBufHolder)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + ByteBufHolder out = null; + DefaultByteBufHolder in = (DefaultByteBufHolder)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + CloseWebSocketFrame out = null; + CloseWebSocketFrame in = (CloseWebSocketFrame)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + ContinuationWebSocketFrame out = null; + ContinuationWebSocketFrame in = (ContinuationWebSocketFrame)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + FileUpload out = null; + FileUpload in = (FileUpload)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + FullHttpMessage out = null; + FullHttpMessage in = (FullHttpMessage)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + FullHttpRequest out = null; + FullHttpRequest in = (FullHttpRequest)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + FullHttpResponse out = null; + FullHttpResponse in = (FullHttpResponse)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + HttpContent out = null; + HttpContent in = (HttpContent)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + HttpData out = null; + HttpData in = (HttpData)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + LastHttpContent out = null; + LastHttpContent in = (LastHttpContent)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + PingWebSocketFrame out = null; + PingWebSocketFrame in = (PingWebSocketFrame)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + PongWebSocketFrame out = null; + PongWebSocketFrame in = (PongWebSocketFrame)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + TextWebSocketFrame out = null; + TextWebSocketFrame in = (TextWebSocketFrame)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufHolder;true;retainedDuplicate;();;Argument[-1];ReturnValue;taint;manual" + WebSocketFrame out = null; + WebSocketFrame in = (WebSocketFrame)source(); + out = in.retainedDuplicate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufInputStream;true;ByteBufInputStream;;;Argument[0];Argument[-1];taint;manual" + ByteBufInputStream out = null; + ByteBuf in = (ByteBuf)source(); + out = new ByteBufInputStream(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufInputStream;true;ByteBufInputStream;;;Argument[0];Argument[-1];taint;manual" + ByteBufInputStream out = null; + ByteBuf in = (ByteBuf)source(); + out = new ByteBufInputStream(in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufInputStream;true;ByteBufInputStream;;;Argument[0];Argument[-1];taint;manual" + ByteBufInputStream out = null; + ByteBuf in = (ByteBuf)source(); + out = new ByteBufInputStream(in, 0, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufInputStream;true;ByteBufInputStream;;;Argument[0];Argument[-1];taint;manual" + ByteBufInputStream out = null; + ByteBuf in = (ByteBuf)source(); + out = new ByteBufInputStream(in, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufOutputStream;true;ByteBufOutputStream;;;Argument[0];Argument[-1];taint;manual" + ByteBufOutputStream out = null; + ByteBuf in = (ByteBuf)source(); + out = new ByteBufOutputStream(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufOutputStream;true;buffer;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBufOutputStream in = (ByteBufOutputStream)source(); + out = in.buffer(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;copy;(AsciiString,ByteBuf);;Argument[0];Argument[1];taint;manual" + ByteBuf out = null; + AsciiString in = (AsciiString)source(); + ByteBufUtil.copy(in, out); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;copy;(AsciiString,int,ByteBuf,int);;Argument[0];Argument[2];taint;manual" + ByteBuf out = null; + AsciiString in = (AsciiString)source(); + ByteBufUtil.copy(in, 0, out, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;copy;(AsciiString,int,ByteBuf,int,int);;Argument[0];Argument[2];taint;manual" + ByteBuf out = null; + AsciiString in = (AsciiString)source(); + ByteBufUtil.copy(in, 0, out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;decodeHexDump;(CharSequence);;Argument[0];ReturnValue;taint;manual" + byte[] out = null; + CharSequence in = (CharSequence)source(); + out = ByteBufUtil.decodeHexDump(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;decodeHexDump;(CharSequence,int,int);;Argument[0];ReturnValue;taint;manual" + byte[] out = null; + CharSequence in = (CharSequence)source(); + out = ByteBufUtil.decodeHexDump(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;encodeString;(ByteBufAllocator,CharBuffer,Charset);;Argument[1];ReturnValue;taint;manual" + ByteBuf out = null; + CharBuffer in = (CharBuffer)source(); + out = ByteBufUtil.encodeString(null, in, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;encodeString;(ByteBufAllocator,CharBuffer,Charset,int);;Argument[1];ReturnValue;taint;manual" + ByteBuf out = null; + CharBuffer in = (CharBuffer)source(); + out = ByteBufUtil.encodeString(null, in, null, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;ensureAccessible;(ByteBuf);;Argument[0];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = ByteBufUtil.ensureAccessible(in); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;getBytes;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + byte[] out = null; + ByteBuf in = (ByteBuf)source(); + out = ByteBufUtil.getBytes(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;getBytes;(ByteBuf,int,int);;Argument[0];ReturnValue;taint;manual" + byte[] out = null; + ByteBuf in = (ByteBuf)source(); + out = ByteBufUtil.getBytes(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;getBytes;(ByteBuf,int,int,boolean);;Argument[0];ReturnValue;taint;manual" + byte[] out = null; + ByteBuf in = (ByteBuf)source(); + out = ByteBufUtil.getBytes(in, 0, 0, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;readBytes;(ByteBufAllocator,ByteBuf,int);;Argument[1];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = ByteBufUtil.readBytes(null, in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;reserveAndWriteUtf8;(ByteBuf,CharSequence,int);;Argument[1];Argument[0];taint;manual" + ByteBuf out = null; + CharSequence in = (CharSequence)source(); + ByteBufUtil.reserveAndWriteUtf8(out, in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;reserveAndWriteUtf8;(ByteBuf,CharSequence,int,int,int);;Argument[1];Argument[0];taint;manual" + ByteBuf out = null; + CharSequence in = (CharSequence)source(); + ByteBufUtil.reserveAndWriteUtf8(out, in, 0, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;setShortBE;(ByteBuf,int,int);;Argument[0];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = ByteBufUtil.setShortBE(in, 0, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;writeAscii;(ByteBuf,CharSequence);;Argument[1];Argument[0];taint;manual" + ByteBuf out = null; + CharSequence in = (CharSequence)source(); + ByteBufUtil.writeAscii(out, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;writeAscii;(ByteBufAllocator,CharSequence);;Argument[1];ReturnValue;taint;manual" + ByteBuf out = null; + CharSequence in = (CharSequence)source(); + out = ByteBufUtil.writeAscii((ByteBufAllocator)null, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;writeMediumBE;(ByteBuf,int);;Argument[0];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = ByteBufUtil.writeMediumBE(in, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;writeShortBE;(ByteBuf,int);;Argument[0];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = ByteBufUtil.writeShortBE(in, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;writeUtf8;(ByteBuf,CharSequence);;Argument[1];Argument[0];taint;manual" + ByteBuf out = null; + CharSequence in = (CharSequence)source(); + ByteBufUtil.writeUtf8(out, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;writeUtf8;(ByteBuf,CharSequence,int,int);;Argument[1];Argument[0];taint;manual" + ByteBuf out = null; + CharSequence in = (CharSequence)source(); + ByteBufUtil.writeUtf8(out, in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;ByteBufUtil;false;writeUtf8;(ByteBufAllocator,CharSequence);;Argument[1];ReturnValue;taint;manual" + ByteBuf out = null; + CharSequence in = (CharSequence)source(); + out = ByteBufUtil.writeUtf8((ByteBufAllocator)null, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;false;CompositeByteBuf;(ByteBufAllocator,boolean,int,ByteBuf[]);;Argument[3].ArrayElement;Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuf[] in = (ByteBuf[])new ByteBuf[]{(ByteBuf)source()}; + out = new CompositeByteBuf((ByteBufAllocator)null, false, 0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;false;CompositeByteBuf;(ByteBufAllocator,boolean,int,Iterable);;Argument[3].Element;Argument[-1];taint;manual" + CompositeByteBuf out = null; + Iterable in = (Iterable)List.of(source()); + out = new CompositeByteBuf((ByteBufAllocator)null, false, 0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponent;(ByteBuf);;Argument[0];Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.addComponent(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponent;(boolean,ByteBuf);;Argument[1];Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.addComponent(false, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponent;(boolean,int,ByteBuf);;Argument[2];Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.addComponent(false, 0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponent;(int,ByteBuf);;Argument[1];Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.addComponent(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponent;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.addComponent(0, (ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponent;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.addComponent(false, (ByteBuf)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponent;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.addComponent(false, 0, null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponent;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.addComponent(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponents;(ByteBuf[]);;Argument[0].ArrayElement;Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuf[] in = (ByteBuf[])new ByteBuf[]{(ByteBuf)source()}; + out.addComponents(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponents;(Iterable);;Argument[0].Element;Argument[-1];taint;manual" + CompositeByteBuf out = null; + Iterable in = (Iterable)List.of(source()); + out.addComponents(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponents;(boolean,ByteBuf[]);;Argument[1].ArrayElement;Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuf[] in = (ByteBuf[])new ByteBuf[]{(ByteBuf)source()}; + out.addComponents(false, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponents;(boolean,Iterable);;Argument[1].Element;Argument[-1];taint;manual" + CompositeByteBuf out = null; + Iterable in = (Iterable)List.of(source()); + out.addComponents(false, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponents;(int,ByteBuf[]);;Argument[1].ArrayElement;Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuf[] in = (ByteBuf[])new ByteBuf[]{(ByteBuf)source()}; + out.addComponents(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponents;(int,Iterable);;Argument[1].Element;Argument[-1];taint;manual" + CompositeByteBuf out = null; + Iterable in = (Iterable)List.of(source()); + out.addComponents(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponents;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.addComponents((ByteBuf[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponents;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.addComponents((Iterable)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponents;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.addComponents(0, (ByteBuf[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponents;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.addComponents(0, (Iterable)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponents;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.addComponents(false, (ByteBuf[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addComponents;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.addComponents(false, (Iterable)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addFlattenedComponents;(boolean,ByteBuf);;Argument[1];Argument[-1];taint;manual" + CompositeByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out.addFlattenedComponents(false, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;addFlattenedComponents;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.addFlattenedComponents(false, null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;component;(int);;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.component(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;componentAtOffset;(int);;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.componentAtOffset(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;consolidate;();;Argument[-1];ReturnValue;taint;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.consolidate(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;consolidate;(int,int);;Argument[-1];ReturnValue;taint;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.consolidate(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;CompositeByteBuf;true;decompose;(int,int);;Argument[-1];ReturnValue.Element;taint;manual" + List out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.decompose(0, 0); + sink(getElement(out)); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;copiedBuffer;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Unpooled.copiedBuffer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;copiedBuffer;(ByteBuf[]);;Argument[0].ArrayElement;ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf[] in = (ByteBuf[])new ByteBuf[]{(ByteBuf)source()}; + out = Unpooled.copiedBuffer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;copiedBuffer;(ByteBuffer);;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuffer in = (ByteBuffer)source(); + out = Unpooled.copiedBuffer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;copiedBuffer;(ByteBuffer[]);;Argument[0].ArrayElement;ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuffer[] in = (ByteBuffer[])new ByteBuffer[]{(ByteBuffer)source()}; + out = Unpooled.copiedBuffer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;copiedBuffer;(CharSequence,Charset);;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + CharSequence in = (CharSequence)source(); + out = Unpooled.copiedBuffer(in, (Charset)null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;copiedBuffer;(CharSequence,int,int,Charset);;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + CharSequence in = (CharSequence)source(); + out = Unpooled.copiedBuffer(in, 0, 0, (Charset)null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;copiedBuffer;(byte[]);;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + byte[] in = (byte[])source(); + out = Unpooled.copiedBuffer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;copiedBuffer;(byte[],int,int);;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + byte[] in = (byte[])source(); + out = Unpooled.copiedBuffer(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;copiedBuffer;(byte[][]);;Argument[0].ArrayElement;ReturnValue;taint;manual" + ByteBuf out = null; + byte[][] in = (byte[][])new byte[][]{(byte[])source()}; + out = Unpooled.copiedBuffer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;copiedBuffer;(char[],Charset);;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + char[] in = (char[])source(); + out = Unpooled.copiedBuffer(in, (Charset)null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;copiedBuffer;(char[],int,int,Charset);;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + char[] in = (char[])source(); + out = Unpooled.copiedBuffer(in, 0, 0, (Charset)null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;unmodifiableBuffer;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Unpooled.unmodifiableBuffer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;unmodifiableBuffer;(ByteBuf[]);;Argument[0].ArrayElement;ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf[] in = (ByteBuf[])new ByteBuf[]{(ByteBuf)source()}; + out = Unpooled.unmodifiableBuffer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;unreleasableBuffer;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Unpooled.unreleasableBuffer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;wrappedBuffer;(ByteBuf);;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Unpooled.wrappedBuffer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;wrappedBuffer;(ByteBuf[]);;Argument[0].ArrayElement;ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf[] in = (ByteBuf[])new ByteBuf[]{(ByteBuf)source()}; + out = Unpooled.wrappedBuffer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;wrappedBuffer;(ByteBuffer);;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuffer in = (ByteBuffer)source(); + out = Unpooled.wrappedBuffer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;wrappedBuffer;(ByteBuffer[]);;Argument[0].ArrayElement;ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuffer[] in = (ByteBuffer[])new ByteBuffer[]{(ByteBuffer)source()}; + out = Unpooled.wrappedBuffer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;wrappedBuffer;(byte[]);;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + byte[] in = (byte[])source(); + out = Unpooled.wrappedBuffer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;wrappedBuffer;(byte[],int,int);;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + byte[] in = (byte[])source(); + out = Unpooled.wrappedBuffer(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;wrappedBuffer;(byte[][]);;Argument[0].ArrayElement;ReturnValue;taint;manual" + ByteBuf out = null; + byte[][] in = (byte[][])new byte[][]{(byte[])source()}; + out = Unpooled.wrappedBuffer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;wrappedBuffer;(int,ByteBuf[]);;Argument[1].ArrayElement;ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf[] in = (ByteBuf[])new ByteBuf[]{(ByteBuf)source()}; + out = Unpooled.wrappedBuffer(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;wrappedBuffer;(int,ByteBuffer[]);;Argument[1].ArrayElement;ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuffer[] in = (ByteBuffer[])new ByteBuffer[]{(ByteBuffer)source()}; + out = Unpooled.wrappedBuffer(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;wrappedBuffer;(int,byte[][]);;Argument[1].ArrayElement;ReturnValue;taint;manual" + ByteBuf out = null; + byte[][] in = (byte[][])new byte[][]{(byte[])source()}; + out = Unpooled.wrappedBuffer(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.buffer;Unpooled;false;wrappedUnmodifiableBuffer;(ByteBuf[]);;Argument[0].ArrayElement;ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf[] in = (ByteBuf[])new ByteBuf[]{(ByteBuf)source()}; + out = Unpooled.wrappedUnmodifiableBuffer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.base64;Base64;true;decode;;;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Base64.decode(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.base64;Base64;true;decode;;;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Base64.decode(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.base64;Base64;true;decode;;;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Base64.decode(in, 0, 0, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.base64;Base64;true;decode;;;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Base64.decode(in, 0, 0, null, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.base64;Base64;true;decode;;;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Base64.decode(in, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.base64;Base64;true;encode;;;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Base64.encode(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.base64;Base64;true;encode;;;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Base64.encode(in, (Base64Dialect)null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.base64;Base64;true;encode;;;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Base64.encode(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.base64;Base64;true;encode;;;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Base64.encode(in, 0, 0, (Base64Dialect)null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.base64;Base64;true;encode;;;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Base64.encode(in, 0, 0, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.base64;Base64;true;encode;;;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Base64.encode(in, 0, 0, false, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.base64;Base64;true;encode;;;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Base64.encode(in, 0, 0, false, null, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.base64;Base64;true;encode;;;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Base64.encode(in, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.base64;Base64;true;encode;;;Argument[0];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = Base64.encode(in, false, (Base64Dialect)null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;Cookie;true;domain;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + Cookie in = (Cookie)source(); + out = in.domain(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;Cookie;true;domain;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + DefaultCookie in = (DefaultCookie)source(); + out = in.domain(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;Cookie;true;name;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + Cookie in = (Cookie)source(); + out = in.name(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;Cookie;true;name;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + DefaultCookie in = (DefaultCookie)source(); + out = in.name(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;Cookie;true;path;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + Cookie in = (Cookie)source(); + out = in.path(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;Cookie;true;path;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + DefaultCookie in = (DefaultCookie)source(); + out = in.path(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;Cookie;true;setDomain;(String);;Argument[0];Argument[-1];taint;manual" + Cookie out = null; + String in = (String)source(); + out.setDomain(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;Cookie;true;setDomain;(String);;Argument[0];Argument[-1];taint;manual" + DefaultCookie out = null; + String in = (String)source(); + out.setDomain(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;Cookie;true;setPath;(String);;Argument[0];Argument[-1];taint;manual" + Cookie out = null; + String in = (String)source(); + out.setPath(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;Cookie;true;setPath;(String);;Argument[0];Argument[-1];taint;manual" + DefaultCookie out = null; + String in = (String)source(); + out.setPath(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;Cookie;true;setValue;(String);;Argument[0];Argument[-1];taint;manual" + Cookie out = null; + String in = (String)source(); + out.setValue(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;Cookie;true;setValue;(String);;Argument[0];Argument[-1];taint;manual" + DefaultCookie out = null; + String in = (String)source(); + out.setValue(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;Cookie;true;value;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + Cookie in = (Cookie)source(); + out = in.value(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;Cookie;true;value;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + DefaultCookie in = (DefaultCookie)source(); + out = in.value(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;ServerCookieDecoder;true;decode;(String);;Argument[0];ReturnValue.Element;taint;manual" + Set out = null; + String in = (String)source(); + ServerCookieDecoder instance = null; + out = instance.decode(in); + sink(getElement(out)); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;ServerCookieDecoder;true;decodeAll;(String);;Argument[0];ReturnValue.Element;taint;manual" + List out = null; + String in = (String)source(); + ServerCookieDecoder instance = null; + out = instance.decodeAll(in); + sink(getElement(out)); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;ServerCookieEncoder;true;encode;(Collection);;Argument[0].Element;ReturnValue.Element;taint;manual" + List out = null; + Collection in = (Collection)List.of(source()); + ServerCookieEncoder instance = null; + out = instance.encode(in); + sink(getElement(out)); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;ServerCookieEncoder;true;encode;(Cookie);;Argument[0];ReturnValue;taint;manual" + String out = null; + Cookie in = (Cookie)source(); + ServerCookieEncoder instance = null; + out = instance.encode(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;ServerCookieEncoder;true;encode;(Cookie[]);;Argument[0].ArrayElement;ReturnValue.Element;taint;manual" + List out = null; + Cookie[] in = (Cookie[])new Cookie[]{(Cookie)source()}; + ServerCookieEncoder instance = null; + out = instance.encode(in); + sink(getElement(out)); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;ServerCookieEncoder;true;encode;(Iterable);;Argument[0].Element;ReturnValue.Element;taint;manual" + List out = null; + Iterable in = (Iterable)List.of(source()); + ServerCookieEncoder instance = null; + out = instance.encode(in); + sink(getElement(out)); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.cookie;ServerCookieEncoder;true;encode;(String,String);;Argument[1..2];ReturnValue;taint;manual" + String out = null; + String in = (String)source(); + ServerCookieEncoder instance = null; + out = instance.encode(null, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;Attribute;true;getValue;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + Attribute in = (Attribute)source(); + out = in.getValue(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;Attribute;true;setValue;(String);;Argument[0];Argument[-1];taint;manual" + Attribute out = null; + String in = (String)source(); + out.setValue(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;FileUpload;true;getContentTransferEncoding;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + FileUpload in = (FileUpload)source(); + out = in.getContentTransferEncoding(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;FileUpload;true;getContentType;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + FileUpload in = (FileUpload)source(); + out = in.getContentType(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;FileUpload;true;getFilename;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + FileUpload in = (FileUpload)source(); + out = in.getFilename(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;FileUpload;true;setContentTransferEncoding;(String);;Argument[0];Argument[-1];taint;manual" + FileUpload out = null; + String in = (String)source(); + out.setContentTransferEncoding(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;FileUpload;true;setContentType;(String);;Argument[0];Argument[-1];taint;manual" + FileUpload out = null; + String in = (String)source(); + out.setContentType(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;FileUpload;true;setFilename;(String);;Argument[0];Argument[-1];taint;manual" + FileUpload out = null; + String in = (String)source(); + out.setFilename(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpData;true;addContent;(ByteBuf,boolean);;Argument[0];Argument[-1];taint;manual" + HttpData out = null; + ByteBuf in = (ByteBuf)source(); + out.addContent(in, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpData;true;get;();;Argument[-1];ReturnValue;taint;manual" + byte[] out = null; + HttpData in = (HttpData)source(); + out = in.get(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpData;true;getByteBuf;();;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + HttpData in = (HttpData)source(); + out = in.getByteBuf(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpData;true;getChunk;(int);;Argument[-1];ReturnValue;taint;manual" + ByteBuf out = null; + HttpData in = (HttpData)source(); + out = in.getChunk(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpData;true;getString;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + HttpData in = (HttpData)source(); + out = in.getString(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpData;true;getString;(Charset);;Argument[-1];ReturnValue;taint;manual" + String out = null; + HttpData in = (HttpData)source(); + out = in.getString(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpData;true;setContent;(ByteBuf);;Argument[0];Argument[-1];taint;manual" + HttpData out = null; + ByteBuf in = (ByteBuf)source(); + out.setContent(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpData;true;setContent;(InputStream);;Argument[0];Argument[-1];taint;manual" + HttpData out = null; + InputStream in = (InputStream)source(); + out.setContent(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpPostMultipartRequestDecoder;true;HttpPostMultipartRequestDecoder;(HttpDataFactory,HttpRequest);;Argument[1];Argument[-1];taint;manual" + HttpPostMultipartRequestDecoder out = null; + HttpRequest in = (HttpRequest)source(); + out = new HttpPostMultipartRequestDecoder(null, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpPostMultipartRequestDecoder;true;HttpPostMultipartRequestDecoder;(HttpDataFactory,HttpRequest,Charset);;Argument[1];Argument[-1];taint;manual" + HttpPostMultipartRequestDecoder out = null; + HttpRequest in = (HttpRequest)source(); + out = new HttpPostMultipartRequestDecoder(null, in, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpPostMultipartRequestDecoder;true;HttpPostMultipartRequestDecoder;(HttpRequest);;Argument[0];Argument[-1];taint;manual" + HttpPostMultipartRequestDecoder out = null; + HttpRequest in = (HttpRequest)source(); + out = new HttpPostMultipartRequestDecoder(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpPostRequestDecoder;true;HttpPostRequestDecoder;(HttpDataFactory,HttpRequest);;Argument[1];Argument[-1];taint;manual" + HttpPostRequestDecoder out = null; + HttpRequest in = (HttpRequest)source(); + out = new HttpPostRequestDecoder(null, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpPostRequestDecoder;true;HttpPostRequestDecoder;(HttpDataFactory,HttpRequest,Charset);;Argument[1];Argument[-1];taint;manual" + HttpPostRequestDecoder out = null; + HttpRequest in = (HttpRequest)source(); + out = new HttpPostRequestDecoder(null, in, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpPostRequestDecoder;true;HttpPostRequestDecoder;(HttpRequest);;Argument[0];Argument[-1];taint;manual" + HttpPostRequestDecoder out = null; + HttpRequest in = (HttpRequest)source(); + out = new HttpPostRequestDecoder(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpPostStandardRequestDecoder;true;HttpPostStandardRequestDecoder;(HttpDataFactory,HttpRequest);;Argument[1];Argument[-1];taint;manual" + HttpPostStandardRequestDecoder out = null; + HttpRequest in = (HttpRequest)source(); + out = new HttpPostStandardRequestDecoder(null, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpPostStandardRequestDecoder;true;HttpPostStandardRequestDecoder;(HttpDataFactory,HttpRequest,Charset);;Argument[1];Argument[-1];taint;manual" + HttpPostStandardRequestDecoder out = null; + HttpRequest in = (HttpRequest)source(); + out = new HttpPostStandardRequestDecoder(null, in, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;HttpPostStandardRequestDecoder;true;HttpPostStandardRequestDecoder;(HttpRequest);;Argument[0];Argument[-1];taint;manual" + HttpPostStandardRequestDecoder out = null; + HttpRequest in = (HttpRequest)source(); + out = new HttpPostStandardRequestDecoder(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpData;true;getName;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + InterfaceHttpData in = (InterfaceHttpData)source(); + out = in.getName(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;currentPartialHttpData;();;Argument[-1];ReturnValue;taint;manual" + InterfaceHttpData out = null; + HttpPostMultipartRequestDecoder in = (HttpPostMultipartRequestDecoder)source(); + out = in.currentPartialHttpData(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;currentPartialHttpData;();;Argument[-1];ReturnValue;taint;manual" + InterfaceHttpData out = null; + HttpPostRequestDecoder in = (HttpPostRequestDecoder)source(); + out = in.currentPartialHttpData(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;currentPartialHttpData;();;Argument[-1];ReturnValue;taint;manual" + InterfaceHttpData out = null; + HttpPostStandardRequestDecoder in = (HttpPostStandardRequestDecoder)source(); + out = in.currentPartialHttpData(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;currentPartialHttpData;();;Argument[-1];ReturnValue;taint;manual" + InterfaceHttpData out = null; + InterfaceHttpPostRequestDecoder in = (InterfaceHttpPostRequestDecoder)source(); + out = in.currentPartialHttpData(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;getBodyHttpData;(String);;Argument[-1];ReturnValue;taint;manual" + InterfaceHttpData out = null; + HttpPostMultipartRequestDecoder in = (HttpPostMultipartRequestDecoder)source(); + out = in.getBodyHttpData(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;getBodyHttpData;(String);;Argument[-1];ReturnValue;taint;manual" + InterfaceHttpData out = null; + HttpPostRequestDecoder in = (HttpPostRequestDecoder)source(); + out = in.getBodyHttpData(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;getBodyHttpData;(String);;Argument[-1];ReturnValue;taint;manual" + InterfaceHttpData out = null; + HttpPostStandardRequestDecoder in = (HttpPostStandardRequestDecoder)source(); + out = in.getBodyHttpData(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;getBodyHttpData;(String);;Argument[-1];ReturnValue;taint;manual" + InterfaceHttpData out = null; + InterfaceHttpPostRequestDecoder in = (InterfaceHttpPostRequestDecoder)source(); + out = in.getBodyHttpData(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;getBodyHttpDatas;();;Argument[-1];ReturnValue;taint;manual" + List out = null; + HttpPostMultipartRequestDecoder in = (HttpPostMultipartRequestDecoder)source(); + out = in.getBodyHttpDatas(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;getBodyHttpDatas;();;Argument[-1];ReturnValue;taint;manual" + List out = null; + HttpPostRequestDecoder in = (HttpPostRequestDecoder)source(); + out = in.getBodyHttpDatas(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;getBodyHttpDatas;();;Argument[-1];ReturnValue;taint;manual" + List out = null; + HttpPostStandardRequestDecoder in = (HttpPostStandardRequestDecoder)source(); + out = in.getBodyHttpDatas(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;getBodyHttpDatas;();;Argument[-1];ReturnValue;taint;manual" + List out = null; + InterfaceHttpPostRequestDecoder in = (InterfaceHttpPostRequestDecoder)source(); + out = in.getBodyHttpDatas(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;getBodyHttpDatas;(String);;Argument[-1];ReturnValue;taint;manual" + List out = null; + HttpPostMultipartRequestDecoder in = (HttpPostMultipartRequestDecoder)source(); + out = in.getBodyHttpDatas(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;getBodyHttpDatas;(String);;Argument[-1];ReturnValue;taint;manual" + List out = null; + HttpPostRequestDecoder in = (HttpPostRequestDecoder)source(); + out = in.getBodyHttpDatas(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;getBodyHttpDatas;(String);;Argument[-1];ReturnValue;taint;manual" + List out = null; + HttpPostStandardRequestDecoder in = (HttpPostStandardRequestDecoder)source(); + out = in.getBodyHttpDatas(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;getBodyHttpDatas;(String);;Argument[-1];ReturnValue;taint;manual" + List out = null; + InterfaceHttpPostRequestDecoder in = (InterfaceHttpPostRequestDecoder)source(); + out = in.getBodyHttpDatas(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;next;();;Argument[-1];ReturnValue;taint;manual" + InterfaceHttpData out = null; + HttpPostMultipartRequestDecoder in = (HttpPostMultipartRequestDecoder)source(); + out = in.next(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;next;();;Argument[-1];ReturnValue;taint;manual" + InterfaceHttpData out = null; + HttpPostRequestDecoder in = (HttpPostRequestDecoder)source(); + out = in.next(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;next;();;Argument[-1];ReturnValue;taint;manual" + InterfaceHttpData out = null; + HttpPostStandardRequestDecoder in = (HttpPostStandardRequestDecoder)source(); + out = in.next(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;next;();;Argument[-1];ReturnValue;taint;manual" + InterfaceHttpData out = null; + InterfaceHttpPostRequestDecoder in = (InterfaceHttpPostRequestDecoder)source(); + out = in.next(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;offer;(HttpContent);;Argument[-1];ReturnValue;value;manual" + HttpPostMultipartRequestDecoder out = null; + HttpPostMultipartRequestDecoder in = (HttpPostMultipartRequestDecoder)source(); + out = in.offer(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;offer;(HttpContent);;Argument[-1];ReturnValue;value;manual" + HttpPostStandardRequestDecoder out = null; + HttpPostStandardRequestDecoder in = (HttpPostStandardRequestDecoder)source(); + out = in.offer(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;offer;(HttpContent);;Argument[-1];ReturnValue;value;manual" + InterfaceHttpPostRequestDecoder out = null; + HttpPostRequestDecoder in = (HttpPostRequestDecoder)source(); + out = in.offer(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;offer;(HttpContent);;Argument[-1];ReturnValue;value;manual" + InterfaceHttpPostRequestDecoder out = null; + InterfaceHttpPostRequestDecoder in = (InterfaceHttpPostRequestDecoder)source(); + out = in.offer(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;offer;(HttpContent);;Argument[0];Argument[-1];taint;manual" + HttpPostMultipartRequestDecoder out = null; + HttpContent in = (HttpContent)source(); + out.offer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;offer;(HttpContent);;Argument[0];Argument[-1];taint;manual" + HttpPostRequestDecoder out = null; + HttpContent in = (HttpContent)source(); + out.offer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;offer;(HttpContent);;Argument[0];Argument[-1];taint;manual" + HttpPostStandardRequestDecoder out = null; + HttpContent in = (HttpContent)source(); + out.offer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.multipart;InterfaceHttpPostRequestDecoder;true;offer;(HttpContent);;Argument[0];Argument[-1];taint;manual" + InterfaceHttpPostRequestDecoder out = null; + HttpContent in = (HttpContent)source(); + out.offer(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;BinaryWebSocketFrame;true;BinaryWebSocketFrame;(ByteBuf);;Argument[0];Argument[-1];taint;manual" + BinaryWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + out = new BinaryWebSocketFrame(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;BinaryWebSocketFrame;true;BinaryWebSocketFrame;(boolean,int,ByteBuf);;Argument[2];Argument[-1];taint;manual" + BinaryWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + out = new BinaryWebSocketFrame(false, 0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;CloseWebSocketFrame;true;CloseWebSocketFrame;(WebSocketCloseStatus,String);;Argument[1];Argument[-1];taint;manual" + CloseWebSocketFrame out = null; + String in = (String)source(); + out = new CloseWebSocketFrame((WebSocketCloseStatus)null, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;CloseWebSocketFrame;true;CloseWebSocketFrame;(boolean,int,ByteBuf);;Argument[2];Argument[-1];taint;manual" + CloseWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + out = new CloseWebSocketFrame(false, 0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;CloseWebSocketFrame;true;CloseWebSocketFrame;(boolean,int,int,String);;Argument[3];Argument[-1];taint;manual" + CloseWebSocketFrame out = null; + String in = (String)source(); + out = new CloseWebSocketFrame(false, 0, 0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;CloseWebSocketFrame;true;CloseWebSocketFrame;(int,String);;Argument[1];Argument[-1];taint;manual" + CloseWebSocketFrame out = null; + String in = (String)source(); + out = new CloseWebSocketFrame(0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;CloseWebSocketFrame;true;reasonText;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + CloseWebSocketFrame in = (CloseWebSocketFrame)source(); + out = in.reasonText(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;ContinuationWebSocketFrame;true;ContinuationWebSocketFrame;(ByteBuf);;Argument[0];Argument[-1];taint;manual" + ContinuationWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + out = new ContinuationWebSocketFrame(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;ContinuationWebSocketFrame;true;ContinuationWebSocketFrame;(boolean,int,ByteBuf);;Argument[2];Argument[-1];taint;manual" + ContinuationWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + out = new ContinuationWebSocketFrame(false, 0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;ContinuationWebSocketFrame;true;ContinuationWebSocketFrame;(boolean,int,String);;Argument[2];Argument[-1];taint;manual" + ContinuationWebSocketFrame out = null; + String in = (String)source(); + out = new ContinuationWebSocketFrame(false, 0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;ContinuationWebSocketFrame;true;text;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + ContinuationWebSocketFrame in = (ContinuationWebSocketFrame)source(); + out = in.text(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;PingWebSocketFrame;true;PingWebSocketFrame;(ByteBuf);;Argument[0];Argument[-1];taint;manual" + PingWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + out = new PingWebSocketFrame(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;PingWebSocketFrame;true;PingWebSocketFrame;(boolean,int,ByteBuf);;Argument[2];Argument[-1];taint;manual" + PingWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + out = new PingWebSocketFrame(false, 0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;PongWebSocketFrame;true;PongWebSocketFrame;(ByteBuf);;Argument[0];Argument[-1];taint;manual" + PongWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + out = new PongWebSocketFrame(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;PongWebSocketFrame;true;PongWebSocketFrame;(boolean,int,ByteBuf);;Argument[2];Argument[-1];taint;manual" + PongWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + out = new PongWebSocketFrame(false, 0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;TextWebSocketFrame;true;TextWebSocketFrame;(ByteBuf);;Argument[0];Argument[-1];taint;manual" + TextWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + out = new TextWebSocketFrame(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;TextWebSocketFrame;true;TextWebSocketFrame;(String);;Argument[0];Argument[-1];taint;manual" + TextWebSocketFrame out = null; + String in = (String)source(); + out = new TextWebSocketFrame(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;TextWebSocketFrame;true;TextWebSocketFrame;(boolean,int,ByteBuf);;Argument[2];Argument[-1];taint;manual" + TextWebSocketFrame out = null; + ByteBuf in = (ByteBuf)source(); + out = new TextWebSocketFrame(false, 0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;TextWebSocketFrame;true;TextWebSocketFrame;(boolean,int,String);;Argument[2];Argument[-1];taint;manual" + TextWebSocketFrame out = null; + String in = (String)source(); + out = new TextWebSocketFrame(false, 0, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http.websocketx;TextWebSocketFrame;true;text;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + TextWebSocketFrame in = (TextWebSocketFrame)source(); + out = in.text(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;Http2Headers;true;authority;();;Argument[-1].Element.MapValue;ReturnValue;value;manual" + CharSequence out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = in.authority(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http2;Http2Headers;true;authority;(CharSequence);;Argument[-1];ReturnValue;value;manual" + Http2Headers out = null; + Http2Headers in = (Http2Headers)source(); + out = in.authority(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http2;Http2Headers;true;authority;(CharSequence);;Argument[0];Argument[-1].Element.MapValue;value;manual" + Http2Headers out = null; + CharSequence in = (CharSequence)source(); + out.authority(in); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http2;Http2Headers;true;method;();;Argument[-1].Element.MapValue;ReturnValue;value;manual" + CharSequence out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = in.method(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http2;Http2Headers;true;method;(CharSequence);;Argument[-1];ReturnValue;value;manual" + Http2Headers out = null; + Http2Headers in = (Http2Headers)source(); + out = in.method(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http2;Http2Headers;true;method;(CharSequence);;Argument[0];Argument[-1].Element.MapValue;value;manual" + Http2Headers out = null; + CharSequence in = (CharSequence)source(); + out.method(in); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http2;Http2Headers;true;path;();;Argument[-1].Element.MapValue;ReturnValue;value;manual" + CharSequence out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = in.path(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http2;Http2Headers;true;path;(CharSequence);;Argument[-1];ReturnValue;value;manual" + Http2Headers out = null; + Http2Headers in = (Http2Headers)source(); + out = in.path(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http2;Http2Headers;true;path;(CharSequence);;Argument[0];Argument[-1].Element.MapValue;value;manual" + Http2Headers out = null; + CharSequence in = (CharSequence)source(); + out.path(in); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http2;Http2Headers;true;scheme;();;Argument[-1].Element.MapValue;ReturnValue;value;manual" + CharSequence out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = in.scheme(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http2;Http2Headers;true;scheme;(CharSequence);;Argument[-1];ReturnValue;value;manual" + Http2Headers out = null; + Http2Headers in = (Http2Headers)source(); + out = in.scheme(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http2;Http2Headers;true;scheme;(CharSequence);;Argument[0];Argument[-1].Element.MapValue;value;manual" + Http2Headers out = null; + CharSequence in = (CharSequence)source(); + out.scheme(in); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http2;Http2Headers;true;status;();;Argument[-1].Element.MapValue;ReturnValue;value;manual" + CharSequence out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = in.status(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http2;Http2Headers;true;status;(CharSequence);;Argument[-1];ReturnValue;value;manual" + Http2Headers out = null; + Http2Headers in = (Http2Headers)source(); + out = in.status(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http2;Http2Headers;true;status;(CharSequence);;Argument[0];Argument[-1].Element.MapValue;value;manual" + Http2Headers out = null; + CharSequence in = (CharSequence)source(); + out.status(in); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http2;Http2Headers;true;valueIterator;(CharSequence);;Argument[-1].Element.MapValue;ReturnValue.Element;value;manual" + Iterator out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = in.valueIterator(null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http2;Http2HeadersFrame;true;headers;();;Argument[-1];ReturnValue;taint;manual" + Http2Headers out = null; + Http2HeadersFrame in = (Http2HeadersFrame)source(); + out = in.headers(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;Http2PushPromiseFrame;true;http2Headers;();;Argument[-1];ReturnValue;taint;manual" + Http2Headers out = null; + Http2PushPromiseFrame in = (Http2PushPromiseFrame)source(); + out = in.http2Headers(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;addHttp2ToHttpHeaders;(int,Http2Headers,FullHttpMessage,boolean);;Argument[1].Element.MapKey;Argument[2];taint;manual" + FullHttpMessage out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapKeyDefault(source())); + HttpConversionUtil.addHttp2ToHttpHeaders(0, in, out, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;addHttp2ToHttpHeaders;(int,Http2Headers,FullHttpMessage,boolean);;Argument[1].Element.MapValue;Argument[2];taint;manual" + FullHttpMessage out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapValueDefault(source())); + HttpConversionUtil.addHttp2ToHttpHeaders(0, in, out, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;addHttp2ToHttpHeaders;(int,Http2Headers,HttpHeaders,HttpVersion,boolean,boolean);;Argument[1].Element.MapKey;Argument[2].Element.MapKey;taint;manual" + HttpHeaders out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapKeyDefault(source())); + HttpConversionUtil.addHttp2ToHttpHeaders(0, in, out, null, false, false); + sink(getMapKeyDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;addHttp2ToHttpHeaders;(int,Http2Headers,HttpHeaders,HttpVersion,boolean,boolean);;Argument[1].Element.MapValue;Argument[2].Element.MapValue;taint;manual" + HttpHeaders out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapValueDefault(source())); + HttpConversionUtil.addHttp2ToHttpHeaders(0, in, out, null, false, false); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toFullHttpRequest;(int,Http2Headers,ByteBuf,boolean);;Argument[2];ReturnValue;taint;manual" + FullHttpRequest out = null; + ByteBuf in = (ByteBuf)source(); + out = HttpConversionUtil.toFullHttpRequest(0, (Http2Headers)null, in, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toFullHttpRequest;;;Argument[1].Element.MapKey;ReturnValue;taint;manual" + FullHttpRequest out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapKeyDefault(source())); + out = HttpConversionUtil.toFullHttpRequest(0, in, (ByteBuf)null, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toFullHttpRequest;;;Argument[1].Element.MapKey;ReturnValue;taint;manual" + FullHttpRequest out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapKeyDefault(source())); + out = HttpConversionUtil.toFullHttpRequest(0, in, (ByteBufAllocator)null, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toFullHttpRequest;;;Argument[1].Element.MapValue;ReturnValue;taint;manual" + FullHttpRequest out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = HttpConversionUtil.toFullHttpRequest(0, in, (ByteBuf)null, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toFullHttpRequest;;;Argument[1].Element.MapValue;ReturnValue;taint;manual" + FullHttpRequest out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = HttpConversionUtil.toFullHttpRequest(0, in, (ByteBufAllocator)null, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toFullHttpResponse;(int,Http2Headers,ByteBuf,boolean);;Argument[2];ReturnValue;taint;manual" + FullHttpResponse out = null; + ByteBuf in = (ByteBuf)source(); + out = HttpConversionUtil.toFullHttpResponse(0, (Http2Headers)null, in, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toFullHttpResponse;;;Argument[1].Element.MapKey;ReturnValue;taint;manual" + FullHttpResponse out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapKeyDefault(source())); + out = HttpConversionUtil.toFullHttpResponse(0, in, (ByteBuf)null, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toFullHttpResponse;;;Argument[1].Element.MapKey;ReturnValue;taint;manual" + FullHttpResponse out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapKeyDefault(source())); + out = HttpConversionUtil.toFullHttpResponse(0, in, (ByteBufAllocator)null, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toFullHttpResponse;;;Argument[1].Element.MapValue;ReturnValue;taint;manual" + FullHttpResponse out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = HttpConversionUtil.toFullHttpResponse(0, in, (ByteBuf)null, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toFullHttpResponse;;;Argument[1].Element.MapValue;ReturnValue;taint;manual" + FullHttpResponse out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = HttpConversionUtil.toFullHttpResponse(0, in, (ByteBufAllocator)null, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toHttp2Headers;(HttpHeaders,Http2Headers);;Argument[0].Element.MapKey;Argument[1].Element.MapKey;taint;manual" + Http2Headers out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapKeyDefault(source())); + HttpConversionUtil.toHttp2Headers(in, out); + sink(getMapKeyDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toHttp2Headers;(HttpHeaders,Http2Headers);;Argument[0].Element.MapValue;Argument[1].Element.MapValue;taint;manual" + Http2Headers out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + HttpConversionUtil.toHttp2Headers(in, out); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toHttp2Headers;(HttpHeaders,boolean);;Argument[0].Element.MapKey;ReturnValue.Element.MapKey;taint;manual" + Http2Headers out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapKeyDefault(source())); + out = HttpConversionUtil.toHttp2Headers(in, false); + sink(getMapKeyDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toHttp2Headers;(HttpHeaders,boolean);;Argument[0].Element.MapValue;ReturnValue.Element.MapValue;taint;manual" + Http2Headers out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out = HttpConversionUtil.toHttp2Headers(in, false); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toHttpRequest;;;Argument[1].Element.MapKey;ReturnValue;taint;manual" + HttpRequest out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapKeyDefault(source())); + out = HttpConversionUtil.toHttpRequest(0, in, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toHttpRequest;;;Argument[1].Element.MapValue;ReturnValue;taint;manual" + HttpRequest out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = HttpConversionUtil.toHttpRequest(0, in, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toHttpResponse;;;Argument[1].Element.MapKey;ReturnValue;taint;manual" + HttpResponse out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapKeyDefault(source())); + out = HttpConversionUtil.toHttpResponse(0, in, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http2;HttpConversionUtil;false;toHttpResponse;;;Argument[1].Element.MapValue;ReturnValue;taint;manual" + HttpResponse out = null; + Http2Headers in = (Http2Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = HttpConversionUtil.toHttpResponse(0, in, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;add;(CharSequence,Iterable);;Argument[0];Argument[-1].Element.MapKey;taint;manual" + HttpHeaders out = null; + CharSequence in = (CharSequence)source(); + out.add(in, (Iterable)null); + sink(getMapKeyDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;add;(CharSequence,Iterable);;Argument[1].Element;Argument[-1].Element.MapValue;taint;manual" + HttpHeaders out = null; + Iterable in = (Iterable)List.of(source()); + out.add((CharSequence)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;add;(CharSequence,Object);;Argument[0];Argument[-1].Element.MapKey;taint;manual" + HttpHeaders out = null; + CharSequence in = (CharSequence)source(); + out.add(in, (Object)null); + sink(getMapKeyDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;add;(CharSequence,Object);;Argument[1];Argument[-1].Element.MapValue;taint;manual" + HttpHeaders out = null; + Object in = (Object)source(); + out.add((CharSequence)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;add;(HttpHeaders);;Argument[0].Element.MapKey;Argument[-1].Element.MapKey;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapKeyDefault(source())); + out.add(in); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;add;(HttpHeaders);;Argument[0].Element.MapValue;Argument[-1].Element.MapValue;taint;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out.add(in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;add;(String,Iterable);;Argument[0];Argument[-1].Element.MapKey;value;manual" + HttpHeaders out = null; + String in = (String)source(); + out.add(in, (Iterable)null); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;add;(String,Iterable);;Argument[1].Element;Argument[-1].Element.MapValue;taint;manual" + HttpHeaders out = null; + Iterable in = (Iterable)List.of(source()); + out.add((String)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;add;(String,Object);;Argument[0];Argument[-1].Element.MapKey;value;manual" + HttpHeaders out = null; + String in = (String)source(); + out.add(in, (Object)null); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;add;(String,Object);;Argument[1];Argument[-1].Element.MapValue;taint;manual" + HttpHeaders out = null; + Object in = (Object)source(); + out.add((String)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;add;;;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.add((CharSequence)null, (Iterable)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;add;;;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.add((CharSequence)null, (Object)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;add;;;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.add((String)null, (Iterable)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;add;;;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.add((String)null, (Object)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;add;;;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.add(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;addInt;(CharSequence,int);;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.addInt(null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;addInt;(CharSequence,int);;Argument[0];Argument[-1].Element.MapKey;value;manual" + HttpHeaders out = null; + CharSequence in = (CharSequence)source(); + out.addInt(in, 0); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;addShort;(CharSequence,short);;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.addShort(null, (short)0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;addShort;(CharSequence,short);;Argument[0];Argument[-1].Element.MapKey;value;manual" + HttpHeaders out = null; + CharSequence in = (CharSequence)source(); + out.addShort(in, (short)0); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;copy;();;Argument[-1].Element.MapKey;ReturnValue.Element.MapKey;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapKeyDefault(source())); + out = in.copy(); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;copy;();;Argument[-1].Element.MapValue;ReturnValue.Element.MapValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out = in.copy(); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;entries;();;Argument[-1].Element.MapKey;ReturnValue.Element.MapKey;value;manual" + List out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapKeyDefault(source())); + out = in.entries(); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;entries;();;Argument[-1].Element.MapValue;ReturnValue.Element.MapValue;value;manual" + List out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out = in.entries(); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;get;;;Argument[-1].Element.MapValue;ReturnValue;value;manual" + String out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out = in.get((CharSequence)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;get;;;Argument[-1].Element.MapValue;ReturnValue;value;manual" + String out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out = in.get((String)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;get;;;Argument[-1].Element.MapValue;ReturnValue;value;manual" + String out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out = in.get(null, null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;get;;;Argument[1];ReturnValue;value;manual" + String out = null; + String in = (String)source(); + HttpHeaders instance = null; + out = instance.get(null, in); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;getAll;;;Argument[-1].Element.MapValue;ReturnValue.Element;value;manual" + List out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out = in.getAll((CharSequence)null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;getAll;;;Argument[-1].Element.MapValue;ReturnValue.Element;value;manual" + List out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out = in.getAll((String)null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;getAllAsString;;;Argument[-1].Element.MapValue;ReturnValue.Element;value;manual" + List out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out = in.getAllAsString(null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;getAsString;;;Argument[-1].Element.MapValue;ReturnValue;value;manual" + String out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out = in.getAsString(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;getHeader;;;Argument[0];ReturnValue;taint;manual" + String out = null; + HttpMessage in = (HttpMessage)source(); + out = HttpHeaders.getHeader(in, (CharSequence)null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;getHeader;;;Argument[0];ReturnValue;taint;manual" + String out = null; + HttpMessage in = (HttpMessage)source(); + out = HttpHeaders.getHeader(in, (CharSequence)null, (String)null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;getHeader;;;Argument[0];ReturnValue;taint;manual" + String out = null; + HttpMessage in = (HttpMessage)source(); + out = HttpHeaders.getHeader(in, (String)null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;getHeader;;;Argument[0];ReturnValue;taint;manual" + String out = null; + HttpMessage in = (HttpMessage)source(); + out = HttpHeaders.getHeader(in, (String)null, (String)null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;getHeader;;;Argument[2];ReturnValue;value;manual" + String out = null; + String in = (String)source(); + out = HttpHeaders.getHeader((HttpMessage)null, (CharSequence)null, in); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;getHeader;;;Argument[2];ReturnValue;value;manual" + String out = null; + String in = (String)source(); + out = HttpHeaders.getHeader((HttpMessage)null, (String)null, in); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;getHost;;;Argument[0];ReturnValue;taint;manual" + String out = null; + HttpMessage in = (HttpMessage)source(); + out = HttpHeaders.getHost(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;getHost;;;Argument[0];ReturnValue;taint;manual" + String out = null; + HttpMessage in = (HttpMessage)source(); + out = HttpHeaders.getHost(in, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;getHost;;;Argument[1];ReturnValue;value;manual" + String out = null; + String in = (String)source(); + out = HttpHeaders.getHost(null, in); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;iteratorAsString;();;Argument[-1].Element.MapKey;ReturnValue.Element.MapKey;value;manual" + Iterator out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapKeyDefault(source())); + out = in.iteratorAsString(); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;iteratorAsString;();;Argument[-1].Element.MapValue;ReturnValue.Element.MapValue;value;manual" + Iterator out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out = in.iteratorAsString(); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;iteratorCharSequence;();;Argument[-1].Element.MapKey;ReturnValue.Element.MapKey;taint;manual" + Iterator out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapKeyDefault(source())); + out = in.iteratorCharSequence(); + sink(getMapKeyDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;iteratorCharSequence;();;Argument[-1].Element.MapValue;ReturnValue.Element.MapValue;taint;manual" + Iterator out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out = in.iteratorCharSequence(); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;names;();;Argument[-1].Element.MapKey;ReturnValue.Element;value;manual" + Set out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapKeyDefault(source())); + out = in.names(); + sink(getElement(out)); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;newEntity;;;Argument[0];ReturnValue;taint;manual" + CharSequence out = null; + String in = (String)source(); + out = HttpHeaders.newEntity(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;remove;;;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.remove((CharSequence)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;remove;;;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.remove((String)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;set;(CharSequence,Iterable);;Argument[0];Argument[-1].Element.MapKey;taint;manual" + HttpHeaders out = null; + CharSequence in = (CharSequence)source(); + out.set(in, (Iterable)null); + sink(getMapKeyDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;set;(CharSequence,Iterable);;Argument[1].Element;Argument[-1].Element.MapValue;taint;manual" + HttpHeaders out = null; + Iterable in = (Iterable)List.of(source()); + out.set((CharSequence)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;set;(CharSequence,Object);;Argument[0];Argument[-1].Element.MapKey;taint;manual" + HttpHeaders out = null; + CharSequence in = (CharSequence)source(); + out.set(in, (Object)null); + sink(getMapKeyDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;set;(CharSequence,Object);;Argument[1];Argument[-1].Element.MapValue;taint;manual" + HttpHeaders out = null; + Object in = (Object)source(); + out.set((CharSequence)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;set;(HttpHeaders);;Argument[0].Element.MapKey;Argument[-1].Element.MapKey;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapKeyDefault(source())); + out.set(in); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;set;(HttpHeaders);;Argument[0].Element.MapValue;Argument[-1].Element.MapValue;taint;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out.set(in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;set;(String,Iterable);;Argument[0];Argument[-1].Element.MapKey;value;manual" + HttpHeaders out = null; + String in = (String)source(); + out.set(in, (Iterable)null); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;set;(String,Iterable);;Argument[1].Element;Argument[-1].Element.MapValue;taint;manual" + HttpHeaders out = null; + Iterable in = (Iterable)List.of(source()); + out.set((String)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;set;(String,Object);;Argument[0];Argument[-1].Element.MapKey;value;manual" + HttpHeaders out = null; + String in = (String)source(); + out.set(in, (Object)null); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;set;(String,Object);;Argument[1];Argument[-1].Element.MapValue;taint;manual" + HttpHeaders out = null; + Object in = (Object)source(); + out.set((String)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;set;;;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.set((CharSequence)null, (Iterable)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;set;;;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.set((CharSequence)null, (Object)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;set;;;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.set((String)null, (Iterable)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;set;;;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.set((String)null, (Object)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;set;;;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.set(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;setAll;(HttpHeaders);;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.setAll(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;setAll;(HttpHeaders);;Argument[0].Element.MapKey;Argument[-1].Element.MapKey;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapKeyDefault(source())); + out.setAll(in); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;setAll;(HttpHeaders);;Argument[0].Element.MapValue;Argument[-1].Element.MapValue;taint;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out.setAll(in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;setInt;(CharSequence,int);;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.setInt(null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;setInt;(CharSequence,int);;Argument[0];Argument[-1].Element.MapKey;value;manual" + HttpHeaders out = null; + CharSequence in = (CharSequence)source(); + out.setInt(in, 0); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;setShort;(CharSequence,short);;Argument[-1];ReturnValue;value;manual" + HttpHeaders out = null; + HttpHeaders in = (HttpHeaders)source(); + out = in.setShort(null, (short)0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;setShort;(CharSequence,short);;Argument[0];Argument[-1].Element.MapKey;value;manual" + HttpHeaders out = null; + CharSequence in = (CharSequence)source(); + out.setShort(in, (short)0); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;toString;;;Argument[-1].Element.MapKey;ReturnValue;taint;manual" + String out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapKeyDefault(source())); + out = in.toString(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;toString;;;Argument[-1].Element.MapValue;ReturnValue;taint;manual" + String out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out = in.toString(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;valueCharSequenceIterator;(CharSequence);;Argument[-1].Element.MapValue;ReturnValue.Element;taint;manual" + Iterator out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out = in.valueCharSequenceIterator(null); + sink(getElement(out)); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpHeaders;true;valueStringIterator;(CharSequence);;Argument[-1].Element.MapValue;ReturnValue.Element;value;manual" + Iterator out = null; + HttpHeaders in = (HttpHeaders)newWithElementDefault(newWithMapValueDefault(source())); + out = in.valueStringIterator(null); + sink(getElement(out)); // $ hasValueFlow + } + { + // "io.netty.handler.codec.http;HttpMessage;true;headers;;;Argument[-1];ReturnValue;taint;manual" + HttpHeaders out = null; + HttpMessage in = (HttpMessage)source(); + out = in.headers(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpRequest;true;getUri;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + HttpRequest in = (HttpRequest)source(); + out = in.getUri(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpRequest;true;setUri;;;Argument[0];Argument[-1];taint;manual" + FullHttpRequest out = null; + String in = (String)source(); + out.setUri(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpRequest;true;setUri;;;Argument[0];Argument[-1];taint;manual" + HttpRequest out = null; + String in = (String)source(); + out.setUri(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;HttpRequest;true;uri;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + HttpRequest in = (HttpRequest)source(); + out = in.uri(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;LastHttpContent;true;trailingHeaders;;;Argument[-1];ReturnValue;taint;manual" + HttpHeaders out = null; + LastHttpContent in = (LastHttpContent)source(); + out = in.trailingHeaders(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;QueryStringDecoder;;;Argument[0];Argument[-1];taint;manual" + QueryStringDecoder out = null; + String in = (String)source(); + out = new QueryStringDecoder(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;QueryStringDecoder;;;Argument[0];Argument[-1];taint;manual" + QueryStringDecoder out = null; + String in = (String)source(); + out = new QueryStringDecoder(in, (Charset)null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;QueryStringDecoder;;;Argument[0];Argument[-1];taint;manual" + QueryStringDecoder out = null; + String in = (String)source(); + out = new QueryStringDecoder(in, (Charset)null, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;QueryStringDecoder;;;Argument[0];Argument[-1];taint;manual" + QueryStringDecoder out = null; + String in = (String)source(); + out = new QueryStringDecoder(in, (Charset)null, false, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;QueryStringDecoder;;;Argument[0];Argument[-1];taint;manual" + QueryStringDecoder out = null; + String in = (String)source(); + out = new QueryStringDecoder(in, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;QueryStringDecoder;;;Argument[0];Argument[-1];taint;manual" + QueryStringDecoder out = null; + String in = (String)source(); + out = new QueryStringDecoder(in, null, false, 0, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;QueryStringDecoder;;;Argument[0];Argument[-1];taint;manual" + QueryStringDecoder out = null; + URI in = (URI)source(); + out = new QueryStringDecoder(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;QueryStringDecoder;;;Argument[0];Argument[-1];taint;manual" + QueryStringDecoder out = null; + URI in = (URI)source(); + out = new QueryStringDecoder(in, (Charset)null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;QueryStringDecoder;;;Argument[0];Argument[-1];taint;manual" + QueryStringDecoder out = null; + URI in = (URI)source(); + out = new QueryStringDecoder(in, (Charset)null, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;QueryStringDecoder;;;Argument[0];Argument[-1];taint;manual" + QueryStringDecoder out = null; + URI in = (URI)source(); + out = new QueryStringDecoder(in, (Charset)null, 0, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;decodeComponent;;;Argument[0];ReturnValue;taint;manual" + String out = null; + String in = (String)source(); + out = QueryStringDecoder.decodeComponent(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;decodeComponent;;;Argument[0];ReturnValue;taint;manual" + String out = null; + String in = (String)source(); + out = QueryStringDecoder.decodeComponent(in, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;parameters;;;Argument[-1];ReturnValue;taint;manual" + Map out = null; + QueryStringDecoder in = (QueryStringDecoder)source(); + out = in.parameters(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;path;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + QueryStringDecoder in = (QueryStringDecoder)source(); + out = in.path(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;rawPath;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + QueryStringDecoder in = (QueryStringDecoder)source(); + out = in.rawPath(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;rawQuery;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + QueryStringDecoder in = (QueryStringDecoder)source(); + out = in.rawQuery(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + QueryStringDecoder in = (QueryStringDecoder)source(); + out = in.toString(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec.http;QueryStringDecoder;true;uri;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + QueryStringDecoder in = (QueryStringDecoder)source(); + out = in.uri(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;ByteToMessageDecoder$Cumulator;true;cumulate;(ByteBufAllocator,ByteBuf,ByteBuf);;Argument[1..2];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + ByteToMessageDecoder.Cumulator instance = null; + out = instance.cumulate(null, in, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;ByteToMessageDecoder$Cumulator;true;cumulate;(ByteBufAllocator,ByteBuf,ByteBuf);;Argument[1..2];ReturnValue;taint;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + ByteToMessageDecoder.Cumulator instance = null; + out = instance.cumulate(null, null, in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;Headers;true;add;(Headers);;Argument[0].Element.MapKey;Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Headers in = (Headers)newWithElementDefault(newWithMapKeyDefault(source())); + out.add(in); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;add;(Headers);;Argument[0].Element.MapValue;Argument[-1].Element.MapValue;value;manual" + Headers out = null; + Headers in = (Headers)newWithElementDefault(newWithMapValueDefault(source())); + out.add(in); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;add;(Object,Iterable);;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.add(in, (Iterable)null); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;add;(Object,Iterable);;Argument[1].Element;Argument[-1].Element.MapValue;value;manual" + Headers out = null; + Iterable in = (Iterable)List.of(source()); + out.add((Object)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;add;(Object,Object);;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.add(in, (Object)null); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;add;(Object,Object);;Argument[1];Argument[-1].Element.MapValue;value;manual" + Headers out = null; + Object in = (Object)source(); + out.add((Object)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;add;(Object,Object[]);;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.add(in, (Object[])null); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;add;(Object,Object[]);;Argument[1].ArrayElement;Argument[-1].Element.MapValue;value;manual" + Headers out = null; + Object[] in = (Object[])new Object[]{source()}; + out.add((Object)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;add;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.add((Object)null, (Iterable)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;add;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.add((Object)null, (Object)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;add;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.add((Object)null, (Object[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;add;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.add(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addBoolean;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.addBoolean(null, false); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addBoolean;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.addBoolean(in, false); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addByte;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.addByte(null, (byte)0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addByte;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.addByte(in, (byte)0); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addChar;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.addChar(null, '\0'); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addChar;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.addChar(in, '\0'); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addDouble;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.addDouble(null, 0.0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addDouble;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.addDouble(in, 0.0); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addFloat;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.addFloat(null, 0.0f); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addFloat;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.addFloat(in, 0.0f); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addInt;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.addInt(null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addInt;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.addInt(in, 0); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addLong;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.addLong(null, 0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addLong;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.addLong(in, 0L); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addObject;(Object,Iterable);;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.addObject(in, (Iterable)null); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addObject;(Object,Iterable);;Argument[1].Element;Argument[-1].Element.MapValue;taint;manual" + Headers out = null; + Iterable in = (Iterable)List.of(source()); + out.addObject((Object)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;Headers;true;addObject;(Object,Object);;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.addObject(in, (Object)null); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addObject;(Object,Object);;Argument[1];Argument[-1].Element.MapValue;taint;manual" + Headers out = null; + Object in = (Object)source(); + out.addObject((Object)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;Headers;true;addObject;(Object,Object[]);;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.addObject(in, (Object[])null); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addObject;(Object,Object[]);;Argument[1].ArrayElement;Argument[-1].Element.MapValue;taint;manual" + Headers out = null; + Object[] in = (Object[])new Object[]{source()}; + out.addObject((Object)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;Headers;true;addShort;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.addShort(null, (short)0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addShort;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.addShort(in, (short)0); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addTimeMillis;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.addTimeMillis(null, 0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;addTimeMillis;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.addTimeMillis(in, 0L); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;get;(Object);;Argument[-1].Element.MapValue;ReturnValue;taint;manual" + Object out = null; + Headers in = (Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = in.get(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;Headers;true;get;(Object,Object);;Argument[-1].Element.MapValue;ReturnValue;taint;manual" + Object out = null; + Headers in = (Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = in.get(null, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;Headers;true;get;(Object,Object);;Argument[1];ReturnValue;value;manual" + Object out = null; + Object in = (Object)source(); + Headers instance = null; + out = instance.get(null, in); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;getAll;(Object);;Argument[-1].Element.MapValue;ReturnValue.Element;taint;manual" + List out = null; + Headers in = (Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = in.getAll(null); + sink(getElement(out)); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;Headers;true;getAllAndRemove;(Object);;Argument[-1].Element.MapValue;ReturnValue.Element;taint;manual" + List out = null; + Headers in = (Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = in.getAllAndRemove(null); + sink(getElement(out)); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;Headers;true;getAndRemove;(Object);;Argument[-1].Element.MapValue;ReturnValue;taint;manual" + Object out = null; + Headers in = (Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = in.getAndRemove(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;Headers;true;getAndRemove;(Object,Object);;Argument[1];ReturnValue;value;manual" + Object out = null; + Object in = (Object)source(); + Headers instance = null; + out = instance.getAndRemove(null, in); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;names;();;Argument[-1].Element.MapKey;ReturnValue.Element;taint;manual" + Set out = null; + Headers in = (Headers)newWithElementDefault(newWithMapKeyDefault(source())); + out = in.names(); + sink(getElement(out)); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;Headers;true;set;(Headers);;Argument[0].Element.MapKey;Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Headers in = (Headers)newWithElementDefault(newWithMapKeyDefault(source())); + out.set(in); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;set;(Headers);;Argument[0].Element.MapValue;Argument[-1].Element.MapValue;value;manual" + Headers out = null; + Headers in = (Headers)newWithElementDefault(newWithMapValueDefault(source())); + out.set(in); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;set;(Object,Iterable);;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.set(in, (Iterable)null); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;set;(Object,Iterable);;Argument[1].Element;Argument[-1].Element.MapValue;value;manual" + Headers out = null; + Iterable in = (Iterable)List.of(source()); + out.set((Object)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;set;(Object,Object);;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.set(in, (Object)null); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;set;(Object,Object);;Argument[1];Argument[-1].Element.MapValue;value;manual" + Headers out = null; + Object in = (Object)source(); + out.set((Object)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;set;(Object,Object[]);;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.set(in, (Object[])null); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;set;(Object,Object[]);;Argument[1].ArrayElement;Argument[-1].Element.MapValue;value;manual" + Headers out = null; + Object[] in = (Object[])new Object[]{source()}; + out.set((Object)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;set;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.set((Object)null, (Iterable)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;set;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.set((Object)null, (Object)null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;set;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.set((Object)null, (Object[])null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;set;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.set(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setAll;(Headers);;Argument[0].Element.MapKey;Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Headers in = (Headers)newWithElementDefault(newWithMapKeyDefault(source())); + out.setAll(in); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setAll;(Headers);;Argument[0].Element.MapValue;Argument[-1].Element.MapValue;value;manual" + Headers out = null; + Headers in = (Headers)newWithElementDefault(newWithMapValueDefault(source())); + out.setAll(in); + sink(getMapValueDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setBoolean;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.setBoolean(null, false); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setBoolean;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.setBoolean(in, false); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setByte;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.setByte(null, (byte)0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setByte;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.setByte(in, (byte)0); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setChar;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.setChar(null, '\0'); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setChar;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.setChar(in, '\0'); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setDouble;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.setDouble(null, 0.0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setDouble;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.setDouble(in, 0.0); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setFloat;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.setFloat(null, 0.0f); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setFloat;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.setFloat(in, 0.0f); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setInt;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.setInt(null, 0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setInt;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.setInt(in, 0); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setLong;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.setLong(null, 0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setLong;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.setLong(in, 0L); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setObject;(Object,Iterable);;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.setObject(in, (Iterable)null); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setObject;(Object,Iterable);;Argument[1].Element;Argument[-1].Element.MapValue;taint;manual" + Headers out = null; + Iterable in = (Iterable)List.of(source()); + out.setObject((Object)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;Headers;true;setObject;(Object,Object);;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.setObject(in, (Object)null); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setObject;(Object,Object);;Argument[1];Argument[-1].Element.MapValue;taint;manual" + Headers out = null; + Object in = (Object)source(); + out.setObject((Object)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;Headers;true;setObject;(Object,Object[]);;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.setObject(in, (Object[])null); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setObject;(Object,Object[]);;Argument[1].ArrayElement;Argument[-1].Element.MapValue;taint;manual" + Headers out = null; + Object[] in = (Object[])new Object[]{source()}; + out.setObject((Object)null, in); + sink(getMapValueDefault(getElement(out))); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;Headers;true;setShort;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.setShort(null, (short)0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setShort;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.setShort(in, (short)0); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setTimeMillis;;;Argument[-1];ReturnValue;value;manual" + Headers out = null; + Headers in = (Headers)source(); + out = in.setTimeMillis(null, 0L); + sink(out); // $ hasValueFlow + } + { + // "io.netty.handler.codec;Headers;true;setTimeMillis;;;Argument[0];Argument[-1].Element.MapKey;value;manual" + Headers out = null; + Object in = (Object)source(); + out.setTimeMillis(in, 0L); + sink(getMapKeyDefault(getElement(out))); // $ hasValueFlow + } + { + // "io.netty.handler.codec;HeadersUtils;false;getAllAsString;(Headers,Object);;Argument[0].Element.MapValue;ReturnValue;taint;manual" + List out = null; + Headers in = (Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = HeadersUtils.getAllAsString(in, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;HeadersUtils;false;getAsString;(Headers,Object);;Argument[0].Element.MapValue;ReturnValue;taint;manual" + String out = null; + Headers in = (Headers)newWithElementDefault(newWithMapValueDefault(source())); + out = HeadersUtils.getAsString(in, null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;HeadersUtils;false;iteratorAsString;(Iterable);;Argument[0].Element.MapKey;ReturnValue;taint;manual" + Iterator out = null; + Iterable in = (Iterable)List.of(newWithMapKeyDefault(source())); + out = HeadersUtils.iteratorAsString(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;HeadersUtils;false;iteratorAsString;(Iterable);;Argument[0].Element.MapValue;ReturnValue;taint;manual" + Iterator out = null; + Iterable in = (Iterable)List.of(newWithMapValueDefault(source())); + out = HeadersUtils.iteratorAsString(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;HeadersUtils;false;namesAsString;(Headers);;Argument[0].Element.MapKey;ReturnValue.Element;value;manual" + Set out = null; + Headers in = (Headers)newWithElementDefault(newWithMapKeyDefault(source())); + out = HeadersUtils.namesAsString(in); + sink(getElement(out)); // $ hasValueFlow + } + { + // "io.netty.handler.codec;HeadersUtils;false;toString;(Class,Iterator,int);;Argument[1].Element.MapKey;ReturnValue;taint;manual" + String out = null; + Iterator in = (Iterator)List.of(newWithMapKeyDefault(source())).iterator(); + out = HeadersUtils.toString(null, in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.handler.codec;HeadersUtils;false;toString;(Class,Iterator,int);;Argument[1].Element.MapValue;ReturnValue;taint;manual" + String out = null; + Iterator in = (Iterator)List.of(newWithMapValueDefault(source())).iterator(); + out = HeadersUtils.toString(null, in, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;AsciiString;;;Argument[0];Argument[-1];taint;manual" + AsciiString out = null; + ByteBuffer in = (ByteBuffer)source(); + out = new AsciiString(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;AsciiString;;;Argument[0];Argument[-1];taint;manual" + AsciiString out = null; + ByteBuffer in = (ByteBuffer)source(); + out = new AsciiString(in, 0, 0, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;AsciiString;;;Argument[0];Argument[-1];taint;manual" + AsciiString out = null; + ByteBuffer in = (ByteBuffer)source(); + out = new AsciiString(in, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;AsciiString;;;Argument[0];Argument[-1];taint;manual" + AsciiString out = null; + CharSequence in = (CharSequence)source(); + out = new AsciiString(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;AsciiString;;;Argument[0];Argument[-1];taint;manual" + AsciiString out = null; + CharSequence in = (CharSequence)source(); + out = new AsciiString(in, (Charset)null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;AsciiString;;;Argument[0];Argument[-1];taint;manual" + AsciiString out = null; + CharSequence in = (CharSequence)source(); + out = new AsciiString(in, (Charset)null, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;AsciiString;;;Argument[0];Argument[-1];taint;manual" + AsciiString out = null; + CharSequence in = (CharSequence)source(); + out = new AsciiString(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;AsciiString;;;Argument[0];Argument[-1];taint;manual" + AsciiString out = null; + byte[] in = (byte[])source(); + out = new AsciiString(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;AsciiString;;;Argument[0];Argument[-1];taint;manual" + AsciiString out = null; + byte[] in = (byte[])source(); + out = new AsciiString(in, 0, 0, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;AsciiString;;;Argument[0];Argument[-1];taint;manual" + AsciiString out = null; + byte[] in = (byte[])source(); + out = new AsciiString(in, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;AsciiString;;;Argument[0];Argument[-1];taint;manual" + AsciiString out = null; + char[] in = (char[])source(); + out = new AsciiString(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;AsciiString;;;Argument[0];Argument[-1];taint;manual" + AsciiString out = null; + char[] in = (char[])source(); + out = new AsciiString(in, (Charset)null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;AsciiString;;;Argument[0];Argument[-1];taint;manual" + AsciiString out = null; + char[] in = (char[])source(); + out = new AsciiString(in, (Charset)null, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;AsciiString;;;Argument[0];Argument[-1];taint;manual" + AsciiString out = null; + char[] in = (char[])source(); + out = new AsciiString(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;array;();;Argument[-1];ReturnValue;taint;manual" + byte[] out = null; + AsciiString in = (AsciiString)source(); + out = in.array(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;cached;(String);;Argument[0];ReturnValue;taint;manual" + AsciiString out = null; + String in = (String)source(); + out = AsciiString.cached(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;concat;(CharSequence);;Argument[-1];ReturnValue;taint;manual" + AsciiString out = null; + AsciiString in = (AsciiString)source(); + out = in.concat(null); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;concat;(CharSequence);;Argument[0];ReturnValue;taint;manual" + AsciiString out = null; + CharSequence in = (CharSequence)source(); + AsciiString instance = null; + out = instance.concat(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;copy;(int,byte[],int,int);;Argument[-1];Argument[1];taint;manual" + byte[] out = null; + AsciiString in = (AsciiString)source(); + in.copy(0, out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;copy;(int,char[],int,int);;Argument[-1];Argument[1];taint;manual" + char[] out = null; + AsciiString in = (AsciiString)source(); + in.copy(0, out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;of;(CharSequence);;Argument[0];ReturnValue;taint;manual" + AsciiString out = null; + CharSequence in = (CharSequence)source(); + out = AsciiString.of(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;replace;(char,char);;Argument[-1];ReturnValue;taint;manual" + AsciiString out = null; + AsciiString in = (AsciiString)source(); + out = in.replace('\0', '\0'); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;split;(String,int);;Argument[-1];ReturnValue;taint;manual" + AsciiString[] out = null; + AsciiString in = (AsciiString)source(); + out = in.split(null, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;split;(char);;Argument[-1];ReturnValue;taint;manual" + AsciiString[] out = null; + AsciiString in = (AsciiString)source(); + out = in.split('\0'); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;subSequence;;;Argument[-1];ReturnValue;taint;manual" + AsciiString out = null; + AsciiString in = (AsciiString)source(); + out = in.subSequence(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;subSequence;;;Argument[-1];ReturnValue;taint;manual" + AsciiString out = null; + AsciiString in = (AsciiString)source(); + out = in.subSequence(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;subSequence;;;Argument[-1];ReturnValue;taint;manual" + AsciiString out = null; + AsciiString in = (AsciiString)source(); + out = in.subSequence(0, 0, false); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;toByteArray;;;Argument[-1];ReturnValue;taint;manual" + byte[] out = null; + AsciiString in = (AsciiString)source(); + out = in.toByteArray(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;toByteArray;;;Argument[-1];ReturnValue;taint;manual" + byte[] out = null; + AsciiString in = (AsciiString)source(); + out = in.toByteArray(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;toCharArray;;;Argument[-1];ReturnValue;taint;manual" + char[] out = null; + AsciiString in = (AsciiString)source(); + out = in.toCharArray(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;toCharArray;;;Argument[-1];ReturnValue;taint;manual" + char[] out = null; + AsciiString in = (AsciiString)source(); + out = in.toCharArray(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;toLowerCase;();;Argument[-1];ReturnValue;taint;manual" + AsciiString out = null; + AsciiString in = (AsciiString)source(); + out = in.toLowerCase(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + AsciiString in = (AsciiString)source(); + out = in.toString(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + AsciiString in = (AsciiString)source(); + out = in.toString(0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + AsciiString in = (AsciiString)source(); + out = in.toString(0, 0); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;toUpperCase;();;Argument[-1];ReturnValue;taint;manual" + AsciiString out = null; + AsciiString in = (AsciiString)source(); + out = in.toUpperCase(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;trim;();;Argument[-1];ReturnValue;taint;manual" + AsciiString out = null; + AsciiString in = (AsciiString)source(); + out = in.trim(); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;AsciiString;false;trim;(CharSequence);;Argument[0];ReturnValue;taint;manual" + CharSequence out = null; + CharSequence in = (CharSequence)source(); + out = AsciiString.trim(in); + sink(out); // $ hasTaintFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + Attribute out = null; + Attribute in = (Attribute)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + Attribute out = null; + Attribute in = (Attribute)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + BinaryWebSocketFrame out = null; + BinaryWebSocketFrame in = (BinaryWebSocketFrame)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + BinaryWebSocketFrame out = null; + BinaryWebSocketFrame in = (BinaryWebSocketFrame)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractReferenceCountedByteBuf in = (AbstractReferenceCountedByteBuf)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractReferenceCountedByteBuf in = (AbstractReferenceCountedByteBuf)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + ByteBufHolder out = null; + ByteBufHolder in = (ByteBufHolder)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + ByteBufHolder out = null; + ByteBufHolder in = (ByteBufHolder)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + ByteBufHolder out = null; + DefaultByteBufHolder in = (DefaultByteBufHolder)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + ByteBufHolder out = null; + DefaultByteBufHolder in = (DefaultByteBufHolder)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + CloseWebSocketFrame out = null; + CloseWebSocketFrame in = (CloseWebSocketFrame)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + CloseWebSocketFrame out = null; + CloseWebSocketFrame in = (CloseWebSocketFrame)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + ContinuationWebSocketFrame out = null; + ContinuationWebSocketFrame in = (ContinuationWebSocketFrame)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + ContinuationWebSocketFrame out = null; + ContinuationWebSocketFrame in = (ContinuationWebSocketFrame)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + FileRegion out = null; + DefaultFileRegion in = (DefaultFileRegion)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + FileRegion out = null; + DefaultFileRegion in = (DefaultFileRegion)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + FileRegion out = null; + FileRegion in = (FileRegion)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + FileRegion out = null; + FileRegion in = (FileRegion)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + FileUpload out = null; + FileUpload in = (FileUpload)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + FileUpload out = null; + FileUpload in = (FileUpload)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + FullHttpMessage out = null; + FullHttpMessage in = (FullHttpMessage)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + FullHttpMessage out = null; + FullHttpMessage in = (FullHttpMessage)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + FullHttpRequest out = null; + FullHttpRequest in = (FullHttpRequest)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + FullHttpRequest out = null; + FullHttpRequest in = (FullHttpRequest)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + FullHttpResponse out = null; + FullHttpResponse in = (FullHttpResponse)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + FullHttpResponse out = null; + FullHttpResponse in = (FullHttpResponse)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + HttpContent out = null; + HttpContent in = (HttpContent)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + HttpContent out = null; + HttpContent in = (HttpContent)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + HttpData out = null; + HttpData in = (HttpData)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + HttpData out = null; + HttpData in = (HttpData)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + InterfaceHttpData out = null; + InterfaceHttpData in = (InterfaceHttpData)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + InterfaceHttpData out = null; + InterfaceHttpData in = (InterfaceHttpData)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + LastHttpContent out = null; + LastHttpContent in = (LastHttpContent)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + LastHttpContent out = null; + LastHttpContent in = (LastHttpContent)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + PingWebSocketFrame out = null; + PingWebSocketFrame in = (PingWebSocketFrame)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + PingWebSocketFrame out = null; + PingWebSocketFrame in = (PingWebSocketFrame)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + PongWebSocketFrame out = null; + PongWebSocketFrame in = (PongWebSocketFrame)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + PongWebSocketFrame out = null; + PongWebSocketFrame in = (PongWebSocketFrame)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + ReferenceCounted out = null; + AbstractReferenceCounted in = (AbstractReferenceCounted)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + ReferenceCounted out = null; + AbstractReferenceCounted in = (AbstractReferenceCounted)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + ReferenceCounted out = null; + ReferenceCounted in = (ReferenceCounted)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + ReferenceCounted out = null; + ReferenceCounted in = (ReferenceCounted)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + TextWebSocketFrame out = null; + TextWebSocketFrame in = (TextWebSocketFrame)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + TextWebSocketFrame out = null; + TextWebSocketFrame in = (TextWebSocketFrame)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + WebSocketFrame out = null; + WebSocketFrame in = (WebSocketFrame)source(); + out = in.retain(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;retain;;;Argument[-1];ReturnValue;value;manual" + WebSocketFrame out = null; + WebSocketFrame in = (WebSocketFrame)source(); + out = in.retain(0); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + Attribute out = null; + Attribute in = (Attribute)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + Attribute out = null; + Attribute in = (Attribute)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + BinaryWebSocketFrame out = null; + BinaryWebSocketFrame in = (BinaryWebSocketFrame)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + BinaryWebSocketFrame out = null; + BinaryWebSocketFrame in = (BinaryWebSocketFrame)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractReferenceCountedByteBuf in = (AbstractReferenceCountedByteBuf)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + AbstractReferenceCountedByteBuf in = (AbstractReferenceCountedByteBuf)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + ByteBuf in = (ByteBuf)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + ByteBuf out = null; + SwappedByteBuf in = (SwappedByteBuf)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + ByteBufHolder out = null; + ByteBufHolder in = (ByteBufHolder)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + ByteBufHolder out = null; + ByteBufHolder in = (ByteBufHolder)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + ByteBufHolder out = null; + DefaultByteBufHolder in = (DefaultByteBufHolder)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + ByteBufHolder out = null; + DefaultByteBufHolder in = (DefaultByteBufHolder)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + CloseWebSocketFrame out = null; + CloseWebSocketFrame in = (CloseWebSocketFrame)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + CloseWebSocketFrame out = null; + CloseWebSocketFrame in = (CloseWebSocketFrame)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + CompositeByteBuf out = null; + CompositeByteBuf in = (CompositeByteBuf)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + ContinuationWebSocketFrame out = null; + ContinuationWebSocketFrame in = (ContinuationWebSocketFrame)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + ContinuationWebSocketFrame out = null; + ContinuationWebSocketFrame in = (ContinuationWebSocketFrame)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + FileRegion out = null; + DefaultFileRegion in = (DefaultFileRegion)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + FileRegion out = null; + DefaultFileRegion in = (DefaultFileRegion)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + FileRegion out = null; + FileRegion in = (FileRegion)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + FileRegion out = null; + FileRegion in = (FileRegion)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + FileUpload out = null; + FileUpload in = (FileUpload)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + FileUpload out = null; + FileUpload in = (FileUpload)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + FullHttpMessage out = null; + FullHttpMessage in = (FullHttpMessage)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + FullHttpMessage out = null; + FullHttpMessage in = (FullHttpMessage)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + FullHttpRequest out = null; + FullHttpRequest in = (FullHttpRequest)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + FullHttpRequest out = null; + FullHttpRequest in = (FullHttpRequest)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + FullHttpResponse out = null; + FullHttpResponse in = (FullHttpResponse)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + FullHttpResponse out = null; + FullHttpResponse in = (FullHttpResponse)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + HttpContent out = null; + HttpContent in = (HttpContent)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + HttpContent out = null; + HttpContent in = (HttpContent)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + HttpData out = null; + HttpData in = (HttpData)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + HttpData out = null; + HttpData in = (HttpData)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + InterfaceHttpData out = null; + InterfaceHttpData in = (InterfaceHttpData)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + InterfaceHttpData out = null; + InterfaceHttpData in = (InterfaceHttpData)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + LastHttpContent out = null; + LastHttpContent in = (LastHttpContent)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + LastHttpContent out = null; + LastHttpContent in = (LastHttpContent)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + PingWebSocketFrame out = null; + PingWebSocketFrame in = (PingWebSocketFrame)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + PingWebSocketFrame out = null; + PingWebSocketFrame in = (PingWebSocketFrame)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + PongWebSocketFrame out = null; + PongWebSocketFrame in = (PongWebSocketFrame)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + PongWebSocketFrame out = null; + PongWebSocketFrame in = (PongWebSocketFrame)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + ReferenceCounted out = null; + AbstractReferenceCounted in = (AbstractReferenceCounted)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + ReferenceCounted out = null; + ReferenceCounted in = (ReferenceCounted)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + ReferenceCounted out = null; + ReferenceCounted in = (ReferenceCounted)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + TextWebSocketFrame out = null; + TextWebSocketFrame in = (TextWebSocketFrame)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + TextWebSocketFrame out = null; + TextWebSocketFrame in = (TextWebSocketFrame)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + WebSocketFrame out = null; + WebSocketFrame in = (WebSocketFrame)source(); + out = in.touch(); + sink(out); // $ hasValueFlow + } + { + // "io.netty.util;ReferenceCounted;true;touch;;;Argument[-1];ReturnValue;value;manual" + WebSocketFrame out = null; + WebSocketFrame in = (WebSocketFrame)source(); + out = in.touch(null); + sink(out); // $ hasValueFlow + } + + } + +} \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/netty/Test.java b/java/ql/test/library-tests/frameworks/netty/generated/TestA.java similarity index 96% rename from java/ql/test/library-tests/frameworks/netty/Test.java rename to java/ql/test/library-tests/frameworks/netty/generated/TestA.java index 938c9a9e468..4c70d32d39d 100644 --- a/java/ql/test/library-tests/frameworks/netty/Test.java +++ b/java/ql/test/library-tests/frameworks/netty/generated/TestA.java @@ -4,7 +4,7 @@ import io.netty.resolver.SimpleNameResolver; import io.netty.util.concurrent.Future; // Test case generated by GenerateFlowTestCase.ql -public class Test { +public class TestA { Object source() { return null; diff --git a/java/ql/test/library-tests/frameworks/netty/options b/java/ql/test/library-tests/frameworks/netty/generated/options similarity index 75% rename from java/ql/test/library-tests/frameworks/netty/options rename to java/ql/test/library-tests/frameworks/netty/generated/options index 84eb569be33..9c4517826cc 100644 --- a/java/ql/test/library-tests/frameworks/netty/options +++ b/java/ql/test/library-tests/frameworks/netty/generated/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/netty-4.1.x +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/netty-4.1.x \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/netty/generated/test.expected b/java/ql/test/library-tests/frameworks/netty/generated/test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/netty/generated/test.ext.yml b/java/ql/test/library-tests/frameworks/netty/generated/test.ext.yml new file mode 100644 index 00000000000..f6b69f08632 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/netty/generated/test.ext.yml @@ -0,0 +1,11 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["generatedtest", "Test", False, "newWithMapValueDefault", "(Object)", "", "Argument[0]", "ReturnValue.MapValue", "value", "manual"] + - ["generatedtest", "Test", False, "newWithMapKeyDefault", "(Object)", "", "Argument[0]", "ReturnValue.MapKey", "value", "manual"] + - ["generatedtest", "Test", False, "newWithElementDefault", "(Object)", "", "Argument[0]", "ReturnValue.Element", "value", "manual"] + - ["generatedtest", "Test", False, "getMapValueDefault", "(Object)", "", "Argument[0].MapValue", "ReturnValue", "value", "manual"] + - ["generatedtest", "Test", False, "getMapKeyDefault", "(Object)", "", "Argument[0].MapKey", "ReturnValue", "value", "manual"] + - ["generatedtest", "Test", False, "getElementDefault", "(Object)", "", "Argument[0].Element", "ReturnValue", "value", "manual"] diff --git a/java/ql/test/library-tests/frameworks/netty/test.ql b/java/ql/test/library-tests/frameworks/netty/generated/test.ql similarity index 100% rename from java/ql/test/library-tests/frameworks/netty/test.ql rename to java/ql/test/library-tests/frameworks/netty/generated/test.ql diff --git a/java/ql/test/library-tests/frameworks/netty/manual/Test.java b/java/ql/test/library-tests/frameworks/netty/manual/Test.java new file mode 100644 index 00000000000..58150659712 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/netty/manual/Test.java @@ -0,0 +1,76 @@ +import io.netty.channel.*; +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.*; +import io.netty.handler.codec.http.*; +import io.netty.handler.codec.http2.*; + +import java.util.List; + +class Test { + static T source() { return null; } + static void sink(Object s) {} + + class A extends ChannelInboundHandlerAdapter { + public void channelRead(ChannelHandlerContext ctx, Object msg) { + sink(msg); // $hasTaintFlow + } + } + + class B extends ChannelInboundHandlerAdapter { + public void channelRead(ChannelHandlerContext ctx, Object msg) { + ByteBuf bb = (ByteBuf) msg; + byte[] data = new byte[1024]; + bb.readBytes(data); + sink(data); // $hasTaintFlow + } + } + + void test(ByteBuf bb, byte[] x) { + byte[] src = source(); + bb.readBytes(x).setLong(3, 4).readerIndex(2).writeBytes(src).skipBytes(2); + sink(bb); // $ hasTaintFlow + sink(x); + } + + class C extends ByteToMessageDecoder { + public void callDecode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + sink(msg); // $ hasTaintFlow + } + + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + sink(msg); // $ hasTaintFlow + } + + public void decodeLast(ChannelHandlerContext ctx, ByteBuf msg, List out) { + sink(msg); // $ hasTaintFlow + } + } + + class D extends SimpleChannelInboundHandler { + public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) { + sink(msg.uri()); // $ hasTaintFlow + sink(msg.headers().get("X-blah")); // $ hasTaintFlow + sink(msg.content()); // $ hasTaintFlow + } + } + + class E extends Http2FrameAdapter { + public int onDataRead(ChannelHandlerContext ctx, int streamId, ByteBuf data, int padding, boolean endOfStream) { + sink(data); // $ hasTaintFlow + return 0; + } + + public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int padding, boolean endStream) { + sink(headers.get("X-blah")); // $ hasTaintFlow + sink(headers.path()); // $ hasTaintFlow + } + + public void onPushPromiseRead(ChannelHandlerContext ctx, int streamId, int promisedStreamId, Http2Headers headers, int padding) { + sink(headers); // $ hasTaintFlow + } + + public void onUnknownFrame(ChannelHandlerContext ctx, byte frameType, int streamId, Http2Flags flags, ByteBuf payload) { + sink(payload); // $ hasTaintFlow + } + } +} \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/netty/manual/options b/java/ql/test/library-tests/frameworks/netty/manual/options new file mode 100644 index 00000000000..9c4517826cc --- /dev/null +++ b/java/ql/test/library-tests/frameworks/netty/manual/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/netty-4.1.x \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/netty/manual/test.expected b/java/ql/test/library-tests/frameworks/netty/manual/test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/netty/manual/test.ql b/java/ql/test/library-tests/frameworks/netty/manual/test.ql new file mode 100644 index 00000000000..1f707c18e10 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/netty/manual/test.ql @@ -0,0 +1,15 @@ +import java +import semmle.code.java.dataflow.FlowSources +import TestUtilities.InlineFlowTest + +class Conf extends DefaultTaintFlowConf { + override predicate isSource(DataFlow::Node node) { + super.isSource(node) + or + node instanceof RemoteFlowSource + } +} + +class LegacyConfig extends EnableLegacyConfiguration { + LegacyConfig() { this instanceof Unit } +} diff --git a/java/ql/test/query-tests/Telemetry/SupportedExternalApis/SupportedExternalApis.expected b/java/ql/test/query-tests/Telemetry/SupportedExternalApis/SupportedExternalApis.expected index 8a20a6c6c7b..3f5b3663281 100644 --- a/java/ql/test/query-tests/Telemetry/SupportedExternalApis/SupportedExternalApis.expected +++ b/java/ql/test/query-tests/Telemetry/SupportedExternalApis/SupportedExternalApis.expected @@ -6,5 +6,6 @@ | java.net.URL#openConnection() | 1 | | java.net.URL#openStream() | 1 | | java.net.URLConnection#getInputStream() | 1 | +| java.time.Duration#ofMillis(long) | 1 | | java.util.Map#put(Object,Object) | 1 | | org.apache.commons.io.FileUtils#deleteDirectory(File) | 1 | diff --git a/java/ql/test/query-tests/Telemetry/SupportedExternalApis/SupportedExternalApis.java b/java/ql/test/query-tests/Telemetry/SupportedExternalApis/SupportedExternalApis.java index 7dd289acbaa..6445e97b473 100644 --- a/java/ql/test/query-tests/Telemetry/SupportedExternalApis/SupportedExternalApis.java +++ b/java/ql/test/query-tests/Telemetry/SupportedExternalApis/SupportedExternalApis.java @@ -16,7 +16,7 @@ class SupportedExternalApis { Map map = new HashMap<>(); // uninteresting (parameterless constructor) map.put("foo", new Object()); // supported summary - Duration d = java.time.Duration.ofMillis(1000); // not supported + Duration d = java.time.Duration.ofMillis(1000); // supported neutral URL github = new URL("https://www.github.com/"); // supported summary InputStream stream = github.openConnection().getInputStream(); // supported source (getInputStream), supported sink (openConnection) @@ -24,6 +24,6 @@ class SupportedExternalApis { new FileWriter(new File("foo")); // supported sink (FileWriter), supported summary (File) new URL("http://foo").openStream(); // supported sink (openStream), supported summary (URL) - FileUtils.deleteDirectory(new File("foo")); // supported negative summary (deleteDirectory), supported summary (File) + FileUtils.deleteDirectory(new File("foo")); // supported neutral (deleteDirectory), supported summary (File) } } diff --git a/java/ql/test/query-tests/Telemetry/UnsupportedExternalAPIs/Test.java b/java/ql/test/query-tests/Telemetry/UnsupportedExternalAPIs/Test.java index f0e3926c7e9..b398a791836 100644 --- a/java/ql/test/query-tests/Telemetry/UnsupportedExternalAPIs/Test.java +++ b/java/ql/test/query-tests/Telemetry/UnsupportedExternalAPIs/Test.java @@ -11,12 +11,13 @@ class ExternalApiUsage { Map map = new HashMap<>(); map.put("foo", new Object()); - Duration d = java.time.Duration.ofMillis(1000); // not supported + Duration d = java.time.Duration.ofMillis(1000); // supported as a neutral model long l = "foo".length(); // supported as a neutral model - AtomicReference ref = new AtomicReference<>(); // not supported - ref.set("foo"); + AtomicReference ref = new AtomicReference<>(); // uninteresting (parameterless constructor) + ref.set("foo"); // supported as a summary model + ref.toString(); // not supported String.class.isAssignableFrom(Object.class); // parameter with generic type, supported as a neutral model diff --git a/java/ql/test/query-tests/Telemetry/UnsupportedExternalAPIs/UnsupportedExternalAPIs.expected b/java/ql/test/query-tests/Telemetry/UnsupportedExternalAPIs/UnsupportedExternalAPIs.expected index 7bab3b2d75a..6419b137690 100644 --- a/java/ql/test/query-tests/Telemetry/UnsupportedExternalAPIs/UnsupportedExternalAPIs.expected +++ b/java/ql/test/query-tests/Telemetry/UnsupportedExternalAPIs/UnsupportedExternalAPIs.expected @@ -1,2 +1 @@ -| java.time.Duration#ofMillis(long) | 1 | -| java.util.concurrent.atomic.AtomicReference#set(Object) | 1 | +| java.util.concurrent.atomic.AtomicReference#toString() | 1 | diff --git a/java/ql/test/query-tests/security/CWE-074/JndiInjectionTest.ql b/java/ql/test/query-tests/security/CWE-074/JndiInjectionTest.ql index fcad7bff3a4..7a6141b93ce 100644 --- a/java/ql/test/query-tests/security/CWE-074/JndiInjectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-074/JndiInjectionTest.ql @@ -9,7 +9,7 @@ class HasJndiInjectionTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasJndiInjection" and - exists(DataFlow::Node sink, JndiInjectionFlowConfig conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | JndiInjectionFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" diff --git a/java/ql/test/query-tests/security/CWE-074/XsltInjectionTest.ql b/java/ql/test/query-tests/security/CWE-074/XsltInjectionTest.ql index c914638a129..1f5a3030cdb 100644 --- a/java/ql/test/query-tests/security/CWE-074/XsltInjectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-074/XsltInjectionTest.ql @@ -11,7 +11,7 @@ class HasXsltInjectionTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasXsltInjection" and - exists(DataFlow::Node sink, XsltInjectionFlowConfig conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | XsltInjectionFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" diff --git a/java/ql/test/query-tests/security/CWE-094/ApkInstallationTest.ql b/java/ql/test/query-tests/security/CWE-094/ApkInstallationTest.ql index 1e40c0a5d25..dd6aec2ebe3 100644 --- a/java/ql/test/query-tests/security/CWE-094/ApkInstallationTest.ql +++ b/java/ql/test/query-tests/security/CWE-094/ApkInstallationTest.ql @@ -10,7 +10,7 @@ class HasApkInstallationTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasApkInstallation" and - exists(DataFlow::Node sink | ApkInstallationFlow::hasFlowTo(sink) | + exists(DataFlow::Node sink | ApkInstallationFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" diff --git a/java/ql/test/query-tests/security/CWE-094/GroovyInjectionTest.ql b/java/ql/test/query-tests/security/CWE-094/GroovyInjectionTest.ql index 4abcbf497a1..9d979f125a8 100644 --- a/java/ql/test/query-tests/security/CWE-094/GroovyInjectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-094/GroovyInjectionTest.ql @@ -11,7 +11,7 @@ class HasGroovyInjectionTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasGroovyInjection" and - exists(DataFlow::Node sink, GroovyInjectionConfig conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | GroovyInjectionFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" diff --git a/java/ql/test/query-tests/security/CWE-094/JexlInjectionTest.ql b/java/ql/test/query-tests/security/CWE-094/JexlInjectionTest.ql index fa69c303211..9593ae1a8ee 100644 --- a/java/ql/test/query-tests/security/CWE-094/JexlInjectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-094/JexlInjectionTest.ql @@ -9,7 +9,7 @@ class JexlInjectionTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasJexlInjection" and - exists(DataFlow::Node sink, JexlInjectionConfig conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | JexlInjectionFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" diff --git a/java/ql/test/query-tests/security/CWE-094/MvelInjectionTest.ql b/java/ql/test/query-tests/security/CWE-094/MvelInjectionTest.ql index 1a228f99e89..8dc4127cbf1 100644 --- a/java/ql/test/query-tests/security/CWE-094/MvelInjectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-094/MvelInjectionTest.ql @@ -11,7 +11,7 @@ class HasMvelInjectionTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasMvelInjection" and - exists(DataFlow::Node sink, MvelInjectionFlowConfig conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | MvelInjectionFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" diff --git a/java/ql/test/query-tests/security/CWE-094/SpelInjectionTest.ql b/java/ql/test/query-tests/security/CWE-094/SpelInjectionTest.ql index cf89a1673ba..78e147849f1 100644 --- a/java/ql/test/query-tests/security/CWE-094/SpelInjectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-094/SpelInjectionTest.ql @@ -11,7 +11,7 @@ class HasSpelInjectionTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasSpelInjection" and - exists(DataFlow::Node sink, SpelInjectionConfig conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | SpelInjectionFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" diff --git a/java/ql/test/query-tests/security/CWE-094/TemplateInjectionTest.ql b/java/ql/test/query-tests/security/CWE-094/TemplateInjectionTest.ql index b509cb46b03..7e0a7ae1ae2 100644 --- a/java/ql/test/query-tests/security/CWE-094/TemplateInjectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-094/TemplateInjectionTest.ql @@ -9,7 +9,7 @@ class TemplateInjectionTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasTemplateInjection" and - exists(DataFlow::Node sink, TemplateInjectionFlowConfig conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | TemplateInjectionFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" diff --git a/java/ql/test/query-tests/security/CWE-117/LogInjectionTest.ql b/java/ql/test/query-tests/security/CWE-117/LogInjectionTest.ql index ba753b0d930..73a41b1bd8e 100644 --- a/java/ql/test/query-tests/security/CWE-117/LogInjectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-117/LogInjectionTest.ql @@ -12,6 +12,6 @@ private class LogInjectionTest extends InlineFlowTest { override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { none() } override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { - LogInjectionFlow::hasFlow(src, sink) + LogInjectionFlow::flow(src, sink) } } diff --git a/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.ql b/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.ql index c434dbe413a..d90039cf920 100644 --- a/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.ql +++ b/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.ql @@ -6,6 +6,6 @@ class IntentUriPermissionManipulationTest extends InlineFlowTest { override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { none() } override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { - IntentUriPermissionManipulationFlow::hasFlow(src, sink) + IntentUriPermissionManipulationFlow::flow(src, sink) } } diff --git a/java/ql/test/query-tests/security/CWE-441/UnsafeContentUriResolutionTest.ql b/java/ql/test/query-tests/security/CWE-441/UnsafeContentUriResolutionTest.ql index 5e2046c6fbf..55c07bbd301 100644 --- a/java/ql/test/query-tests/security/CWE-441/UnsafeContentUriResolutionTest.ql +++ b/java/ql/test/query-tests/security/CWE-441/UnsafeContentUriResolutionTest.ql @@ -6,6 +6,6 @@ class Test extends InlineFlowTest { override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { none() } override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { - UnsafeContentResolutionFlow::hasFlow(src, sink) + UnsafeContentResolutionFlow::flow(src, sink) } } diff --git a/java/ql/test/query-tests/security/CWE-470/FragmentInjectionTest.ql b/java/ql/test/query-tests/security/CWE-470/FragmentInjectionTest.ql index 22b02c818f5..2771dd3af90 100644 --- a/java/ql/test/query-tests/security/CWE-470/FragmentInjectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-470/FragmentInjectionTest.ql @@ -6,6 +6,6 @@ class Test extends InlineFlowTest { override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { none() } override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { - FragmentInjectionTaintFlow::hasFlow(src, sink) + FragmentInjectionTaintFlow::flow(src, sink) } } diff --git a/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql b/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql index aeceb941e09..5bd19fb5b9e 100644 --- a/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql +++ b/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql @@ -1,15 +1,11 @@ import java import TestUtilities.InlineFlowTest -import semmle.code.java.security.WebviewDubuggingEnabledQuery - -class EnableLegacy extends EnableLegacyConfiguration { - EnableLegacy() { exists(this) } -} +import semmle.code.java.security.WebviewDebuggingEnabledQuery class HasFlowTest extends InlineFlowTest { - override DataFlow::Configuration getTaintFlowConfig() { none() } + override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { none() } - override DataFlow::Configuration getValueFlowConfig() { - result = any(WebviewDebugEnabledConfig c) + override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { + WebviewDebugEnabledFlow::flow(src, sink) } } diff --git a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java b/java/ql/test/query-tests/security/CWE-522/InsecureLdapAuth.java similarity index 90% rename from java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java rename to java/ql/test/query-tests/security/CWE-522/InsecureLdapAuth.java index 978a4df671b..d769258a611 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-522/InsecureLdapAuth.java +++ b/java/ql/test/query-tests/security/CWE-522/InsecureLdapAuth.java @@ -11,13 +11,13 @@ public class InsecureLdapAuth { String ldapUrl = "ldap://ad.your-server.com:389"; Hashtable environment = new Hashtable(); environment.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); + "com.sun.jndi.ldap.LdapCtxFactory"); environment.put(Context.PROVIDER_URL, ldapUrl); environment.put(Context.REFERRAL, "follow"); environment.put(Context.SECURITY_AUTHENTICATION, "simple"); environment.put(Context.SECURITY_PRINCIPAL, ldapUserName); environment.put(Context.SECURITY_CREDENTIALS, password); - DirContext dirContext = new InitialDirContext(environment); + DirContext dirContext = new InitialDirContext(environment); // $ hasInsecureLdapAuth } // BAD - Test LDAP authentication in cleartext using `DirContext`. @@ -25,13 +25,13 @@ public class InsecureLdapAuth { String ldapUrl = "ldap://"+serverName+":389"; Hashtable environment = new Hashtable(); environment.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); + "com.sun.jndi.ldap.LdapCtxFactory"); environment.put(Context.PROVIDER_URL, ldapUrl); environment.put(Context.REFERRAL, "follow"); environment.put(Context.SECURITY_AUTHENTICATION, "simple"); environment.put(Context.SECURITY_PRINCIPAL, ldapUserName); environment.put(Context.SECURITY_CREDENTIALS, password); - DirContext dirContext = new InitialDirContext(environment); + DirContext dirContext = new InitialDirContext(environment); // $ hasInsecureLdapAuth } // GOOD - Test LDAP authentication over SSL. @@ -39,7 +39,7 @@ public class InsecureLdapAuth { String ldapUrl = "ldaps://ad.your-server.com:636"; Hashtable environment = new Hashtable(); environment.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); + "com.sun.jndi.ldap.LdapCtxFactory"); environment.put(Context.PROVIDER_URL, ldapUrl); environment.put(Context.REFERRAL, "follow"); environment.put(Context.SECURITY_AUTHENTICATION, "simple"); @@ -53,7 +53,7 @@ public class InsecureLdapAuth { String ldapUrl = "ldap://ad.your-server.com:636"; Hashtable environment = new Hashtable(); environment.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); + "com.sun.jndi.ldap.LdapCtxFactory"); environment.put(Context.PROVIDER_URL, ldapUrl); environment.put(Context.REFERRAL, "follow"); environment.put(Context.SECURITY_AUTHENTICATION, "simple"); @@ -68,7 +68,7 @@ public class InsecureLdapAuth { String ldapUrl = "ldap://ad.your-server.com:389"; Hashtable environment = new Hashtable(); environment.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); + "com.sun.jndi.ldap.LdapCtxFactory"); environment.put(Context.PROVIDER_URL, ldapUrl); environment.put(Context.REFERRAL, "follow"); environment.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5 GSSAPI"); @@ -82,7 +82,7 @@ public class InsecureLdapAuth { String ldapUrl = "ldap://localhost:389"; Hashtable environment = new Hashtable(); environment.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); + "com.sun.jndi.ldap.LdapCtxFactory"); environment.put(Context.PROVIDER_URL, ldapUrl); environment.put(Context.REFERRAL, "follow"); environment.put(Context.SECURITY_AUTHENTICATION, "simple"); @@ -96,14 +96,14 @@ public class InsecureLdapAuth { String ldapUrl = "ldap://ad.your-server.com:389"; Hashtable environment = new Hashtable(); environment.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); + "com.sun.jndi.ldap.LdapCtxFactory"); environment.put(Context.PROVIDER_URL, ldapUrl); environment.put(Context.REFERRAL, "follow"); environment.put(Context.SECURITY_AUTHENTICATION, "simple"); environment.put(Context.SECURITY_PRINCIPAL, ldapUserName); environment.put(Context.SECURITY_CREDENTIALS, password); - InitialLdapContext ldapContext = new InitialLdapContext(environment, null); - } + InitialLdapContext ldapContext = new InitialLdapContext(environment, null); // $ hasInsecureLdapAuth + } // BAD - Test LDAP authentication in cleartext using `DirContext` and string literals. @@ -111,13 +111,13 @@ public class InsecureLdapAuth { String ldapUrl = "ldap://ad.your-server.com:389"; Hashtable environment = new Hashtable(); environment.put("java.naming.factory.initial", - "com.sun.jndi.ldap.LdapCtxFactory"); + "com.sun.jndi.ldap.LdapCtxFactory"); environment.put("java.naming.provider.url", ldapUrl); environment.put("java.naming.referral", "follow"); environment.put("java.naming.security.authentication", "simple"); environment.put("java.naming.security.principal", ldapUserName); environment.put("java.naming.security.credentials", password); - DirContext dirContext = new InitialDirContext(environment); + DirContext dirContext = new InitialDirContext(environment); // $ hasInsecureLdapAuth } private void setSSL(Hashtable env) { @@ -136,7 +136,7 @@ public class InsecureLdapAuth { Hashtable environment = new Hashtable(); setSSL(environment); environment.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); + "com.sun.jndi.ldap.LdapCtxFactory"); environment.put(Context.PROVIDER_URL, ldapUrl); setBasicAuth(environment, ldapUserName, password); DirContext dirContext = new InitialLdapContext(environment, null); @@ -147,9 +147,9 @@ public class InsecureLdapAuth { String ldapUrl = "ldap://"+serverName+":389"; Hashtable environment = new Hashtable(); environment.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); + "com.sun.jndi.ldap.LdapCtxFactory"); environment.put(Context.PROVIDER_URL, ldapUrl); setBasicAuth(environment, ldapUserName, password); - DirContext dirContext = new InitialLdapContext(environment, null); + DirContext dirContext = new InitialLdapContext(environment, null); // $ hasInsecureLdapAuth } } diff --git a/java/ql/test/query-tests/security/CWE-522/InsecureLdapAuthTest.expected b/java/ql/test/query-tests/security/CWE-522/InsecureLdapAuthTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/query-tests/security/CWE-522/InsecureLdapAuthTest.ql b/java/ql/test/query-tests/security/CWE-522/InsecureLdapAuthTest.ql new file mode 100644 index 00000000000..4ae89d21313 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-522/InsecureLdapAuthTest.ql @@ -0,0 +1,20 @@ +import java +import semmle.code.java.security.InsecureLdapAuthQuery +import TestUtilities.InlineExpectationsTest + +class InsecureLdapAuthenticationTest extends InlineExpectationsTest { + InsecureLdapAuthenticationTest() { this = "InsecureLdapAuthentication" } + + override string getARelevantTag() { result = "hasInsecureLdapAuth" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasInsecureLdapAuth" and + exists(DataFlow::Node sink | InsecureLdapUrlFlow::flowTo(sink) | + BasicAuthFlow::flowTo(sink) and + not RequiresSslFlow::flowTo(sink) and + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) + } +} diff --git a/java/ql/test/query-tests/security/CWE-532/SensitiveLogInfo.ql b/java/ql/test/query-tests/security/CWE-532/SensitiveLogInfo.ql index b868dcabf85..5de153a9e35 100644 --- a/java/ql/test/query-tests/security/CWE-532/SensitiveLogInfo.ql +++ b/java/ql/test/query-tests/security/CWE-532/SensitiveLogInfo.ql @@ -4,7 +4,7 @@ import semmle.code.java.security.SensitiveLoggingQuery class HasFlowTest extends InlineFlowTest { override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { - SensitiveLoggerFlow::hasFlow(src, sink) + SensitiveLoggerFlow::flow(src, sink) } override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { none() } diff --git a/java/ql/test/query-tests/security/CWE-730/PolynomialReDoS.ql b/java/ql/test/query-tests/security/CWE-730/PolynomialReDoS.ql index e31d890d908..75af0160def 100644 --- a/java/ql/test/query-tests/security/CWE-730/PolynomialReDoS.ql +++ b/java/ql/test/query-tests/security/CWE-730/PolynomialReDoS.ql @@ -9,7 +9,7 @@ class HasPolyRedos extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasPolyRedos" and exists(DataFlow::Node sink | - PolynomialRedosFlow::hasFlowTo(sink) and + PolynomialRedosFlow::flowTo(sink) and location = sink.getLocation() and element = sink.toString() and value = "" diff --git a/java/ql/test/query-tests/security/CWE-730/RegexInjectionTest.ql b/java/ql/test/query-tests/security/CWE-730/RegexInjectionTest.ql index 63b4f19b3a1..f42de310988 100644 --- a/java/ql/test/query-tests/security/CWE-730/RegexInjectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-730/RegexInjectionTest.ql @@ -9,7 +9,7 @@ class RegexInjectionTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasRegexInjection" and - exists(DataFlow::PathNode sink, RegexInjectionConfiguration c | c.hasFlowPath(_, sink) | + exists(RegexInjectionFlow::PathNode sink | RegexInjectionFlow::flowPath(_, sink) | location = sink.getNode().getLocation() and element = sink.getNode().toString() and value = "" diff --git a/java/ql/test/query-tests/security/CWE-749/UnsafeAndroidAccessTest.ql b/java/ql/test/query-tests/security/CWE-749/UnsafeAndroidAccessTest.ql index 7305d6aeb6f..4da1ca7fd5f 100644 --- a/java/ql/test/query-tests/security/CWE-749/UnsafeAndroidAccessTest.ql +++ b/java/ql/test/query-tests/security/CWE-749/UnsafeAndroidAccessTest.ql @@ -9,7 +9,7 @@ class UnsafeAndroidAccessTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasUnsafeAndroidAccess" and - exists(DataFlow::Node sink, FetchUntrustedResourceConfiguration conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | FetchUntrustedResourceFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" diff --git a/java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.ql b/java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.ql index cdfdaea621e..01af77284f0 100644 --- a/java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.ql +++ b/java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.ql @@ -7,6 +7,6 @@ class HasFlowTest extends InlineFlowTest { override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { none() } override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { - RsaWithoutOaepFlow::hasFlow(src, sink) + RsaWithoutOaepFlow::flow(src, sink) } } diff --git a/java/ql/test/query-tests/security/CWE-917/OgnlInjectionTest.ql b/java/ql/test/query-tests/security/CWE-917/OgnlInjectionTest.ql index efbf1508fe4..68db2593628 100644 --- a/java/ql/test/query-tests/security/CWE-917/OgnlInjectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-917/OgnlInjectionTest.ql @@ -9,7 +9,7 @@ class OgnlInjectionTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasOgnlInjection" and - exists(DataFlow::Node sink, OgnlInjectionFlowConfig conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | OgnlInjectionFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" diff --git a/java/ql/test/query-tests/security/CWE-918/RequestForgery.ql b/java/ql/test/query-tests/security/CWE-918/RequestForgery.ql index b27d81ee073..865e6e8f0d3 100644 --- a/java/ql/test/query-tests/security/CWE-918/RequestForgery.ql +++ b/java/ql/test/query-tests/security/CWE-918/RequestForgery.ql @@ -10,7 +10,7 @@ class HasFlowTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "SSRF" and exists(DataFlow::Node sink | - RequestForgeryFlow::hasFlowTo(sink) and + RequestForgeryFlow::flowTo(sink) and sink.getLocation() = location and element = sink.toString() and value = "" diff --git a/java/ql/test/query-tests/security/CWE-927/SensitiveCommunication.ql b/java/ql/test/query-tests/security/CWE-927/SensitiveCommunication.ql index c57c316310d..0f1864398b4 100644 --- a/java/ql/test/query-tests/security/CWE-927/SensitiveCommunication.ql +++ b/java/ql/test/query-tests/security/CWE-927/SensitiveCommunication.ql @@ -7,6 +7,6 @@ class HasFlowTest extends InlineFlowTest { override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { none() } override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { - SensitiveCommunicationFlow::hasFlow(src, sink) + SensitiveCommunicationFlow::flow(src, sink) } } diff --git a/java/ql/test/query-tests/security/CWE-940/AndroidIntentRedirectionTest.ql b/java/ql/test/query-tests/security/CWE-940/AndroidIntentRedirectionTest.ql index 62605ed505d..7b74855caa5 100644 --- a/java/ql/test/query-tests/security/CWE-940/AndroidIntentRedirectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-940/AndroidIntentRedirectionTest.ql @@ -9,7 +9,7 @@ class HasAndroidIntentRedirectionTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasAndroidIntentRedirection" and - exists(DataFlow::Node sink, IntentRedirectionConfiguration conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | IntentRedirectionFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/AbstractByteBuf.java b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/AbstractByteBuf.java new file mode 100644 index 00000000000..368533e2f9b --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/AbstractByteBuf.java @@ -0,0 +1,199 @@ +// Generated automatically from io.netty.buffer.AbstractByteBuf for testing purposes + +package io.netty.buffer; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.SwappedByteBuf; +import io.netty.util.ByteProcessor; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.channels.FileChannel; +import java.nio.channels.GatheringByteChannel; +import java.nio.channels.ScatteringByteChannel; +import java.nio.charset.Charset; + +abstract public class AbstractByteBuf extends ByteBuf +{ + protected AbstractByteBuf() {} + protected AbstractByteBuf(int p0){} + protected SwappedByteBuf newSwappedByteBuf(){ return null; } + protected abstract byte _getByte(int p0); + protected abstract int _getInt(int p0); + protected abstract int _getIntLE(int p0); + protected abstract int _getUnsignedMedium(int p0); + protected abstract int _getUnsignedMediumLE(int p0); + protected abstract long _getLong(int p0); + protected abstract long _getLongLE(int p0); + protected abstract short _getShort(int p0); + protected abstract short _getShortLE(int p0); + protected abstract void _setByte(int p0, int p1); + protected abstract void _setInt(int p0, int p1); + protected abstract void _setIntLE(int p0, int p1); + protected abstract void _setLong(int p0, long p1); + protected abstract void _setLongLE(int p0, long p1); + protected abstract void _setMedium(int p0, int p1); + protected abstract void _setMediumLE(int p0, int p1); + protected abstract void _setShort(int p0, int p1); + protected abstract void _setShortLE(int p0, int p1); + protected final void adjustMarkers(int p0){} + protected final void checkDstIndex(int p0, int p1, int p2){} + protected final void checkDstIndex(int p0, int p1, int p2, int p3){} + protected final void checkIndex(int p0){} + protected final void checkIndex(int p0, int p1){} + protected final void checkNewCapacity(int p0){} + protected final void checkReadableBytes(int p0){} + protected final void checkSrcIndex(int p0, int p1, int p2, int p3){} + protected final void ensureAccessible(){} + protected final void maxCapacity(int p0){} + protected final void trimIndicesToCapacity(int p0){} + public ByteBuf asReadOnly(){ return null; } + public ByteBuf clear(){ return null; } + public ByteBuf copy(){ return null; } + public ByteBuf discardReadBytes(){ return null; } + public ByteBuf discardSomeReadBytes(){ return null; } + public ByteBuf duplicate(){ return null; } + public ByteBuf ensureWritable(int p0){ return null; } + public ByteBuf getBytes(int p0, ByteBuf p1){ return null; } + public ByteBuf getBytes(int p0, ByteBuf p1, int p2){ return null; } + public ByteBuf getBytes(int p0, byte[] p1){ return null; } + public ByteBuf markReaderIndex(){ return null; } + public ByteBuf markWriterIndex(){ return null; } + public ByteBuf order(ByteOrder p0){ return null; } + public ByteBuf readBytes(ByteBuf p0){ return null; } + public ByteBuf readBytes(ByteBuf p0, int p1){ return null; } + public ByteBuf readBytes(ByteBuf p0, int p1, int p2){ return null; } + public ByteBuf readBytes(ByteBuffer p0){ return null; } + public ByteBuf readBytes(OutputStream p0, int p1){ return null; } + public ByteBuf readBytes(byte[] p0){ return null; } + public ByteBuf readBytes(byte[] p0, int p1, int p2){ return null; } + public ByteBuf readBytes(int p0){ return null; } + public ByteBuf readRetainedSlice(int p0){ return null; } + public ByteBuf readSlice(int p0){ return null; } + public ByteBuf readerIndex(int p0){ return null; } + public ByteBuf resetReaderIndex(){ return null; } + public ByteBuf resetWriterIndex(){ return null; } + public ByteBuf retainedDuplicate(){ return null; } + public ByteBuf retainedSlice(){ return null; } + public ByteBuf retainedSlice(int p0, int p1){ return null; } + public ByteBuf setBoolean(int p0, boolean p1){ return null; } + public ByteBuf setByte(int p0, int p1){ return null; } + public ByteBuf setBytes(int p0, ByteBuf p1){ return null; } + public ByteBuf setBytes(int p0, ByteBuf p1, int p2){ return null; } + public ByteBuf setBytes(int p0, byte[] p1){ return null; } + public ByteBuf setChar(int p0, int p1){ return null; } + public ByteBuf setDouble(int p0, double p1){ return null; } + public ByteBuf setFloat(int p0, float p1){ return null; } + public ByteBuf setIndex(int p0, int p1){ return null; } + public ByteBuf setInt(int p0, int p1){ return null; } + public ByteBuf setIntLE(int p0, int p1){ return null; } + public ByteBuf setLong(int p0, long p1){ return null; } + public ByteBuf setLongLE(int p0, long p1){ return null; } + public ByteBuf setMedium(int p0, int p1){ return null; } + public ByteBuf setMediumLE(int p0, int p1){ return null; } + public ByteBuf setShort(int p0, int p1){ return null; } + public ByteBuf setShortLE(int p0, int p1){ return null; } + public ByteBuf setZero(int p0, int p1){ return null; } + public ByteBuf skipBytes(int p0){ return null; } + public ByteBuf slice(){ return null; } + public ByteBuf slice(int p0, int p1){ return null; } + public ByteBuf writeBoolean(boolean p0){ return null; } + public ByteBuf writeByte(int p0){ return null; } + public ByteBuf writeBytes(ByteBuf p0){ return null; } + public ByteBuf writeBytes(ByteBuf p0, int p1){ return null; } + public ByteBuf writeBytes(ByteBuf p0, int p1, int p2){ return null; } + public ByteBuf writeBytes(ByteBuffer p0){ return null; } + public ByteBuf writeBytes(byte[] p0){ return null; } + public ByteBuf writeBytes(byte[] p0, int p1, int p2){ return null; } + public ByteBuf writeChar(int p0){ return null; } + public ByteBuf writeDouble(double p0){ return null; } + public ByteBuf writeFloat(float p0){ return null; } + public ByteBuf writeInt(int p0){ return null; } + public ByteBuf writeIntLE(int p0){ return null; } + public ByteBuf writeLong(long p0){ return null; } + public ByteBuf writeLongLE(long p0){ return null; } + public ByteBuf writeMedium(int p0){ return null; } + public ByteBuf writeMediumLE(int p0){ return null; } + public ByteBuf writeShort(int p0){ return null; } + public ByteBuf writeShortLE(int p0){ return null; } + public ByteBuf writeZero(int p0){ return null; } + public ByteBuf writerIndex(int p0){ return null; } + public ByteBuffer nioBuffer(){ return null; } + public ByteBuffer[] nioBuffers(){ return null; } + public CharSequence getCharSequence(int p0, int p1, Charset p2){ return null; } + public CharSequence readCharSequence(int p0, Charset p1){ return null; } + public String toString(){ return null; } + public String toString(Charset p0){ return null; } + public String toString(int p0, int p1, Charset p2){ return null; } + public boolean equals(Object p0){ return false; } + public boolean getBoolean(int p0){ return false; } + public boolean isReadOnly(){ return false; } + public boolean isReadable(){ return false; } + public boolean isReadable(int p0){ return false; } + public boolean isWritable(){ return false; } + public boolean isWritable(int p0){ return false; } + public boolean readBoolean(){ return false; } + public byte getByte(int p0){ return 0; } + public byte readByte(){ return 0; } + public char getChar(int p0){ return '0'; } + public char readChar(){ return '0'; } + public double getDouble(int p0){ return 0; } + public double readDouble(){ return 0; } + public float getFloat(int p0){ return 0; } + public float readFloat(){ return 0; } + public int bytesBefore(byte p0){ return 0; } + public int bytesBefore(int p0, byte p1){ return 0; } + public int bytesBefore(int p0, int p1, byte p2){ return 0; } + public int compareTo(ByteBuf p0){ return 0; } + public int ensureWritable(int p0, boolean p1){ return 0; } + public int forEachByte(ByteProcessor p0){ return 0; } + public int forEachByte(int p0, int p1, ByteProcessor p2){ return 0; } + public int forEachByteDesc(ByteProcessor p0){ return 0; } + public int forEachByteDesc(int p0, int p1, ByteProcessor p2){ return 0; } + public int getInt(int p0){ return 0; } + public int getIntLE(int p0){ return 0; } + public int getMedium(int p0){ return 0; } + public int getMediumLE(int p0){ return 0; } + public int getUnsignedMedium(int p0){ return 0; } + public int getUnsignedMediumLE(int p0){ return 0; } + public int getUnsignedShort(int p0){ return 0; } + public int getUnsignedShortLE(int p0){ return 0; } + public int hashCode(){ return 0; } + public int indexOf(int p0, int p1, byte p2){ return 0; } + public int maxCapacity(){ return 0; } + public int maxWritableBytes(){ return 0; } + public int readBytes(FileChannel p0, long p1, int p2){ return 0; } + public int readBytes(GatheringByteChannel p0, int p1){ return 0; } + public int readInt(){ return 0; } + public int readIntLE(){ return 0; } + public int readMedium(){ return 0; } + public int readMediumLE(){ return 0; } + public int readUnsignedMedium(){ return 0; } + public int readUnsignedMediumLE(){ return 0; } + public int readUnsignedShort(){ return 0; } + public int readUnsignedShortLE(){ return 0; } + public int readableBytes(){ return 0; } + public int readerIndex(){ return 0; } + public int setCharSequence(int p0, CharSequence p1, Charset p2){ return 0; } + public int writableBytes(){ return 0; } + public int writeBytes(FileChannel p0, long p1, int p2){ return 0; } + public int writeBytes(InputStream p0, int p1){ return 0; } + public int writeBytes(ScatteringByteChannel p0, int p1){ return 0; } + public int writeCharSequence(CharSequence p0, Charset p1){ return 0; } + public int writerIndex(){ return 0; } + public long getLong(int p0){ return 0; } + public long getLongLE(int p0){ return 0; } + public long getUnsignedInt(int p0){ return 0; } + public long getUnsignedIntLE(int p0){ return 0; } + public long readLong(){ return 0; } + public long readLongLE(){ return 0; } + public long readUnsignedInt(){ return 0; } + public long readUnsignedIntLE(){ return 0; } + public short getShort(int p0){ return 0; } + public short getShortLE(int p0){ return 0; } + public short getUnsignedByte(int p0){ return 0; } + public short readShort(){ return 0; } + public short readShortLE(){ return 0; } + public short readUnsignedByte(){ return 0; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/AbstractReferenceCountedByteBuf.java b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/AbstractReferenceCountedByteBuf.java new file mode 100644 index 00000000000..e5c1bf5be0a --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/AbstractReferenceCountedByteBuf.java @@ -0,0 +1,22 @@ +// Generated automatically from io.netty.buffer.AbstractReferenceCountedByteBuf for testing purposes + +package io.netty.buffer; + +import io.netty.buffer.AbstractByteBuf; +import io.netty.buffer.ByteBuf; + +abstract public class AbstractReferenceCountedByteBuf extends AbstractByteBuf +{ + protected AbstractReferenceCountedByteBuf() {} + protected AbstractReferenceCountedByteBuf(int p0){} + protected abstract void deallocate(); + protected final void resetRefCnt(){} + protected final void setRefCnt(int p0){} + public ByteBuf retain(){ return null; } + public ByteBuf retain(int p0){ return null; } + public ByteBuf touch(){ return null; } + public ByteBuf touch(Object p0){ return null; } + public boolean release(){ return false; } + public boolean release(int p0){ return false; } + public int refCnt(){ return 0; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBuf.java b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBuf.java index cb327fdf002..ab10df0c171 100644 --- a/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBuf.java +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBuf.java @@ -1,19 +1,212 @@ -/* - * Copyright 2012 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ +// Generated automatically from io.netty.buffer.ByteBuf for testing purposes + package io.netty.buffer; -public abstract class ByteBuf implements Comparable { -} \ No newline at end of file +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.ByteBufConvertible; +import io.netty.util.ByteProcessor; +import io.netty.util.ReferenceCounted; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.channels.FileChannel; +import java.nio.channels.GatheringByteChannel; +import java.nio.channels.ScatteringByteChannel; +import java.nio.charset.Charset; + +abstract public class ByteBuf implements ByteBufConvertible, Comparable, ReferenceCounted +{ + public ByteBuf asByteBuf(){ return null; } + public ByteBuf setDoubleLE(int p0, double p1){ return null; } + public ByteBuf setFloatLE(int p0, float p1){ return null; } + public ByteBuf writeDoubleLE(double p0){ return null; } + public ByteBuf writeFloatLE(float p0){ return null; } + public ByteBuf(){} + public abstract ByteBuf asReadOnly(); + public abstract ByteBuf capacity(int p0); + public abstract ByteBuf clear(); + public abstract ByteBuf copy(); + public abstract ByteBuf copy(int p0, int p1); + public abstract ByteBuf discardReadBytes(); + public abstract ByteBuf discardSomeReadBytes(); + public abstract ByteBuf duplicate(); + public abstract ByteBuf ensureWritable(int p0); + public abstract ByteBuf getBytes(int p0, ByteBuf p1); + public abstract ByteBuf getBytes(int p0, ByteBuf p1, int p2); + public abstract ByteBuf getBytes(int p0, ByteBuf p1, int p2, int p3); + public abstract ByteBuf getBytes(int p0, ByteBuffer p1); + public abstract ByteBuf getBytes(int p0, OutputStream p1, int p2); + public abstract ByteBuf getBytes(int p0, byte[] p1); + public abstract ByteBuf getBytes(int p0, byte[] p1, int p2, int p3); + public abstract ByteBuf markReaderIndex(); + public abstract ByteBuf markWriterIndex(); + public abstract ByteBuf order(ByteOrder p0); + public abstract ByteBuf readBytes(ByteBuf p0); + public abstract ByteBuf readBytes(ByteBuf p0, int p1); + public abstract ByteBuf readBytes(ByteBuf p0, int p1, int p2); + public abstract ByteBuf readBytes(ByteBuffer p0); + public abstract ByteBuf readBytes(OutputStream p0, int p1); + public abstract ByteBuf readBytes(byte[] p0); + public abstract ByteBuf readBytes(byte[] p0, int p1, int p2); + public abstract ByteBuf readBytes(int p0); + public abstract ByteBuf readRetainedSlice(int p0); + public abstract ByteBuf readSlice(int p0); + public abstract ByteBuf readerIndex(int p0); + public abstract ByteBuf resetReaderIndex(); + public abstract ByteBuf resetWriterIndex(); + public abstract ByteBuf retain(); + public abstract ByteBuf retain(int p0); + public abstract ByteBuf retainedDuplicate(); + public abstract ByteBuf retainedSlice(); + public abstract ByteBuf retainedSlice(int p0, int p1); + public abstract ByteBuf setBoolean(int p0, boolean p1); + public abstract ByteBuf setByte(int p0, int p1); + public abstract ByteBuf setBytes(int p0, ByteBuf p1); + public abstract ByteBuf setBytes(int p0, ByteBuf p1, int p2); + public abstract ByteBuf setBytes(int p0, ByteBuf p1, int p2, int p3); + public abstract ByteBuf setBytes(int p0, ByteBuffer p1); + public abstract ByteBuf setBytes(int p0, byte[] p1); + public abstract ByteBuf setBytes(int p0, byte[] p1, int p2, int p3); + public abstract ByteBuf setChar(int p0, int p1); + public abstract ByteBuf setDouble(int p0, double p1); + public abstract ByteBuf setFloat(int p0, float p1); + public abstract ByteBuf setIndex(int p0, int p1); + public abstract ByteBuf setInt(int p0, int p1); + public abstract ByteBuf setIntLE(int p0, int p1); + public abstract ByteBuf setLong(int p0, long p1); + public abstract ByteBuf setLongLE(int p0, long p1); + public abstract ByteBuf setMedium(int p0, int p1); + public abstract ByteBuf setMediumLE(int p0, int p1); + public abstract ByteBuf setShort(int p0, int p1); + public abstract ByteBuf setShortLE(int p0, int p1); + public abstract ByteBuf setZero(int p0, int p1); + public abstract ByteBuf skipBytes(int p0); + public abstract ByteBuf slice(); + public abstract ByteBuf slice(int p0, int p1); + public abstract ByteBuf touch(); + public abstract ByteBuf touch(Object p0); + public abstract ByteBuf unwrap(); + public abstract ByteBuf writeBoolean(boolean p0); + public abstract ByteBuf writeByte(int p0); + public abstract ByteBuf writeBytes(ByteBuf p0); + public abstract ByteBuf writeBytes(ByteBuf p0, int p1); + public abstract ByteBuf writeBytes(ByteBuf p0, int p1, int p2); + public abstract ByteBuf writeBytes(ByteBuffer p0); + public abstract ByteBuf writeBytes(byte[] p0); + public abstract ByteBuf writeBytes(byte[] p0, int p1, int p2); + public abstract ByteBuf writeChar(int p0); + public abstract ByteBuf writeDouble(double p0); + public abstract ByteBuf writeFloat(float p0); + public abstract ByteBuf writeInt(int p0); + public abstract ByteBuf writeIntLE(int p0); + public abstract ByteBuf writeLong(long p0); + public abstract ByteBuf writeLongLE(long p0); + public abstract ByteBuf writeMedium(int p0); + public abstract ByteBuf writeMediumLE(int p0); + public abstract ByteBuf writeShort(int p0); + public abstract ByteBuf writeShortLE(int p0); + public abstract ByteBuf writeZero(int p0); + public abstract ByteBuf writerIndex(int p0); + public abstract ByteBufAllocator alloc(); + public abstract ByteBuffer internalNioBuffer(int p0, int p1); + public abstract ByteBuffer nioBuffer(); + public abstract ByteBuffer nioBuffer(int p0, int p1); + public abstract ByteBuffer[] nioBuffers(); + public abstract ByteBuffer[] nioBuffers(int p0, int p1); + public abstract ByteOrder order(); + public abstract CharSequence getCharSequence(int p0, int p1, Charset p2); + public abstract CharSequence readCharSequence(int p0, Charset p1); + public abstract String toString(); + public abstract String toString(Charset p0); + public abstract String toString(int p0, int p1, Charset p2); + public abstract boolean equals(Object p0); + public abstract boolean getBoolean(int p0); + public abstract boolean hasArray(); + public abstract boolean hasMemoryAddress(); + public abstract boolean isDirect(); + public abstract boolean isReadOnly(); + public abstract boolean isReadable(); + public abstract boolean isReadable(int p0); + public abstract boolean isWritable(); + public abstract boolean isWritable(int p0); + public abstract boolean readBoolean(); + public abstract byte getByte(int p0); + public abstract byte readByte(); + public abstract byte[] array(); + public abstract char getChar(int p0); + public abstract char readChar(); + public abstract double getDouble(int p0); + public abstract double readDouble(); + public abstract float getFloat(int p0); + public abstract float readFloat(); + public abstract int arrayOffset(); + public abstract int bytesBefore(byte p0); + public abstract int bytesBefore(int p0, byte p1); + public abstract int bytesBefore(int p0, int p1, byte p2); + public abstract int capacity(); + public abstract int compareTo(ByteBuf p0); + public abstract int ensureWritable(int p0, boolean p1); + public abstract int forEachByte(ByteProcessor p0); + public abstract int forEachByte(int p0, int p1, ByteProcessor p2); + public abstract int forEachByteDesc(ByteProcessor p0); + public abstract int forEachByteDesc(int p0, int p1, ByteProcessor p2); + public abstract int getBytes(int p0, FileChannel p1, long p2, int p3); + public abstract int getBytes(int p0, GatheringByteChannel p1, int p2); + public abstract int getInt(int p0); + public abstract int getIntLE(int p0); + public abstract int getMedium(int p0); + public abstract int getMediumLE(int p0); + public abstract int getUnsignedMedium(int p0); + public abstract int getUnsignedMediumLE(int p0); + public abstract int getUnsignedShort(int p0); + public abstract int getUnsignedShortLE(int p0); + public abstract int hashCode(); + public abstract int indexOf(int p0, int p1, byte p2); + public abstract int maxCapacity(); + public abstract int maxWritableBytes(); + public abstract int nioBufferCount(); + public abstract int readBytes(FileChannel p0, long p1, int p2); + public abstract int readBytes(GatheringByteChannel p0, int p1); + public abstract int readInt(); + public abstract int readIntLE(); + public abstract int readMedium(); + public abstract int readMediumLE(); + public abstract int readUnsignedMedium(); + public abstract int readUnsignedMediumLE(); + public abstract int readUnsignedShort(); + public abstract int readUnsignedShortLE(); + public abstract int readableBytes(); + public abstract int readerIndex(); + public abstract int setBytes(int p0, FileChannel p1, long p2, int p3); + public abstract int setBytes(int p0, InputStream p1, int p2); + public abstract int setBytes(int p0, ScatteringByteChannel p1, int p2); + public abstract int setCharSequence(int p0, CharSequence p1, Charset p2); + public abstract int writableBytes(); + public abstract int writeBytes(FileChannel p0, long p1, int p2); + public abstract int writeBytes(InputStream p0, int p1); + public abstract int writeBytes(ScatteringByteChannel p0, int p1); + public abstract int writeCharSequence(CharSequence p0, Charset p1); + public abstract int writerIndex(); + public abstract long getLong(int p0); + public abstract long getLongLE(int p0); + public abstract long getUnsignedInt(int p0); + public abstract long getUnsignedIntLE(int p0); + public abstract long memoryAddress(); + public abstract long readLong(); + public abstract long readLongLE(); + public abstract long readUnsignedInt(); + public abstract long readUnsignedIntLE(); + public abstract short getShort(int p0); + public abstract short getShortLE(int p0); + public abstract short getUnsignedByte(int p0); + public abstract short readShort(); + public abstract short readShortLE(); + public abstract short readUnsignedByte(); + public boolean isContiguous(){ return false; } + public double getDoubleLE(int p0){ return 0; } + public double readDoubleLE(){ return 0; } + public float getFloatLE(int p0){ return 0; } + public float readFloatLE(){ return 0; } + public int maxFastWritableBytes(){ return 0; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufAllocator.java b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufAllocator.java new file mode 100644 index 00000000000..490f4364b8d --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufAllocator.java @@ -0,0 +1,31 @@ +// Generated automatically from io.netty.buffer.ByteBufAllocator for testing purposes + +package io.netty.buffer; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.CompositeByteBuf; + +public interface ByteBufAllocator +{ + ByteBuf buffer(); + ByteBuf buffer(int p0); + ByteBuf buffer(int p0, int p1); + ByteBuf directBuffer(); + ByteBuf directBuffer(int p0); + ByteBuf directBuffer(int p0, int p1); + ByteBuf heapBuffer(); + ByteBuf heapBuffer(int p0); + ByteBuf heapBuffer(int p0, int p1); + ByteBuf ioBuffer(); + ByteBuf ioBuffer(int p0); + ByteBuf ioBuffer(int p0, int p1); + CompositeByteBuf compositeBuffer(); + CompositeByteBuf compositeBuffer(int p0); + CompositeByteBuf compositeDirectBuffer(); + CompositeByteBuf compositeDirectBuffer(int p0); + CompositeByteBuf compositeHeapBuffer(); + CompositeByteBuf compositeHeapBuffer(int p0); + boolean isDirectBufferPooled(); + int calculateNewCapacity(int p0, int p1); + static ByteBufAllocator DEFAULT = null; +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufConvertible.java b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufConvertible.java new file mode 100644 index 00000000000..145e4f72565 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufConvertible.java @@ -0,0 +1,10 @@ +// Generated automatically from io.netty.buffer.ByteBufConvertible for testing purposes + +package io.netty.buffer; + +import io.netty.buffer.ByteBuf; + +public interface ByteBufConvertible +{ + ByteBuf asByteBuf(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufHolder.java b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufHolder.java new file mode 100644 index 00000000000..bed25be4032 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufHolder.java @@ -0,0 +1,19 @@ +// Generated automatically from io.netty.buffer.ByteBufHolder for testing purposes + +package io.netty.buffer; + +import io.netty.buffer.ByteBuf; +import io.netty.util.ReferenceCounted; + +public interface ByteBufHolder extends ReferenceCounted +{ + ByteBuf content(); + ByteBufHolder copy(); + ByteBufHolder duplicate(); + ByteBufHolder replace(ByteBuf p0); + ByteBufHolder retain(); + ByteBufHolder retain(int p0); + ByteBufHolder retainedDuplicate(); + ByteBufHolder touch(); + ByteBufHolder touch(Object p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufInputStream.java b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufInputStream.java new file mode 100644 index 00000000000..cb01654d4e7 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufInputStream.java @@ -0,0 +1,40 @@ +// Generated automatically from io.netty.buffer.ByteBufInputStream for testing purposes + +package io.netty.buffer; + +import io.netty.buffer.ByteBuf; +import java.io.DataInput; +import java.io.InputStream; + +public class ByteBufInputStream extends InputStream implements DataInput +{ + protected ByteBufInputStream() {} + public ByteBufInputStream(ByteBuf p0){} + public ByteBufInputStream(ByteBuf p0, boolean p1){} + public ByteBufInputStream(ByteBuf p0, int p1){} + public ByteBufInputStream(ByteBuf p0, int p1, boolean p2){} + public String readLine(){ return null; } + public String readUTF(){ return null; } + public boolean markSupported(){ return false; } + public boolean readBoolean(){ return false; } + public byte readByte(){ return 0; } + public char readChar(){ return '0'; } + public double readDouble(){ return 0; } + public float readFloat(){ return 0; } + public int available(){ return 0; } + public int read(){ return 0; } + public int read(byte[] p0, int p1, int p2){ return 0; } + public int readBytes(){ return 0; } + public int readInt(){ return 0; } + public int readUnsignedByte(){ return 0; } + public int readUnsignedShort(){ return 0; } + public int skipBytes(int p0){ return 0; } + public long readLong(){ return 0; } + public long skip(long p0){ return 0; } + public short readShort(){ return 0; } + public void close(){} + public void mark(int p0){} + public void readFully(byte[] p0){} + public void readFully(byte[] p0, int p1, int p2){} + public void reset(){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufOutputStream.java b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufOutputStream.java new file mode 100644 index 00000000000..868e7bd78c3 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufOutputStream.java @@ -0,0 +1,30 @@ +// Generated automatically from io.netty.buffer.ByteBufOutputStream for testing purposes + +package io.netty.buffer; + +import io.netty.buffer.ByteBuf; +import java.io.DataOutput; +import java.io.OutputStream; + +public class ByteBufOutputStream extends OutputStream implements DataOutput +{ + protected ByteBufOutputStream() {} + public ByteBuf buffer(){ return null; } + public ByteBufOutputStream(ByteBuf p0){} + public int writtenBytes(){ return 0; } + public void close(){} + public void write(byte[] p0){} + public void write(byte[] p0, int p1, int p2){} + public void write(int p0){} + public void writeBoolean(boolean p0){} + public void writeByte(int p0){} + public void writeBytes(String p0){} + public void writeChar(int p0){} + public void writeChars(String p0){} + public void writeDouble(double p0){} + public void writeFloat(float p0){} + public void writeInt(int p0){} + public void writeLong(long p0){} + public void writeShort(int p0){} + public void writeUTF(String p0){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufUtil.java b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufUtil.java new file mode 100644 index 00000000000..e9287e530d6 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/ByteBufUtil.java @@ -0,0 +1,64 @@ +// Generated automatically from io.netty.buffer.ByteBufUtil for testing purposes + +package io.netty.buffer; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.util.AsciiString; +import java.nio.CharBuffer; +import java.nio.charset.Charset; + +public class ByteBufUtil +{ + protected ByteBufUtil() {} + public static ByteBuf encodeString(ByteBufAllocator p0, CharBuffer p1, Charset p2){ return null; } + public static ByteBuf encodeString(ByteBufAllocator p0, CharBuffer p1, Charset p2, int p3){ return null; } + public static ByteBuf ensureAccessible(ByteBuf p0){ return null; } + public static ByteBuf readBytes(ByteBufAllocator p0, ByteBuf p1, int p2){ return null; } + public static ByteBuf setShortBE(ByteBuf p0, int p1, int p2){ return null; } + public static ByteBuf threadLocalDirectBuffer(){ return null; } + public static ByteBuf writeAscii(ByteBufAllocator p0, CharSequence p1){ return null; } + public static ByteBuf writeMediumBE(ByteBuf p0, int p1){ return null; } + public static ByteBuf writeShortBE(ByteBuf p0, int p1){ return null; } + public static ByteBuf writeUtf8(ByteBufAllocator p0, CharSequence p1){ return null; } + public static String hexDump(ByteBuf p0){ return null; } + public static String hexDump(ByteBuf p0, int p1, int p2){ return null; } + public static String hexDump(byte[] p0){ return null; } + public static String hexDump(byte[] p0, int p1, int p2){ return null; } + public static String prettyHexDump(ByteBuf p0){ return null; } + public static String prettyHexDump(ByteBuf p0, int p1, int p2){ return null; } + public static boolean ensureWritableSuccess(int p0){ return false; } + public static boolean equals(ByteBuf p0, ByteBuf p1){ return false; } + public static boolean equals(ByteBuf p0, int p1, ByteBuf p2, int p3, int p4){ return false; } + public static boolean isAccessible(ByteBuf p0){ return false; } + public static boolean isText(ByteBuf p0, Charset p1){ return false; } + public static boolean isText(ByteBuf p0, int p1, int p2, Charset p3){ return false; } + public static byte decodeHexByte(CharSequence p0, int p1){ return 0; } + public static byte[] decodeHexDump(CharSequence p0){ return null; } + public static byte[] decodeHexDump(CharSequence p0, int p1, int p2){ return null; } + public static byte[] getBytes(ByteBuf p0){ return null; } + public static byte[] getBytes(ByteBuf p0, int p1, int p2){ return null; } + public static byte[] getBytes(ByteBuf p0, int p1, int p2, boolean p3){ return null; } + public static int compare(ByteBuf p0, ByteBuf p1){ return 0; } + public static int hashCode(ByteBuf p0){ return 0; } + public static int indexOf(ByteBuf p0, ByteBuf p1){ return 0; } + public static int indexOf(ByteBuf p0, int p1, int p2, byte p3){ return 0; } + public static int reserveAndWriteUtf8(ByteBuf p0, CharSequence p1, int p2){ return 0; } + public static int reserveAndWriteUtf8(ByteBuf p0, CharSequence p1, int p2, int p3, int p4){ return 0; } + public static int swapInt(int p0){ return 0; } + public static int swapMedium(int p0){ return 0; } + public static int utf8Bytes(CharSequence p0){ return 0; } + public static int utf8Bytes(CharSequence p0, int p1, int p2){ return 0; } + public static int utf8MaxBytes(CharSequence p0){ return 0; } + public static int utf8MaxBytes(int p0){ return 0; } + public static int writeAscii(ByteBuf p0, CharSequence p1){ return 0; } + public static int writeUtf8(ByteBuf p0, CharSequence p1){ return 0; } + public static int writeUtf8(ByteBuf p0, CharSequence p1, int p2, int p3){ return 0; } + public static long swapLong(long p0){ return 0; } + public static short swapShort(short p0){ return 0; } + public static void appendPrettyHexDump(StringBuilder p0, ByteBuf p1){} + public static void appendPrettyHexDump(StringBuilder p0, ByteBuf p1, int p2, int p3){} + public static void copy(AsciiString p0, ByteBuf p1){} + public static void copy(AsciiString p0, int p1, ByteBuf p2, int p3){} + public static void copy(AsciiString p0, int p1, ByteBuf p2, int p3, int p4){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/CompositeByteBuf.java b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/CompositeByteBuf.java new file mode 100644 index 00000000000..87d0f0c4190 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/CompositeByteBuf.java @@ -0,0 +1,158 @@ +// Generated automatically from io.netty.buffer.CompositeByteBuf for testing purposes + +package io.netty.buffer; + +import io.netty.buffer.AbstractReferenceCountedByteBuf; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.util.ByteProcessor; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.channels.FileChannel; +import java.nio.channels.GatheringByteChannel; +import java.nio.channels.ScatteringByteChannel; +import java.util.Iterator; +import java.util.List; + +public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements Iterable +{ + protected CompositeByteBuf() {} + protected byte _getByte(int p0){ return 0; } + protected int _getInt(int p0){ return 0; } + protected int _getIntLE(int p0){ return 0; } + protected int _getUnsignedMedium(int p0){ return 0; } + protected int _getUnsignedMediumLE(int p0){ return 0; } + protected int forEachByteAsc0(int p0, int p1, ByteProcessor p2){ return 0; } + protected int forEachByteDesc0(int p0, int p1, ByteProcessor p2){ return 0; } + protected long _getLong(int p0){ return 0; } + protected long _getLongLE(int p0){ return 0; } + protected short _getShort(int p0){ return 0; } + protected short _getShortLE(int p0){ return 0; } + protected void _setByte(int p0, int p1){} + protected void _setInt(int p0, int p1){} + protected void _setIntLE(int p0, int p1){} + protected void _setLong(int p0, long p1){} + protected void _setLongLE(int p0, long p1){} + protected void _setMedium(int p0, int p1){} + protected void _setMediumLE(int p0, int p1){} + protected void _setShort(int p0, int p1){} + protected void _setShortLE(int p0, int p1){} + protected void deallocate(){} + public ByteBuf component(int p0){ return null; } + public ByteBuf componentAtOffset(int p0){ return null; } + public ByteBuf copy(int p0, int p1){ return null; } + public ByteBuf internalComponent(int p0){ return null; } + public ByteBuf internalComponentAtOffset(int p0){ return null; } + public ByteBuf unwrap(){ return null; } + public ByteBufAllocator alloc(){ return null; } + public ByteBuffer internalNioBuffer(int p0, int p1){ return null; } + public ByteBuffer nioBuffer(int p0, int p1){ return null; } + public ByteBuffer[] nioBuffers(){ return null; } + public ByteBuffer[] nioBuffers(int p0, int p1){ return null; } + public ByteOrder order(){ return null; } + public CompositeByteBuf addComponent(ByteBuf p0){ return null; } + public CompositeByteBuf addComponent(boolean p0, ByteBuf p1){ return null; } + public CompositeByteBuf addComponent(boolean p0, int p1, ByteBuf p2){ return null; } + public CompositeByteBuf addComponent(int p0, ByteBuf p1){ return null; } + public CompositeByteBuf addComponents(ByteBuf... p0){ return null; } + public CompositeByteBuf addComponents(Iterable p0){ return null; } + public CompositeByteBuf addComponents(boolean p0, ByteBuf... p1){ return null; } + public CompositeByteBuf addComponents(boolean p0, Iterable p1){ return null; } + public CompositeByteBuf addComponents(int p0, ByteBuf... p1){ return null; } + public CompositeByteBuf addComponents(int p0, Iterable p1){ return null; } + public CompositeByteBuf addFlattenedComponents(boolean p0, ByteBuf p1){ return null; } + public CompositeByteBuf capacity(int p0){ return null; } + public CompositeByteBuf clear(){ return null; } + public CompositeByteBuf consolidate(){ return null; } + public CompositeByteBuf consolidate(int p0, int p1){ return null; } + public CompositeByteBuf discardReadBytes(){ return null; } + public CompositeByteBuf discardReadComponents(){ return null; } + public CompositeByteBuf discardSomeReadBytes(){ return null; } + public CompositeByteBuf ensureWritable(int p0){ return null; } + public CompositeByteBuf getBytes(int p0, ByteBuf p1){ return null; } + public CompositeByteBuf getBytes(int p0, ByteBuf p1, int p2){ return null; } + public CompositeByteBuf getBytes(int p0, ByteBuf p1, int p2, int p3){ return null; } + public CompositeByteBuf getBytes(int p0, ByteBuffer p1){ return null; } + public CompositeByteBuf getBytes(int p0, OutputStream p1, int p2){ return null; } + public CompositeByteBuf getBytes(int p0, byte[] p1){ return null; } + public CompositeByteBuf getBytes(int p0, byte[] p1, int p2, int p3){ return null; } + public CompositeByteBuf markReaderIndex(){ return null; } + public CompositeByteBuf markWriterIndex(){ return null; } + public CompositeByteBuf readBytes(ByteBuf p0){ return null; } + public CompositeByteBuf readBytes(ByteBuf p0, int p1){ return null; } + public CompositeByteBuf readBytes(ByteBuf p0, int p1, int p2){ return null; } + public CompositeByteBuf readBytes(ByteBuffer p0){ return null; } + public CompositeByteBuf readBytes(OutputStream p0, int p1){ return null; } + public CompositeByteBuf readBytes(byte[] p0){ return null; } + public CompositeByteBuf readBytes(byte[] p0, int p1, int p2){ return null; } + public CompositeByteBuf readerIndex(int p0){ return null; } + public CompositeByteBuf removeComponent(int p0){ return null; } + public CompositeByteBuf removeComponents(int p0, int p1){ return null; } + public CompositeByteBuf resetReaderIndex(){ return null; } + public CompositeByteBuf resetWriterIndex(){ return null; } + public CompositeByteBuf retain(){ return null; } + public CompositeByteBuf retain(int p0){ return null; } + public CompositeByteBuf setBoolean(int p0, boolean p1){ return null; } + public CompositeByteBuf setByte(int p0, int p1){ return null; } + public CompositeByteBuf setBytes(int p0, ByteBuf p1){ return null; } + public CompositeByteBuf setBytes(int p0, ByteBuf p1, int p2){ return null; } + public CompositeByteBuf setBytes(int p0, ByteBuf p1, int p2, int p3){ return null; } + public CompositeByteBuf setBytes(int p0, ByteBuffer p1){ return null; } + public CompositeByteBuf setBytes(int p0, byte[] p1){ return null; } + public CompositeByteBuf setBytes(int p0, byte[] p1, int p2, int p3){ return null; } + public CompositeByteBuf setChar(int p0, int p1){ return null; } + public CompositeByteBuf setDouble(int p0, double p1){ return null; } + public CompositeByteBuf setFloat(int p0, float p1){ return null; } + public CompositeByteBuf setIndex(int p0, int p1){ return null; } + public CompositeByteBuf setInt(int p0, int p1){ return null; } + public CompositeByteBuf setLong(int p0, long p1){ return null; } + public CompositeByteBuf setMedium(int p0, int p1){ return null; } + public CompositeByteBuf setShort(int p0, int p1){ return null; } + public CompositeByteBuf setZero(int p0, int p1){ return null; } + public CompositeByteBuf skipBytes(int p0){ return null; } + public CompositeByteBuf touch(){ return null; } + public CompositeByteBuf touch(Object p0){ return null; } + public CompositeByteBuf writeBoolean(boolean p0){ return null; } + public CompositeByteBuf writeByte(int p0){ return null; } + public CompositeByteBuf writeBytes(ByteBuf p0){ return null; } + public CompositeByteBuf writeBytes(ByteBuf p0, int p1){ return null; } + public CompositeByteBuf writeBytes(ByteBuf p0, int p1, int p2){ return null; } + public CompositeByteBuf writeBytes(ByteBuffer p0){ return null; } + public CompositeByteBuf writeBytes(byte[] p0){ return null; } + public CompositeByteBuf writeBytes(byte[] p0, int p1, int p2){ return null; } + public CompositeByteBuf writeChar(int p0){ return null; } + public CompositeByteBuf writeDouble(double p0){ return null; } + public CompositeByteBuf writeFloat(float p0){ return null; } + public CompositeByteBuf writeInt(int p0){ return null; } + public CompositeByteBuf writeLong(long p0){ return null; } + public CompositeByteBuf writeMedium(int p0){ return null; } + public CompositeByteBuf writeShort(int p0){ return null; } + public CompositeByteBuf writeZero(int p0){ return null; } + public CompositeByteBuf writerIndex(int p0){ return null; } + public CompositeByteBuf(ByteBufAllocator p0, boolean p1, int p2){} + public CompositeByteBuf(ByteBufAllocator p0, boolean p1, int p2, ByteBuf... p3){} + public CompositeByteBuf(ByteBufAllocator p0, boolean p1, int p2, Iterable p3){} + public Iterator iterator(){ return null; } + public List decompose(int p0, int p1){ return null; } + public String toString(){ return null; } + public boolean hasArray(){ return false; } + public boolean hasMemoryAddress(){ return false; } + public boolean isDirect(){ return false; } + public byte getByte(int p0){ return 0; } + public byte[] array(){ return null; } + public int arrayOffset(){ return 0; } + public int capacity(){ return 0; } + public int getBytes(int p0, FileChannel p1, long p2, int p3){ return 0; } + public int getBytes(int p0, GatheringByteChannel p1, int p2){ return 0; } + public int maxNumComponents(){ return 0; } + public int nioBufferCount(){ return 0; } + public int numComponents(){ return 0; } + public int setBytes(int p0, FileChannel p1, long p2, int p3){ return 0; } + public int setBytes(int p0, InputStream p1, int p2){ return 0; } + public int setBytes(int p0, ScatteringByteChannel p1, int p2){ return 0; } + public int toByteIndex(int p0){ return 0; } + public int toComponentIndex(int p0){ return 0; } + public long memoryAddress(){ return 0; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/DefaultByteBufHolder.java b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/DefaultByteBufHolder.java new file mode 100644 index 00000000000..5da3e0ad3ce --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/DefaultByteBufHolder.java @@ -0,0 +1,28 @@ +// Generated automatically from io.netty.buffer.DefaultByteBufHolder for testing purposes + +package io.netty.buffer; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufHolder; + +public class DefaultByteBufHolder implements ByteBufHolder +{ + protected DefaultByteBufHolder() {} + protected final String contentToString(){ return null; } + public ByteBuf content(){ return null; } + public ByteBufHolder copy(){ return null; } + public ByteBufHolder duplicate(){ return null; } + public ByteBufHolder replace(ByteBuf p0){ return null; } + public ByteBufHolder retain(){ return null; } + public ByteBufHolder retain(int p0){ return null; } + public ByteBufHolder retainedDuplicate(){ return null; } + public ByteBufHolder touch(){ return null; } + public ByteBufHolder touch(Object p0){ return null; } + public DefaultByteBufHolder(ByteBuf p0){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean release(){ return false; } + public boolean release(int p0){ return false; } + public int hashCode(){ return 0; } + public int refCnt(){ return 0; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/SwappedByteBuf.java b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/SwappedByteBuf.java new file mode 100644 index 00000000000..d16fd06663f --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/SwappedByteBuf.java @@ -0,0 +1,206 @@ +// Generated automatically from io.netty.buffer.SwappedByteBuf for testing purposes + +package io.netty.buffer; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.util.ByteProcessor; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.channels.FileChannel; +import java.nio.channels.GatheringByteChannel; +import java.nio.channels.ScatteringByteChannel; +import java.nio.charset.Charset; + +public class SwappedByteBuf extends ByteBuf +{ + protected SwappedByteBuf() {} + public ByteBuf asReadOnly(){ return null; } + public ByteBuf capacity(int p0){ return null; } + public ByteBuf clear(){ return null; } + public ByteBuf copy(){ return null; } + public ByteBuf copy(int p0, int p1){ return null; } + public ByteBuf discardReadBytes(){ return null; } + public ByteBuf discardSomeReadBytes(){ return null; } + public ByteBuf duplicate(){ return null; } + public ByteBuf ensureWritable(int p0){ return null; } + public ByteBuf getBytes(int p0, ByteBuf p1){ return null; } + public ByteBuf getBytes(int p0, ByteBuf p1, int p2){ return null; } + public ByteBuf getBytes(int p0, ByteBuf p1, int p2, int p3){ return null; } + public ByteBuf getBytes(int p0, ByteBuffer p1){ return null; } + public ByteBuf getBytes(int p0, OutputStream p1, int p2){ return null; } + public ByteBuf getBytes(int p0, byte[] p1){ return null; } + public ByteBuf getBytes(int p0, byte[] p1, int p2, int p3){ return null; } + public ByteBuf markReaderIndex(){ return null; } + public ByteBuf markWriterIndex(){ return null; } + public ByteBuf order(ByteOrder p0){ return null; } + public ByteBuf readBytes(ByteBuf p0){ return null; } + public ByteBuf readBytes(ByteBuf p0, int p1){ return null; } + public ByteBuf readBytes(ByteBuf p0, int p1, int p2){ return null; } + public ByteBuf readBytes(ByteBuffer p0){ return null; } + public ByteBuf readBytes(OutputStream p0, int p1){ return null; } + public ByteBuf readBytes(byte[] p0){ return null; } + public ByteBuf readBytes(byte[] p0, int p1, int p2){ return null; } + public ByteBuf readBytes(int p0){ return null; } + public ByteBuf readRetainedSlice(int p0){ return null; } + public ByteBuf readSlice(int p0){ return null; } + public ByteBuf readerIndex(int p0){ return null; } + public ByteBuf resetReaderIndex(){ return null; } + public ByteBuf resetWriterIndex(){ return null; } + public ByteBuf retain(){ return null; } + public ByteBuf retain(int p0){ return null; } + public ByteBuf retainedDuplicate(){ return null; } + public ByteBuf retainedSlice(){ return null; } + public ByteBuf retainedSlice(int p0, int p1){ return null; } + public ByteBuf setBoolean(int p0, boolean p1){ return null; } + public ByteBuf setByte(int p0, int p1){ return null; } + public ByteBuf setBytes(int p0, ByteBuf p1){ return null; } + public ByteBuf setBytes(int p0, ByteBuf p1, int p2){ return null; } + public ByteBuf setBytes(int p0, ByteBuf p1, int p2, int p3){ return null; } + public ByteBuf setBytes(int p0, ByteBuffer p1){ return null; } + public ByteBuf setBytes(int p0, byte[] p1){ return null; } + public ByteBuf setBytes(int p0, byte[] p1, int p2, int p3){ return null; } + public ByteBuf setChar(int p0, int p1){ return null; } + public ByteBuf setDouble(int p0, double p1){ return null; } + public ByteBuf setFloat(int p0, float p1){ return null; } + public ByteBuf setIndex(int p0, int p1){ return null; } + public ByteBuf setInt(int p0, int p1){ return null; } + public ByteBuf setIntLE(int p0, int p1){ return null; } + public ByteBuf setLong(int p0, long p1){ return null; } + public ByteBuf setLongLE(int p0, long p1){ return null; } + public ByteBuf setMedium(int p0, int p1){ return null; } + public ByteBuf setMediumLE(int p0, int p1){ return null; } + public ByteBuf setShort(int p0, int p1){ return null; } + public ByteBuf setShortLE(int p0, int p1){ return null; } + public ByteBuf setZero(int p0, int p1){ return null; } + public ByteBuf skipBytes(int p0){ return null; } + public ByteBuf slice(){ return null; } + public ByteBuf slice(int p0, int p1){ return null; } + public ByteBuf touch(){ return null; } + public ByteBuf touch(Object p0){ return null; } + public ByteBuf unwrap(){ return null; } + public ByteBuf writeBoolean(boolean p0){ return null; } + public ByteBuf writeByte(int p0){ return null; } + public ByteBuf writeBytes(ByteBuf p0){ return null; } + public ByteBuf writeBytes(ByteBuf p0, int p1){ return null; } + public ByteBuf writeBytes(ByteBuf p0, int p1, int p2){ return null; } + public ByteBuf writeBytes(ByteBuffer p0){ return null; } + public ByteBuf writeBytes(byte[] p0){ return null; } + public ByteBuf writeBytes(byte[] p0, int p1, int p2){ return null; } + public ByteBuf writeChar(int p0){ return null; } + public ByteBuf writeDouble(double p0){ return null; } + public ByteBuf writeFloat(float p0){ return null; } + public ByteBuf writeInt(int p0){ return null; } + public ByteBuf writeIntLE(int p0){ return null; } + public ByteBuf writeLong(long p0){ return null; } + public ByteBuf writeLongLE(long p0){ return null; } + public ByteBuf writeMedium(int p0){ return null; } + public ByteBuf writeMediumLE(int p0){ return null; } + public ByteBuf writeShort(int p0){ return null; } + public ByteBuf writeShortLE(int p0){ return null; } + public ByteBuf writeZero(int p0){ return null; } + public ByteBuf writerIndex(int p0){ return null; } + public ByteBufAllocator alloc(){ return null; } + public ByteBuffer internalNioBuffer(int p0, int p1){ return null; } + public ByteBuffer nioBuffer(){ return null; } + public ByteBuffer nioBuffer(int p0, int p1){ return null; } + public ByteBuffer[] nioBuffers(){ return null; } + public ByteBuffer[] nioBuffers(int p0, int p1){ return null; } + public ByteOrder order(){ return null; } + public CharSequence getCharSequence(int p0, int p1, Charset p2){ return null; } + public CharSequence readCharSequence(int p0, Charset p1){ return null; } + public String toString(){ return null; } + public String toString(Charset p0){ return null; } + public String toString(int p0, int p1, Charset p2){ return null; } + public SwappedByteBuf(ByteBuf p0){} + public boolean equals(Object p0){ return false; } + public boolean getBoolean(int p0){ return false; } + public boolean hasArray(){ return false; } + public boolean hasMemoryAddress(){ return false; } + public boolean isContiguous(){ return false; } + public boolean isDirect(){ return false; } + public boolean isReadOnly(){ return false; } + public boolean isReadable(){ return false; } + public boolean isReadable(int p0){ return false; } + public boolean isWritable(){ return false; } + public boolean isWritable(int p0){ return false; } + public boolean readBoolean(){ return false; } + public boolean release(){ return false; } + public boolean release(int p0){ return false; } + public byte getByte(int p0){ return 0; } + public byte readByte(){ return 0; } + public byte[] array(){ return null; } + public char getChar(int p0){ return '0'; } + public char readChar(){ return '0'; } + public double getDouble(int p0){ return 0; } + public double readDouble(){ return 0; } + public float getFloat(int p0){ return 0; } + public float readFloat(){ return 0; } + public int arrayOffset(){ return 0; } + public int bytesBefore(byte p0){ return 0; } + public int bytesBefore(int p0, byte p1){ return 0; } + public int bytesBefore(int p0, int p1, byte p2){ return 0; } + public int capacity(){ return 0; } + public int compareTo(ByteBuf p0){ return 0; } + public int ensureWritable(int p0, boolean p1){ return 0; } + public int forEachByte(ByteProcessor p0){ return 0; } + public int forEachByte(int p0, int p1, ByteProcessor p2){ return 0; } + public int forEachByteDesc(ByteProcessor p0){ return 0; } + public int forEachByteDesc(int p0, int p1, ByteProcessor p2){ return 0; } + public int getBytes(int p0, FileChannel p1, long p2, int p3){ return 0; } + public int getBytes(int p0, GatheringByteChannel p1, int p2){ return 0; } + public int getInt(int p0){ return 0; } + public int getIntLE(int p0){ return 0; } + public int getMedium(int p0){ return 0; } + public int getMediumLE(int p0){ return 0; } + public int getUnsignedMedium(int p0){ return 0; } + public int getUnsignedMediumLE(int p0){ return 0; } + public int getUnsignedShort(int p0){ return 0; } + public int getUnsignedShortLE(int p0){ return 0; } + public int hashCode(){ return 0; } + public int indexOf(int p0, int p1, byte p2){ return 0; } + public int maxCapacity(){ return 0; } + public int maxFastWritableBytes(){ return 0; } + public int maxWritableBytes(){ return 0; } + public int nioBufferCount(){ return 0; } + public int readBytes(FileChannel p0, long p1, int p2){ return 0; } + public int readBytes(GatheringByteChannel p0, int p1){ return 0; } + public int readInt(){ return 0; } + public int readIntLE(){ return 0; } + public int readMedium(){ return 0; } + public int readMediumLE(){ return 0; } + public int readUnsignedMedium(){ return 0; } + public int readUnsignedMediumLE(){ return 0; } + public int readUnsignedShort(){ return 0; } + public int readUnsignedShortLE(){ return 0; } + public int readableBytes(){ return 0; } + public int readerIndex(){ return 0; } + public int refCnt(){ return 0; } + public int setBytes(int p0, FileChannel p1, long p2, int p3){ return 0; } + public int setBytes(int p0, InputStream p1, int p2){ return 0; } + public int setBytes(int p0, ScatteringByteChannel p1, int p2){ return 0; } + public int setCharSequence(int p0, CharSequence p1, Charset p2){ return 0; } + public int writableBytes(){ return 0; } + public int writeBytes(FileChannel p0, long p1, int p2){ return 0; } + public int writeBytes(InputStream p0, int p1){ return 0; } + public int writeBytes(ScatteringByteChannel p0, int p1){ return 0; } + public int writeCharSequence(CharSequence p0, Charset p1){ return 0; } + public int writerIndex(){ return 0; } + public long getLong(int p0){ return 0; } + public long getLongLE(int p0){ return 0; } + public long getUnsignedInt(int p0){ return 0; } + public long getUnsignedIntLE(int p0){ return 0; } + public long memoryAddress(){ return 0; } + public long readLong(){ return 0; } + public long readLongLE(){ return 0; } + public long readUnsignedInt(){ return 0; } + public long readUnsignedIntLE(){ return 0; } + public short getShort(int p0){ return 0; } + public short getShortLE(int p0){ return 0; } + public short getUnsignedByte(int p0){ return 0; } + public short readShort(){ return 0; } + public short readShortLE(){ return 0; } + public short readUnsignedByte(){ return 0; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/Unpooled.java b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/Unpooled.java new file mode 100644 index 00000000000..4d4c0c58dce --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/buffer/Unpooled.java @@ -0,0 +1,66 @@ +// Generated automatically from io.netty.buffer.Unpooled for testing purposes + +package io.netty.buffer; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.CompositeByteBuf; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.Charset; + +public class Unpooled +{ + protected Unpooled() {} + public static ByteBuf EMPTY_BUFFER = null; + public static ByteBuf buffer(){ return null; } + public static ByteBuf buffer(int p0){ return null; } + public static ByteBuf buffer(int p0, int p1){ return null; } + public static ByteBuf copiedBuffer(ByteBuf p0){ return null; } + public static ByteBuf copiedBuffer(ByteBuf... p0){ return null; } + public static ByteBuf copiedBuffer(ByteBuffer p0){ return null; } + public static ByteBuf copiedBuffer(ByteBuffer... p0){ return null; } + public static ByteBuf copiedBuffer(CharSequence p0, Charset p1){ return null; } + public static ByteBuf copiedBuffer(CharSequence p0, int p1, int p2, Charset p3){ return null; } + public static ByteBuf copiedBuffer(byte[] p0){ return null; } + public static ByteBuf copiedBuffer(byte[] p0, int p1, int p2){ return null; } + public static ByteBuf copiedBuffer(byte[]... p0){ return null; } + public static ByteBuf copiedBuffer(char[] p0, Charset p1){ return null; } + public static ByteBuf copiedBuffer(char[] p0, int p1, int p2, Charset p3){ return null; } + public static ByteBuf copyBoolean(boolean p0){ return null; } + public static ByteBuf copyBoolean(boolean... p0){ return null; } + public static ByteBuf copyDouble(double p0){ return null; } + public static ByteBuf copyDouble(double... p0){ return null; } + public static ByteBuf copyFloat(float p0){ return null; } + public static ByteBuf copyFloat(float... p0){ return null; } + public static ByteBuf copyInt(int p0){ return null; } + public static ByteBuf copyInt(int... p0){ return null; } + public static ByteBuf copyLong(long p0){ return null; } + public static ByteBuf copyLong(long... p0){ return null; } + public static ByteBuf copyMedium(int p0){ return null; } + public static ByteBuf copyMedium(int... p0){ return null; } + public static ByteBuf copyShort(int p0){ return null; } + public static ByteBuf copyShort(int... p0){ return null; } + public static ByteBuf copyShort(short... p0){ return null; } + public static ByteBuf directBuffer(){ return null; } + public static ByteBuf directBuffer(int p0){ return null; } + public static ByteBuf directBuffer(int p0, int p1){ return null; } + public static ByteBuf unmodifiableBuffer(ByteBuf p0){ return null; } + public static ByteBuf unmodifiableBuffer(ByteBuf... p0){ return null; } + public static ByteBuf unreleasableBuffer(ByteBuf p0){ return null; } + public static ByteBuf wrappedBuffer(ByteBuf p0){ return null; } + public static ByteBuf wrappedBuffer(ByteBuf... p0){ return null; } + public static ByteBuf wrappedBuffer(ByteBuffer p0){ return null; } + public static ByteBuf wrappedBuffer(ByteBuffer... p0){ return null; } + public static ByteBuf wrappedBuffer(byte[] p0){ return null; } + public static ByteBuf wrappedBuffer(byte[] p0, int p1, int p2){ return null; } + public static ByteBuf wrappedBuffer(byte[]... p0){ return null; } + public static ByteBuf wrappedBuffer(int p0, ByteBuf... p1){ return null; } + public static ByteBuf wrappedBuffer(int p0, ByteBuffer... p1){ return null; } + public static ByteBuf wrappedBuffer(int p0, byte[]... p1){ return null; } + public static ByteBuf wrappedBuffer(long p0, int p1, boolean p2){ return null; } + public static ByteBuf wrappedUnmodifiableBuffer(ByteBuf... p0){ return null; } + public static ByteOrder BIG_ENDIAN = null; + public static ByteOrder LITTLE_ENDIAN = null; + public static CompositeByteBuf compositeBuffer(){ return null; } + public static CompositeByteBuf compositeBuffer(int p0){ return null; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/Channel.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/Channel.java new file mode 100644 index 00000000000..e3252ed33c8 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/Channel.java @@ -0,0 +1,58 @@ +// Generated automatically from io.netty.channel.Channel for testing purposes + +package io.netty.channel; + +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelConfig; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelId; +import io.netty.channel.ChannelMetadata; +import io.netty.channel.ChannelOutboundBuffer; +import io.netty.channel.ChannelOutboundInvoker; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.ChannelPromise; +import io.netty.channel.EventLoop; +import io.netty.channel.RecvByteBufAllocator; +import io.netty.util.AttributeMap; +import java.net.SocketAddress; + +public interface Channel extends AttributeMap, ChannelOutboundInvoker, Comparable +{ + ByteBufAllocator alloc(); + Channel flush(); + Channel parent(); + Channel read(); + Channel.Unsafe unsafe(); + ChannelConfig config(); + ChannelFuture closeFuture(); + ChannelId id(); + ChannelMetadata metadata(); + ChannelPipeline pipeline(); + EventLoop eventLoop(); + SocketAddress localAddress(); + SocketAddress remoteAddress(); + boolean isActive(); + boolean isOpen(); + boolean isRegistered(); + boolean isWritable(); + long bytesBeforeUnwritable(); + long bytesBeforeWritable(); + static public interface Unsafe + { + ChannelOutboundBuffer outboundBuffer(); + ChannelPromise voidPromise(); + RecvByteBufAllocator.Handle recvBufAllocHandle(); + SocketAddress localAddress(); + SocketAddress remoteAddress(); + void beginRead(); + void bind(SocketAddress p0, ChannelPromise p1); + void close(ChannelPromise p0); + void closeForcibly(); + void connect(SocketAddress p0, SocketAddress p1, ChannelPromise p2); + void deregister(ChannelPromise p0); + void disconnect(ChannelPromise p0); + void flush(); + void register(EventLoop p0, ChannelPromise p1); + void write(Object p0, ChannelPromise p1); + } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelConfig.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelConfig.java new file mode 100644 index 00000000000..b62888f8bb6 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelConfig.java @@ -0,0 +1,40 @@ +// Generated automatically from io.netty.channel.ChannelConfig for testing purposes + +package io.netty.channel; + +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelOption; +import io.netty.channel.MessageSizeEstimator; +import io.netty.channel.RecvByteBufAllocator; +import io.netty.channel.WriteBufferWaterMark; +import java.util.Map; + +public interface ChannelConfig +{ + T getRecvByteBufAllocator(); + T getOption(io.netty.channel.ChannelOption p0); + boolean setOption(io.netty.channel.ChannelOption p0, T p1); + ByteBufAllocator getAllocator(); + ChannelConfig setAllocator(ByteBufAllocator p0); + ChannelConfig setAutoClose(boolean p0); + ChannelConfig setAutoRead(boolean p0); + ChannelConfig setConnectTimeoutMillis(int p0); + ChannelConfig setMaxMessagesPerRead(int p0); + ChannelConfig setMessageSizeEstimator(MessageSizeEstimator p0); + ChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator p0); + ChannelConfig setWriteBufferHighWaterMark(int p0); + ChannelConfig setWriteBufferLowWaterMark(int p0); + ChannelConfig setWriteBufferWaterMark(WriteBufferWaterMark p0); + ChannelConfig setWriteSpinCount(int p0); + Map, Object> getOptions(); + MessageSizeEstimator getMessageSizeEstimator(); + WriteBufferWaterMark getWriteBufferWaterMark(); + boolean isAutoClose(); + boolean isAutoRead(); + boolean setOptions(Map, ? extends Object> p0); + int getConnectTimeoutMillis(); + int getMaxMessagesPerRead(); + int getWriteBufferHighWaterMark(); + int getWriteBufferLowWaterMark(); + int getWriteSpinCount(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelFuture.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelFuture.java new file mode 100644 index 00000000000..d03340e6290 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelFuture.java @@ -0,0 +1,20 @@ +// Generated automatically from io.netty.channel.ChannelFuture for testing purposes + +package io.netty.channel; + +import io.netty.channel.Channel; +import io.netty.util.concurrent.GenericFutureListener; + +public interface ChannelFuture extends io.netty.util.concurrent.Future +{ + Channel channel(); + ChannelFuture addListener(GenericFutureListener> p0); + ChannelFuture addListeners(GenericFutureListener>... p0); + ChannelFuture await(); + ChannelFuture awaitUninterruptibly(); + ChannelFuture removeListener(GenericFutureListener> p0); + ChannelFuture removeListeners(GenericFutureListener>... p0); + ChannelFuture sync(); + ChannelFuture syncUninterruptibly(); + boolean isVoid(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelHandler.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelHandler.java new file mode 100644 index 00000000000..d82464df94b --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelHandler.java @@ -0,0 +1,12 @@ +// Generated automatically from io.netty.channel.ChannelHandler for testing purposes + +package io.netty.channel; + +import io.netty.channel.ChannelHandlerContext; + +public interface ChannelHandler +{ + void exceptionCaught(ChannelHandlerContext p0, Throwable p1); + void handlerAdded(ChannelHandlerContext p0); + void handlerRemoved(ChannelHandlerContext p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelHandlerAdapter.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelHandlerAdapter.java new file mode 100644 index 00000000000..1cf2749e183 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelHandlerAdapter.java @@ -0,0 +1,16 @@ +// Generated automatically from io.netty.channel.ChannelHandlerAdapter for testing purposes + +package io.netty.channel; + +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; + +abstract public class ChannelHandlerAdapter implements ChannelHandler +{ + protected void ensureNotSharable(){} + public ChannelHandlerAdapter(){} + public boolean isSharable(){ return false; } + public void exceptionCaught(ChannelHandlerContext p0, Throwable p1){} + public void handlerAdded(ChannelHandlerContext p0){} + public void handlerRemoved(ChannelHandlerContext p0){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelHandlerContext.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelHandlerContext.java new file mode 100644 index 00000000000..016f043a665 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelHandlerContext.java @@ -0,0 +1,38 @@ +// Generated automatically from io.netty.channel.ChannelHandlerContext for testing purposes + +package io.netty.channel; + +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInboundInvoker; +import io.netty.channel.ChannelOutboundInvoker; +import io.netty.channel.ChannelPipeline; +import io.netty.util.Attribute; +import io.netty.util.AttributeKey; +import io.netty.util.AttributeMap; +import io.netty.util.concurrent.EventExecutor; + +public interface ChannelHandlerContext extends AttributeMap, ChannelInboundInvoker, ChannelOutboundInvoker +{ + boolean hasAttr(io.netty.util.AttributeKey p0); + io.netty.util.Attribute attr(io.netty.util.AttributeKey p0); + ByteBufAllocator alloc(); + Channel channel(); + ChannelHandler handler(); + ChannelHandlerContext fireChannelActive(); + ChannelHandlerContext fireChannelInactive(); + ChannelHandlerContext fireChannelRead(Object p0); + ChannelHandlerContext fireChannelReadComplete(); + ChannelHandlerContext fireChannelRegistered(); + ChannelHandlerContext fireChannelUnregistered(); + ChannelHandlerContext fireChannelWritabilityChanged(); + ChannelHandlerContext fireExceptionCaught(Throwable p0); + ChannelHandlerContext fireUserEventTriggered(Object p0); + ChannelHandlerContext flush(); + ChannelHandlerContext read(); + ChannelPipeline pipeline(); + EventExecutor executor(); + String name(); + boolean isRemoved(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelId.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelId.java new file mode 100644 index 00000000000..88ecea3e327 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelId.java @@ -0,0 +1,11 @@ +// Generated automatically from io.netty.channel.ChannelId for testing purposes + +package io.netty.channel; + +import java.io.Serializable; + +public interface ChannelId extends Comparable, Serializable +{ + String asLongText(); + String asShortText(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelInboundHandler.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelInboundHandler.java new file mode 100644 index 00000000000..485bcb0ba91 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelInboundHandler.java @@ -0,0 +1,19 @@ +// Generated automatically from io.netty.channel.ChannelInboundHandler for testing purposes + +package io.netty.channel; + +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; + +public interface ChannelInboundHandler extends ChannelHandler +{ + void channelActive(ChannelHandlerContext p0); + void channelInactive(ChannelHandlerContext p0); + void channelRead(ChannelHandlerContext p0, Object p1); + void channelReadComplete(ChannelHandlerContext p0); + void channelRegistered(ChannelHandlerContext p0); + void channelUnregistered(ChannelHandlerContext p0); + void channelWritabilityChanged(ChannelHandlerContext p0); + void exceptionCaught(ChannelHandlerContext p0, Throwable p1); + void userEventTriggered(ChannelHandlerContext p0, Object p1); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelInboundHandlerAdapter.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelInboundHandlerAdapter.java new file mode 100644 index 00000000000..cc775515e6b --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelInboundHandlerAdapter.java @@ -0,0 +1,21 @@ +// Generated automatically from io.netty.channel.ChannelInboundHandlerAdapter for testing purposes + +package io.netty.channel; + +import io.netty.channel.ChannelHandlerAdapter; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandler; + +public class ChannelInboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelInboundHandler +{ + public ChannelInboundHandlerAdapter(){} + public void channelActive(ChannelHandlerContext p0){} + public void channelInactive(ChannelHandlerContext p0){} + public void channelRead(ChannelHandlerContext p0, Object p1){} + public void channelReadComplete(ChannelHandlerContext p0){} + public void channelRegistered(ChannelHandlerContext p0){} + public void channelUnregistered(ChannelHandlerContext p0){} + public void channelWritabilityChanged(ChannelHandlerContext p0){} + public void exceptionCaught(ChannelHandlerContext p0, Throwable p1){} + public void userEventTriggered(ChannelHandlerContext p0, Object p1){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelInboundInvoker.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelInboundInvoker.java new file mode 100644 index 00000000000..e0e73b5b871 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelInboundInvoker.java @@ -0,0 +1,17 @@ +// Generated automatically from io.netty.channel.ChannelInboundInvoker for testing purposes + +package io.netty.channel; + + +public interface ChannelInboundInvoker +{ + ChannelInboundInvoker fireChannelActive(); + ChannelInboundInvoker fireChannelInactive(); + ChannelInboundInvoker fireChannelRead(Object p0); + ChannelInboundInvoker fireChannelReadComplete(); + ChannelInboundInvoker fireChannelRegistered(); + ChannelInboundInvoker fireChannelUnregistered(); + ChannelInboundInvoker fireChannelWritabilityChanged(); + ChannelInboundInvoker fireExceptionCaught(Throwable p0); + ChannelInboundInvoker fireUserEventTriggered(Object p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelMetadata.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelMetadata.java new file mode 100644 index 00000000000..5f21a3e3d95 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelMetadata.java @@ -0,0 +1,13 @@ +// Generated automatically from io.netty.channel.ChannelMetadata for testing purposes + +package io.netty.channel; + + +public class ChannelMetadata +{ + protected ChannelMetadata() {} + public ChannelMetadata(boolean p0){} + public ChannelMetadata(boolean p0, int p1){} + public boolean hasDisconnect(){ return false; } + public int defaultMaxMessagesPerRead(){ return 0; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelOption.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelOption.java new file mode 100644 index 00000000000..b47513d23f6 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelOption.java @@ -0,0 +1,53 @@ +// Generated automatically from io.netty.channel.ChannelOption for testing purposes + +package io.netty.channel; + +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.MessageSizeEstimator; +import io.netty.channel.RecvByteBufAllocator; +import io.netty.channel.WriteBufferWaterMark; +import io.netty.util.AbstractConstant; +import java.net.InetAddress; +import java.net.NetworkInterface; + +public class ChannelOption extends AbstractConstant> +{ + protected ChannelOption() {} + protected ChannelOption(String p0){} + public static io.netty.channel.ChannelOption newInstance(String p0){ return null; } + public static io.netty.channel.ChannelOption valueOf(Class p0, String p1){ return null; } + public static io.netty.channel.ChannelOption valueOf(String p0){ return null; } + public static ChannelOption ALLOW_HALF_CLOSURE = null; + public static ChannelOption AUTO_CLOSE = null; + public static ChannelOption AUTO_READ = null; + public static ChannelOption DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION = null; + public static ChannelOption IP_MULTICAST_LOOP_DISABLED = null; + public static ChannelOption SINGLE_EVENTEXECUTOR_PER_GROUP = null; + public static ChannelOption SO_BROADCAST = null; + public static ChannelOption SO_KEEPALIVE = null; + public static ChannelOption SO_REUSEADDR = null; + public static ChannelOption TCP_FASTOPEN_CONNECT = null; + public static ChannelOption TCP_NODELAY = null; + public static ChannelOption ALLOCATOR = null; + public static ChannelOption IP_MULTICAST_ADDR = null; + public static ChannelOption CONNECT_TIMEOUT_MILLIS = null; + public static ChannelOption IP_MULTICAST_TTL = null; + public static ChannelOption IP_TOS = null; + public static ChannelOption MAX_MESSAGES_PER_READ = null; + public static ChannelOption MAX_MESSAGES_PER_WRITE = null; + public static ChannelOption SO_BACKLOG = null; + public static ChannelOption SO_LINGER = null; + public static ChannelOption SO_RCVBUF = null; + public static ChannelOption SO_SNDBUF = null; + public static ChannelOption SO_TIMEOUT = null; + public static ChannelOption TCP_FASTOPEN = null; + public static ChannelOption WRITE_BUFFER_HIGH_WATER_MARK = null; + public static ChannelOption WRITE_BUFFER_LOW_WATER_MARK = null; + public static ChannelOption WRITE_SPIN_COUNT = null; + public static ChannelOption MESSAGE_SIZE_ESTIMATOR = null; + public static ChannelOption IP_MULTICAST_IF = null; + public static ChannelOption RCVBUF_ALLOCATOR = null; + public static ChannelOption WRITE_BUFFER_WATER_MARK = null; + public static boolean exists(String p0){ return false; } + public void validate(T p0){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelOutboundBuffer.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelOutboundBuffer.java new file mode 100644 index 00000000000..537b52f874c --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelOutboundBuffer.java @@ -0,0 +1,37 @@ +// Generated automatically from io.netty.channel.ChannelOutboundBuffer for testing purposes + +package io.netty.channel; + +import io.netty.channel.ChannelPromise; +import java.nio.ByteBuffer; + +public class ChannelOutboundBuffer +{ + protected ChannelOutboundBuffer() {} + public ByteBuffer[] nioBuffers(){ return null; } + public ByteBuffer[] nioBuffers(int p0, long p1){ return null; } + public Object current(){ return null; } + public boolean getUserDefinedWritability(int p0){ return false; } + public boolean isEmpty(){ return false; } + public boolean isWritable(){ return false; } + public boolean remove(){ return false; } + public boolean remove(Throwable p0){ return false; } + public int nioBufferCount(){ return 0; } + public int size(){ return 0; } + public long bytesBeforeUnwritable(){ return 0; } + public long bytesBeforeWritable(){ return 0; } + public long currentProgress(){ return 0; } + public long nioBufferSize(){ return 0; } + public long totalPendingWriteBytes(){ return 0; } + public void addFlush(){} + public void addMessage(Object p0, int p1, ChannelPromise p2){} + public void forEachFlushedMessage(ChannelOutboundBuffer.MessageProcessor p0){} + public void progress(long p0){} + public void recycle(){} + public void removeBytes(long p0){} + public void setUserDefinedWritability(int p0, boolean p1){} + static public interface MessageProcessor + { + boolean processMessage(Object p0); + } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelOutboundInvoker.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelOutboundInvoker.java new file mode 100644 index 00000000000..cd034b1ae63 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelOutboundInvoker.java @@ -0,0 +1,35 @@ +// Generated automatically from io.netty.channel.ChannelOutboundInvoker for testing purposes + +package io.netty.channel; + +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelProgressivePromise; +import io.netty.channel.ChannelPromise; +import java.net.SocketAddress; + +public interface ChannelOutboundInvoker +{ + ChannelFuture bind(SocketAddress p0); + ChannelFuture bind(SocketAddress p0, ChannelPromise p1); + ChannelFuture close(); + ChannelFuture close(ChannelPromise p0); + ChannelFuture connect(SocketAddress p0); + ChannelFuture connect(SocketAddress p0, ChannelPromise p1); + ChannelFuture connect(SocketAddress p0, SocketAddress p1); + ChannelFuture connect(SocketAddress p0, SocketAddress p1, ChannelPromise p2); + ChannelFuture deregister(); + ChannelFuture deregister(ChannelPromise p0); + ChannelFuture disconnect(); + ChannelFuture disconnect(ChannelPromise p0); + ChannelFuture newFailedFuture(Throwable p0); + ChannelFuture newSucceededFuture(); + ChannelFuture write(Object p0); + ChannelFuture write(Object p0, ChannelPromise p1); + ChannelFuture writeAndFlush(Object p0); + ChannelFuture writeAndFlush(Object p0, ChannelPromise p1); + ChannelOutboundInvoker flush(); + ChannelOutboundInvoker read(); + ChannelProgressivePromise newProgressivePromise(); + ChannelPromise newPromise(); + ChannelPromise voidPromise(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelPipeline.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelPipeline.java new file mode 100644 index 00000000000..86ad380d93f --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelPipeline.java @@ -0,0 +1,58 @@ +// Generated automatically from io.netty.channel.ChannelPipeline for testing purposes + +package io.netty.channel; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundInvoker; +import io.netty.channel.ChannelOutboundInvoker; +import io.netty.util.concurrent.EventExecutorGroup; +import java.util.List; +import java.util.Map; + +public interface ChannelPipeline extends ChannelInboundInvoker, ChannelOutboundInvoker, Iterable> +{ + T get(java.lang.Class p0); + T remove(java.lang.Class p0); + T replace(java.lang.Class p0, String p1, ChannelHandler p2); + Channel channel(); + ChannelHandler first(); + ChannelHandler get(String p0); + ChannelHandler last(); + ChannelHandler remove(String p0); + ChannelHandler removeFirst(); + ChannelHandler removeLast(); + ChannelHandler replace(String p0, String p1, ChannelHandler p2); + ChannelHandlerContext context(ChannelHandler p0); + ChannelHandlerContext context(Class p0); + ChannelHandlerContext context(String p0); + ChannelHandlerContext firstContext(); + ChannelHandlerContext lastContext(); + ChannelPipeline addAfter(EventExecutorGroup p0, String p1, String p2, ChannelHandler p3); + ChannelPipeline addAfter(String p0, String p1, ChannelHandler p2); + ChannelPipeline addBefore(EventExecutorGroup p0, String p1, String p2, ChannelHandler p3); + ChannelPipeline addBefore(String p0, String p1, ChannelHandler p2); + ChannelPipeline addFirst(ChannelHandler... p0); + ChannelPipeline addFirst(EventExecutorGroup p0, ChannelHandler... p1); + ChannelPipeline addFirst(EventExecutorGroup p0, String p1, ChannelHandler p2); + ChannelPipeline addFirst(String p0, ChannelHandler p1); + ChannelPipeline addLast(ChannelHandler... p0); + ChannelPipeline addLast(EventExecutorGroup p0, ChannelHandler... p1); + ChannelPipeline addLast(EventExecutorGroup p0, String p1, ChannelHandler p2); + ChannelPipeline addLast(String p0, ChannelHandler p1); + ChannelPipeline fireChannelActive(); + ChannelPipeline fireChannelInactive(); + ChannelPipeline fireChannelRead(Object p0); + ChannelPipeline fireChannelReadComplete(); + ChannelPipeline fireChannelRegistered(); + ChannelPipeline fireChannelUnregistered(); + ChannelPipeline fireChannelWritabilityChanged(); + ChannelPipeline fireExceptionCaught(Throwable p0); + ChannelPipeline fireUserEventTriggered(Object p0); + ChannelPipeline flush(); + ChannelPipeline remove(ChannelHandler p0); + ChannelPipeline replace(ChannelHandler p0, String p1, ChannelHandler p2); + List names(); + Map toMap(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelProgressiveFuture.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelProgressiveFuture.java new file mode 100644 index 00000000000..6306d8dfb89 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelProgressiveFuture.java @@ -0,0 +1,19 @@ +// Generated automatically from io.netty.channel.ChannelProgressiveFuture for testing purposes + +package io.netty.channel; + +import io.netty.channel.ChannelFuture; +import io.netty.util.concurrent.GenericFutureListener; +import io.netty.util.concurrent.ProgressiveFuture; + +public interface ChannelProgressiveFuture extends ChannelFuture, ProgressiveFuture +{ + ChannelProgressiveFuture addListener(GenericFutureListener> p0); + ChannelProgressiveFuture addListeners(GenericFutureListener>... p0); + ChannelProgressiveFuture await(); + ChannelProgressiveFuture awaitUninterruptibly(); + ChannelProgressiveFuture removeListener(GenericFutureListener> p0); + ChannelProgressiveFuture removeListeners(GenericFutureListener>... p0); + ChannelProgressiveFuture sync(); + ChannelProgressiveFuture syncUninterruptibly(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelProgressivePromise.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelProgressivePromise.java new file mode 100644 index 00000000000..c315415341e --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelProgressivePromise.java @@ -0,0 +1,25 @@ +// Generated automatically from io.netty.channel.ChannelProgressivePromise for testing purposes + +package io.netty.channel; + +import io.netty.channel.ChannelProgressiveFuture; +import io.netty.channel.ChannelPromise; +import io.netty.util.concurrent.GenericFutureListener; +import io.netty.util.concurrent.ProgressivePromise; + +public interface ChannelProgressivePromise extends ChannelProgressiveFuture, ChannelPromise, ProgressivePromise +{ + ChannelProgressivePromise addListener(GenericFutureListener> p0); + ChannelProgressivePromise addListeners(GenericFutureListener>... p0); + ChannelProgressivePromise await(); + ChannelProgressivePromise awaitUninterruptibly(); + ChannelProgressivePromise removeListener(GenericFutureListener> p0); + ChannelProgressivePromise removeListeners(GenericFutureListener>... p0); + ChannelProgressivePromise setFailure(Throwable p0); + ChannelProgressivePromise setProgress(long p0, long p1); + ChannelProgressivePromise setSuccess(); + ChannelProgressivePromise setSuccess(Void p0); + ChannelProgressivePromise sync(); + ChannelProgressivePromise syncUninterruptibly(); + ChannelProgressivePromise unvoid(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelPromise.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelPromise.java new file mode 100644 index 00000000000..e5c632bc9c6 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/ChannelPromise.java @@ -0,0 +1,26 @@ +// Generated automatically from io.netty.channel.ChannelPromise for testing purposes + +package io.netty.channel; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.util.concurrent.GenericFutureListener; +import io.netty.util.concurrent.Promise; + +public interface ChannelPromise extends ChannelFuture, Promise +{ + Channel channel(); + ChannelPromise addListener(GenericFutureListener> p0); + ChannelPromise addListeners(GenericFutureListener>... p0); + ChannelPromise await(); + ChannelPromise awaitUninterruptibly(); + ChannelPromise removeListener(GenericFutureListener> p0); + ChannelPromise removeListeners(GenericFutureListener>... p0); + ChannelPromise setFailure(Throwable p0); + ChannelPromise setSuccess(); + ChannelPromise setSuccess(Void p0); + ChannelPromise sync(); + ChannelPromise syncUninterruptibly(); + ChannelPromise unvoid(); + boolean trySuccess(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/DefaultFileRegion.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/DefaultFileRegion.java new file mode 100644 index 00000000000..1532bcdb192 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/DefaultFileRegion.java @@ -0,0 +1,28 @@ +// Generated automatically from io.netty.channel.DefaultFileRegion for testing purposes + +package io.netty.channel; + +import io.netty.channel.FileRegion; +import io.netty.util.AbstractReferenceCounted; +import java.io.File; +import java.nio.channels.FileChannel; +import java.nio.channels.WritableByteChannel; + +public class DefaultFileRegion extends AbstractReferenceCounted implements FileRegion +{ + protected DefaultFileRegion() {} + protected void deallocate(){} + public DefaultFileRegion(File p0, long p1, long p2){} + public DefaultFileRegion(FileChannel p0, long p1, long p2){} + public FileRegion retain(){ return null; } + public FileRegion retain(int p0){ return null; } + public FileRegion touch(){ return null; } + public FileRegion touch(Object p0){ return null; } + public boolean isOpen(){ return false; } + public long count(){ return 0; } + public long position(){ return 0; } + public long transferTo(WritableByteChannel p0, long p1){ return 0; } + public long transfered(){ return 0; } + public long transferred(){ return 0; } + public void open(){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/EventLoop.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/EventLoop.java new file mode 100644 index 00000000000..2260759717b --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/EventLoop.java @@ -0,0 +1,11 @@ +// Generated automatically from io.netty.channel.EventLoop for testing purposes + +package io.netty.channel; + +import io.netty.channel.EventLoopGroup; +import io.netty.util.concurrent.OrderedEventExecutor; + +public interface EventLoop extends EventLoopGroup, OrderedEventExecutor +{ + EventLoopGroup parent(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/EventLoopGroup.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/EventLoopGroup.java new file mode 100644 index 00000000000..1e6da3111a0 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/EventLoopGroup.java @@ -0,0 +1,17 @@ +// Generated automatically from io.netty.channel.EventLoopGroup for testing purposes + +package io.netty.channel; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelPromise; +import io.netty.channel.EventLoop; +import io.netty.util.concurrent.EventExecutorGroup; + +public interface EventLoopGroup extends EventExecutorGroup +{ + ChannelFuture register(Channel p0); + ChannelFuture register(Channel p0, ChannelPromise p1); + ChannelFuture register(ChannelPromise p0); + EventLoop next(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/FileRegion.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/FileRegion.java new file mode 100644 index 00000000000..36cce9c0547 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/FileRegion.java @@ -0,0 +1,19 @@ +// Generated automatically from io.netty.channel.FileRegion for testing purposes + +package io.netty.channel; + +import io.netty.util.ReferenceCounted; +import java.nio.channels.WritableByteChannel; + +public interface FileRegion extends ReferenceCounted +{ + FileRegion retain(); + FileRegion retain(int p0); + FileRegion touch(); + FileRegion touch(Object p0); + long count(); + long position(); + long transferTo(WritableByteChannel p0, long p1); + long transfered(); + long transferred(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/MessageSizeEstimator.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/MessageSizeEstimator.java new file mode 100644 index 00000000000..e2f4267b189 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/MessageSizeEstimator.java @@ -0,0 +1,13 @@ +// Generated automatically from io.netty.channel.MessageSizeEstimator for testing purposes + +package io.netty.channel; + + +public interface MessageSizeEstimator +{ + MessageSizeEstimator.Handle newHandle(); + static public interface Handle + { + int size(Object p0); + } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/RecvByteBufAllocator.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/RecvByteBufAllocator.java new file mode 100644 index 00000000000..062a9850b77 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/RecvByteBufAllocator.java @@ -0,0 +1,25 @@ +// Generated automatically from io.netty.channel.RecvByteBufAllocator for testing purposes + +package io.netty.channel; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelConfig; + +public interface RecvByteBufAllocator +{ + RecvByteBufAllocator.Handle newHandle(); + static public interface Handle + { + ByteBuf allocate(ByteBufAllocator p0); + boolean continueReading(); + int attemptedBytesRead(); + int guess(); + int lastBytesRead(); + void attemptedBytesRead(int p0); + void incMessagesRead(int p0); + void lastBytesRead(int p0); + void readComplete(); + void reset(ChannelConfig p0); + } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/SimpleChannelInboundHandler.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/SimpleChannelInboundHandler.java new file mode 100644 index 00000000000..f29b1ca2ebf --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/SimpleChannelInboundHandler.java @@ -0,0 +1,17 @@ +// Generated automatically from io.netty.channel.SimpleChannelInboundHandler for testing purposes + +package io.netty.channel; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; + +abstract public class SimpleChannelInboundHandler extends ChannelInboundHandlerAdapter +{ + protected SimpleChannelInboundHandler(){} + protected SimpleChannelInboundHandler(Class p0){} + protected SimpleChannelInboundHandler(Class p0, boolean p1){} + protected SimpleChannelInboundHandler(boolean p0){} + protected abstract void channelRead0(ChannelHandlerContext p0, I p1); + public boolean acceptInboundMessage(Object p0){ return false; } + public void channelRead(ChannelHandlerContext p0, Object p1){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/channel/WriteBufferWaterMark.java b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/WriteBufferWaterMark.java new file mode 100644 index 00000000000..a2a98f482f7 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/channel/WriteBufferWaterMark.java @@ -0,0 +1,14 @@ +// Generated automatically from io.netty.channel.WriteBufferWaterMark for testing purposes + +package io.netty.channel; + + +public class WriteBufferWaterMark +{ + protected WriteBufferWaterMark() {} + public String toString(){ return null; } + public WriteBufferWaterMark(int p0, int p1){} + public int high(){ return 0; } + public int low(){ return 0; } + public static WriteBufferWaterMark DEFAULT = null; +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/ByteToMessageDecoder.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/ByteToMessageDecoder.java new file mode 100644 index 00000000000..bc5b75fbeeb --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/ByteToMessageDecoder.java @@ -0,0 +1,36 @@ +// Generated automatically from io.netty.handler.codec.ByteToMessageDecoder for testing purposes + +package io.netty.handler.codec; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import java.util.List; + +abstract public class ByteToMessageDecoder extends ChannelInboundHandlerAdapter +{ + protected ByteBuf internalBuffer(){ return null; } + protected ByteToMessageDecoder(){} + protected abstract void decode(ChannelHandlerContext p0, ByteBuf p1, List p2); + protected final void discardSomeReadBytes(){} + protected int actualReadableBytes(){ return 0; } + protected void callDecode(ChannelHandlerContext p0, ByteBuf p1, List p2){} + protected void decodeLast(ChannelHandlerContext p0, ByteBuf p1, List p2){} + protected void handlerRemoved0(ChannelHandlerContext p0){} + public boolean isSingleDecode(){ return false; } + public final void handlerRemoved(ChannelHandlerContext p0){} + public static ByteToMessageDecoder.Cumulator COMPOSITE_CUMULATOR = null; + public static ByteToMessageDecoder.Cumulator MERGE_CUMULATOR = null; + public void channelInactive(ChannelHandlerContext p0){} + public void channelRead(ChannelHandlerContext p0, Object p1){} + public void channelReadComplete(ChannelHandlerContext p0){} + public void setCumulator(ByteToMessageDecoder.Cumulator p0){} + public void setDiscardAfterReads(int p0){} + public void setSingleDecode(boolean p0){} + public void userEventTriggered(ChannelHandlerContext p0, Object p1){} + static public interface Cumulator + { + ByteBuf cumulate(ByteBufAllocator p0, ByteBuf p1, ByteBuf p2); + } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/DecoderResult.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/DecoderResult.java new file mode 100644 index 00000000000..50ef9ccb33d --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/DecoderResult.java @@ -0,0 +1,21 @@ +// Generated automatically from io.netty.handler.codec.DecoderResult for testing purposes + +package io.netty.handler.codec; + +import io.netty.util.Signal; + +public class DecoderResult +{ + protected DecoderResult() {} + protected DecoderResult(Throwable p0){} + protected static Signal SIGNAL_SUCCESS = null; + protected static Signal SIGNAL_UNFINISHED = null; + public String toString(){ return null; } + public Throwable cause(){ return null; } + public boolean isFailure(){ return false; } + public boolean isFinished(){ return false; } + public boolean isSuccess(){ return false; } + public static DecoderResult SUCCESS = null; + public static DecoderResult UNFINISHED = null; + public static DecoderResult failure(Throwable p0){ return null; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/DecoderResultProvider.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/DecoderResultProvider.java new file mode 100644 index 00000000000..341fea20bc1 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/DecoderResultProvider.java @@ -0,0 +1,11 @@ +// Generated automatically from io.netty.handler.codec.DecoderResultProvider for testing purposes + +package io.netty.handler.codec; + +import io.netty.handler.codec.DecoderResult; + +public interface DecoderResultProvider +{ + DecoderResult decoderResult(); + void setDecoderResult(DecoderResult p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/Headers.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/Headers.java new file mode 100644 index 00000000000..3362deafdb5 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/Headers.java @@ -0,0 +1,105 @@ +// Generated automatically from io.netty.handler.codec.Headers for testing purposes + +package io.netty.handler.codec; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public interface Headers> extends java.lang.Iterable> +{ + Boolean getBoolean(K p0); + Boolean getBooleanAndRemove(K p0); + Byte getByte(K p0); + Byte getByteAndRemove(K p0); + Character getChar(K p0); + Character getCharAndRemove(K p0); + Double getDouble(K p0); + Double getDoubleAndRemove(K p0); + Float getFloat(K p0); + Float getFloatAndRemove(K p0); + Integer getInt(K p0); + Integer getIntAndRemove(K p0); + List getAll(K p0); + List getAllAndRemove(K p0); + Long getLong(K p0); + Long getLongAndRemove(K p0); + Long getTimeMillis(K p0); + Long getTimeMillisAndRemove(K p0); + Short getShort(K p0); + Short getShortAndRemove(K p0); + T add(Headers p0); + T add(K p0, Iterable p1); + T add(K p0, V p1); + T add(K p0, V... p1); + T addBoolean(K p0, boolean p1); + T addByte(K p0, byte p1); + T addChar(K p0, char p1); + T addDouble(K p0, double p1); + T addFloat(K p0, float p1); + T addInt(K p0, int p1); + T addLong(K p0, long p1); + T addObject(K p0, Iterable p1); + T addObject(K p0, Object p1); + T addObject(K p0, Object... p1); + T addShort(K p0, short p1); + T addTimeMillis(K p0, long p1); + T clear(); + T set(Headers p0); + T set(K p0, Iterable p1); + T set(K p0, V p1); + T set(K p0, V... p1); + T setAll(Headers p0); + T setBoolean(K p0, boolean p1); + T setByte(K p0, byte p1); + T setChar(K p0, char p1); + T setDouble(K p0, double p1); + T setFloat(K p0, float p1); + T setInt(K p0, int p1); + T setLong(K p0, long p1); + T setObject(K p0, Iterable p1); + T setObject(K p0, Object p1); + T setObject(K p0, Object... p1); + T setShort(K p0, short p1); + T setTimeMillis(K p0, long p1); + V get(K p0); + V get(K p0, V p1); + V getAndRemove(K p0); + V getAndRemove(K p0, V p1); + boolean contains(K p0); + boolean contains(K p0, V p1); + boolean containsBoolean(K p0, boolean p1); + boolean containsByte(K p0, byte p1); + boolean containsChar(K p0, char p1); + boolean containsDouble(K p0, double p1); + boolean containsFloat(K p0, float p1); + boolean containsInt(K p0, int p1); + boolean containsLong(K p0, long p1); + boolean containsObject(K p0, Object p1); + boolean containsShort(K p0, short p1); + boolean containsTimeMillis(K p0, long p1); + boolean getBoolean(K p0, boolean p1); + boolean getBooleanAndRemove(K p0, boolean p1); + boolean isEmpty(); + boolean remove(K p0); + byte getByte(K p0, byte p1); + byte getByteAndRemove(K p0, byte p1); + char getChar(K p0, char p1); + char getCharAndRemove(K p0, char p1); + double getDouble(K p0, double p1); + double getDoubleAndRemove(K p0, double p1); + float getFloat(K p0, float p1); + float getFloatAndRemove(K p0, float p1); + int getInt(K p0, int p1); + int getIntAndRemove(K p0, int p1); + int size(); + java.util.Iterator> iterator(); + java.util.Set names(); + long getLong(K p0, long p1); + long getLongAndRemove(K p0, long p1); + long getTimeMillis(K p0, long p1); + long getTimeMillisAndRemove(K p0, long p1); + short getShort(K p0, short p1); + short getShortAndRemove(K p0, short p1); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/HeadersUtils.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/HeadersUtils.java new file mode 100644 index 00000000000..7746d808d68 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/HeadersUtils.java @@ -0,0 +1,19 @@ +// Generated automatically from io.netty.handler.codec.HeadersUtils for testing purposes + +package io.netty.handler.codec; + +import io.netty.handler.codec.Headers; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class HeadersUtils +{ + protected HeadersUtils() {} + public static List getAllAsString(io.netty.handler.codec.Headers p0, K p1){ return null; } + public static String getAsString(io.netty.handler.codec.Headers p0, K p1){ return null; } + public static String toString(Class p0, java.util.Iterator> p1, int p2){ return null; } + public static Iterator> iteratorAsString(Iterable> p0){ return null; } + public static Set namesAsString(Headers p0){ return null; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/base64/Base64.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/base64/Base64.java new file mode 100644 index 00000000000..57b87267320 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/base64/Base64.java @@ -0,0 +1,26 @@ +// Generated automatically from io.netty.handler.codec.base64.Base64 for testing purposes + +package io.netty.handler.codec.base64; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.handler.codec.base64.Base64Dialect; + +public class Base64 +{ + protected Base64() {} + public static ByteBuf decode(ByteBuf p0){ return null; } + public static ByteBuf decode(ByteBuf p0, Base64Dialect p1){ return null; } + public static ByteBuf decode(ByteBuf p0, int p1, int p2){ return null; } + public static ByteBuf decode(ByteBuf p0, int p1, int p2, Base64Dialect p3){ return null; } + public static ByteBuf decode(ByteBuf p0, int p1, int p2, Base64Dialect p3, ByteBufAllocator p4){ return null; } + public static ByteBuf encode(ByteBuf p0){ return null; } + public static ByteBuf encode(ByteBuf p0, Base64Dialect p1){ return null; } + public static ByteBuf encode(ByteBuf p0, boolean p1){ return null; } + public static ByteBuf encode(ByteBuf p0, boolean p1, Base64Dialect p2){ return null; } + public static ByteBuf encode(ByteBuf p0, int p1, int p2){ return null; } + public static ByteBuf encode(ByteBuf p0, int p1, int p2, Base64Dialect p3){ return null; } + public static ByteBuf encode(ByteBuf p0, int p1, int p2, boolean p3){ return null; } + public static ByteBuf encode(ByteBuf p0, int p1, int p2, boolean p3, Base64Dialect p4){ return null; } + public static ByteBuf encode(ByteBuf p0, int p1, int p2, boolean p3, Base64Dialect p4, ByteBufAllocator p5){ return null; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/base64/Base64Dialect.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/base64/Base64Dialect.java new file mode 100644 index 00000000000..3c2c5740384 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/base64/Base64Dialect.java @@ -0,0 +1,10 @@ +// Generated automatically from io.netty.handler.codec.base64.Base64Dialect for testing purposes + +package io.netty.handler.codec.base64; + + +public enum Base64Dialect +{ + ORDERED, STANDARD, URL_SAFE; + private Base64Dialect() {} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/FullHttpMessage.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/FullHttpMessage.java new file mode 100644 index 00000000000..7ee11bc4b41 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/FullHttpMessage.java @@ -0,0 +1,19 @@ +// Generated automatically from io.netty.handler.codec.http.FullHttpMessage for testing purposes + +package io.netty.handler.codec.http; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.HttpMessage; +import io.netty.handler.codec.http.LastHttpContent; + +public interface FullHttpMessage extends HttpMessage, LastHttpContent +{ + FullHttpMessage copy(); + FullHttpMessage duplicate(); + FullHttpMessage replace(ByteBuf p0); + FullHttpMessage retain(); + FullHttpMessage retain(int p0); + FullHttpMessage retainedDuplicate(); + FullHttpMessage touch(); + FullHttpMessage touch(Object p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/FullHttpRequest.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/FullHttpRequest.java new file mode 100644 index 00000000000..5439e5179df --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/FullHttpRequest.java @@ -0,0 +1,24 @@ +// Generated automatically from io.netty.handler.codec.http.FullHttpRequest for testing purposes + +package io.netty.handler.codec.http; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.FullHttpMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpVersion; + +public interface FullHttpRequest extends FullHttpMessage, HttpRequest +{ + FullHttpRequest copy(); + FullHttpRequest duplicate(); + FullHttpRequest replace(ByteBuf p0); + FullHttpRequest retain(); + FullHttpRequest retain(int p0); + FullHttpRequest retainedDuplicate(); + FullHttpRequest setMethod(HttpMethod p0); + FullHttpRequest setProtocolVersion(HttpVersion p0); + FullHttpRequest setUri(String p0); + FullHttpRequest touch(); + FullHttpRequest touch(Object p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/FullHttpResponse.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/FullHttpResponse.java new file mode 100644 index 00000000000..777c5f2b9b0 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/FullHttpResponse.java @@ -0,0 +1,23 @@ +// Generated automatically from io.netty.handler.codec.http.FullHttpResponse for testing purposes + +package io.netty.handler.codec.http; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.FullHttpMessage; +import io.netty.handler.codec.http.HttpResponse; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; + +public interface FullHttpResponse extends FullHttpMessage, HttpResponse +{ + FullHttpResponse copy(); + FullHttpResponse duplicate(); + FullHttpResponse replace(ByteBuf p0); + FullHttpResponse retain(); + FullHttpResponse retain(int p0); + FullHttpResponse retainedDuplicate(); + FullHttpResponse setProtocolVersion(HttpVersion p0); + FullHttpResponse setStatus(HttpResponseStatus p0); + FullHttpResponse touch(); + FullHttpResponse touch(Object p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpContent.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpContent.java new file mode 100644 index 00000000000..36214511ffa --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpContent.java @@ -0,0 +1,19 @@ +// Generated automatically from io.netty.handler.codec.http.HttpContent for testing purposes + +package io.netty.handler.codec.http; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufHolder; +import io.netty.handler.codec.http.HttpObject; + +public interface HttpContent extends ByteBufHolder, HttpObject +{ + HttpContent copy(); + HttpContent duplicate(); + HttpContent replace(ByteBuf p0); + HttpContent retain(); + HttpContent retain(int p0); + HttpContent retainedDuplicate(); + HttpContent touch(); + HttpContent touch(Object p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpHeaders.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpHeaders.java new file mode 100644 index 00000000000..0f436cf64cb --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpHeaders.java @@ -0,0 +1,119 @@ +// Generated automatically from io.netty.handler.codec.http.HttpHeaders for testing purposes + +package io.netty.handler.codec.http; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.HttpMessage; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +abstract public class HttpHeaders implements Iterable> +{ + protected HttpHeaders(){} + public HttpHeaders add(CharSequence p0, Iterable p1){ return null; } + public HttpHeaders add(CharSequence p0, Object p1){ return null; } + public HttpHeaders add(HttpHeaders p0){ return null; } + public HttpHeaders copy(){ return null; } + public HttpHeaders remove(CharSequence p0){ return null; } + public HttpHeaders set(CharSequence p0, Iterable p1){ return null; } + public HttpHeaders set(CharSequence p0, Object p1){ return null; } + public HttpHeaders set(HttpHeaders p0){ return null; } + public HttpHeaders setAll(HttpHeaders p0){ return null; } + public Iterator valueCharSequenceIterator(CharSequence p0){ return null; } + public Iterator valueStringIterator(CharSequence p0){ return null; } + public List getAll(CharSequence p0){ return null; } + public String get(CharSequence p0){ return null; } + public String get(CharSequence p0, String p1){ return null; } + public String toString(){ return null; } + public abstract HttpHeaders add(String p0, Iterable p1); + public abstract HttpHeaders add(String p0, Object p1); + public abstract HttpHeaders addInt(CharSequence p0, int p1); + public abstract HttpHeaders addShort(CharSequence p0, short p1); + public abstract HttpHeaders clear(); + public abstract HttpHeaders remove(String p0); + public abstract HttpHeaders set(String p0, Iterable p1); + public abstract HttpHeaders set(String p0, Object p1); + public abstract HttpHeaders setInt(CharSequence p0, int p1); + public abstract HttpHeaders setShort(CharSequence p0, short p1); + public abstract Integer getInt(CharSequence p0); + public abstract Iterator> iteratorCharSequence(); + public abstract Iterator> iterator(); + public abstract List> entries(); + public abstract List getAll(String p0); + public abstract Long getTimeMillis(CharSequence p0); + public abstract Set names(); + public abstract Short getShort(CharSequence p0); + public abstract String get(String p0); + public abstract boolean contains(String p0); + public abstract boolean isEmpty(); + public abstract int getInt(CharSequence p0, int p1); + public abstract int size(); + public abstract long getTimeMillis(CharSequence p0, long p1); + public abstract short getShort(CharSequence p0, short p1); + public boolean contains(CharSequence p0){ return false; } + public boolean contains(CharSequence p0, CharSequence p1, boolean p2){ return false; } + public boolean contains(String p0, String p1, boolean p2){ return false; } + public boolean containsValue(CharSequence p0, CharSequence p1, boolean p2){ return false; } + public final Iterator> iteratorAsString(){ return null; } + public final List getAllAsString(CharSequence p0){ return null; } + public final String getAsString(CharSequence p0){ return null; } + public static CharSequence newEntity(String p0){ return null; } + public static Date getDate(HttpMessage p0){ return null; } + public static Date getDate(HttpMessage p0, Date p1){ return null; } + public static Date getDateHeader(HttpMessage p0, CharSequence p1){ return null; } + public static Date getDateHeader(HttpMessage p0, CharSequence p1, Date p2){ return null; } + public static Date getDateHeader(HttpMessage p0, String p1){ return null; } + public static Date getDateHeader(HttpMessage p0, String p1, Date p2){ return null; } + public static HttpHeaders EMPTY_HEADERS = null; + public static String getHeader(HttpMessage p0, CharSequence p1){ return null; } + public static String getHeader(HttpMessage p0, CharSequence p1, String p2){ return null; } + public static String getHeader(HttpMessage p0, String p1){ return null; } + public static String getHeader(HttpMessage p0, String p1, String p2){ return null; } + public static String getHost(HttpMessage p0){ return null; } + public static String getHost(HttpMessage p0, String p1){ return null; } + public static boolean equalsIgnoreCase(CharSequence p0, CharSequence p1){ return false; } + public static boolean is100ContinueExpected(HttpMessage p0){ return false; } + public static boolean isContentLengthSet(HttpMessage p0){ return false; } + public static boolean isKeepAlive(HttpMessage p0){ return false; } + public static boolean isTransferEncodingChunked(HttpMessage p0){ return false; } + public static int getIntHeader(HttpMessage p0, CharSequence p1){ return 0; } + public static int getIntHeader(HttpMessage p0, CharSequence p1, int p2){ return 0; } + public static int getIntHeader(HttpMessage p0, String p1){ return 0; } + public static int getIntHeader(HttpMessage p0, String p1, int p2){ return 0; } + public static long getContentLength(HttpMessage p0){ return 0; } + public static long getContentLength(HttpMessage p0, long p1){ return 0; } + public static void addDateHeader(HttpMessage p0, CharSequence p1, Date p2){} + public static void addDateHeader(HttpMessage p0, String p1, Date p2){} + public static void addHeader(HttpMessage p0, CharSequence p1, Object p2){} + public static void addHeader(HttpMessage p0, String p1, Object p2){} + public static void addIntHeader(HttpMessage p0, CharSequence p1, int p2){} + public static void addIntHeader(HttpMessage p0, String p1, int p2){} + public static void clearHeaders(HttpMessage p0){} + public static void encodeAscii(CharSequence p0, ByteBuf p1){} + public static void removeHeader(HttpMessage p0, CharSequence p1){} + public static void removeHeader(HttpMessage p0, String p1){} + public static void removeTransferEncodingChunked(HttpMessage p0){} + public static void set100ContinueExpected(HttpMessage p0){} + public static void set100ContinueExpected(HttpMessage p0, boolean p1){} + public static void setContentLength(HttpMessage p0, long p1){} + public static void setDate(HttpMessage p0, Date p1){} + public static void setDateHeader(HttpMessage p0, CharSequence p1, Date p2){} + public static void setDateHeader(HttpMessage p0, CharSequence p1, Iterable p2){} + public static void setDateHeader(HttpMessage p0, String p1, Date p2){} + public static void setDateHeader(HttpMessage p0, String p1, Iterable p2){} + public static void setHeader(HttpMessage p0, CharSequence p1, Iterable p2){} + public static void setHeader(HttpMessage p0, CharSequence p1, Object p2){} + public static void setHeader(HttpMessage p0, String p1, Iterable p2){} + public static void setHeader(HttpMessage p0, String p1, Object p2){} + public static void setHost(HttpMessage p0, CharSequence p1){} + public static void setHost(HttpMessage p0, String p1){} + public static void setIntHeader(HttpMessage p0, CharSequence p1, Iterable p2){} + public static void setIntHeader(HttpMessage p0, CharSequence p1, int p2){} + public static void setIntHeader(HttpMessage p0, String p1, Iterable p2){} + public static void setIntHeader(HttpMessage p0, String p1, int p2){} + public static void setKeepAlive(HttpMessage p0, boolean p1){} + public static void setTransferEncodingChunked(HttpMessage p0){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpMessage.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpMessage.java new file mode 100644 index 00000000000..7e57a70a5db --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpMessage.java @@ -0,0 +1,15 @@ +// Generated automatically from io.netty.handler.codec.http.HttpMessage for testing purposes + +package io.netty.handler.codec.http; + +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpObject; +import io.netty.handler.codec.http.HttpVersion; + +public interface HttpMessage extends HttpObject +{ + HttpHeaders headers(); + HttpMessage setProtocolVersion(HttpVersion p0); + HttpVersion getProtocolVersion(); + HttpVersion protocolVersion(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpMethod.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpMethod.java new file mode 100644 index 00000000000..9ff2913feaf --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpMethod.java @@ -0,0 +1,27 @@ +// Generated automatically from io.netty.handler.codec.http.HttpMethod for testing purposes + +package io.netty.handler.codec.http; + +import io.netty.util.AsciiString; + +public class HttpMethod implements Comparable +{ + protected HttpMethod() {} + public AsciiString asciiName(){ return null; } + public HttpMethod(String p0){} + public String name(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int compareTo(HttpMethod p0){ return 0; } + public int hashCode(){ return 0; } + public static HttpMethod CONNECT = null; + public static HttpMethod DELETE = null; + public static HttpMethod GET = null; + public static HttpMethod HEAD = null; + public static HttpMethod OPTIONS = null; + public static HttpMethod PATCH = null; + public static HttpMethod POST = null; + public static HttpMethod PUT = null; + public static HttpMethod TRACE = null; + public static HttpMethod valueOf(String p0){ return null; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpObject.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpObject.java new file mode 100644 index 00000000000..6e38be4aa02 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpObject.java @@ -0,0 +1,11 @@ +// Generated automatically from io.netty.handler.codec.http.HttpObject for testing purposes + +package io.netty.handler.codec.http; + +import io.netty.handler.codec.DecoderResult; +import io.netty.handler.codec.DecoderResultProvider; + +public interface HttpObject extends DecoderResultProvider +{ + DecoderResult getDecoderResult(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpRequest.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpRequest.java new file mode 100644 index 00000000000..2c8f90ed109 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpRequest.java @@ -0,0 +1,18 @@ +// Generated automatically from io.netty.handler.codec.http.HttpRequest for testing purposes + +package io.netty.handler.codec.http; + +import io.netty.handler.codec.http.HttpMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; + +public interface HttpRequest extends HttpMessage +{ + HttpMethod getMethod(); + HttpMethod method(); + HttpRequest setMethod(HttpMethod p0); + HttpRequest setProtocolVersion(HttpVersion p0); + HttpRequest setUri(String p0); + String getUri(); + String uri(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpResponse.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpResponse.java new file mode 100644 index 00000000000..8026bc00843 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpResponse.java @@ -0,0 +1,15 @@ +// Generated automatically from io.netty.handler.codec.http.HttpResponse for testing purposes + +package io.netty.handler.codec.http; + +import io.netty.handler.codec.http.HttpMessage; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; + +public interface HttpResponse extends HttpMessage +{ + HttpResponse setProtocolVersion(HttpVersion p0); + HttpResponse setStatus(HttpResponseStatus p0); + HttpResponseStatus getStatus(); + HttpResponseStatus status(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpResponseStatus.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpResponseStatus.java new file mode 100644 index 00000000000..777d3a946e4 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpResponseStatus.java @@ -0,0 +1,82 @@ +// Generated automatically from io.netty.handler.codec.http.HttpResponseStatus for testing purposes + +package io.netty.handler.codec.http; + +import io.netty.handler.codec.http.HttpStatusClass; +import io.netty.util.AsciiString; + +public class HttpResponseStatus implements Comparable +{ + protected HttpResponseStatus() {} + public AsciiString codeAsText(){ return null; } + public HttpResponseStatus(int p0, String p1){} + public HttpStatusClass codeClass(){ return null; } + public String reasonPhrase(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int code(){ return 0; } + public int compareTo(HttpResponseStatus p0){ return 0; } + public int hashCode(){ return 0; } + public static HttpResponseStatus ACCEPTED = null; + public static HttpResponseStatus BAD_GATEWAY = null; + public static HttpResponseStatus BAD_REQUEST = null; + public static HttpResponseStatus CONFLICT = null; + public static HttpResponseStatus CONTINUE = null; + public static HttpResponseStatus CREATED = null; + public static HttpResponseStatus EARLY_HINTS = null; + public static HttpResponseStatus EXPECTATION_FAILED = null; + public static HttpResponseStatus FAILED_DEPENDENCY = null; + public static HttpResponseStatus FORBIDDEN = null; + public static HttpResponseStatus FOUND = null; + public static HttpResponseStatus GATEWAY_TIMEOUT = null; + public static HttpResponseStatus GONE = null; + public static HttpResponseStatus HTTP_VERSION_NOT_SUPPORTED = null; + public static HttpResponseStatus INSUFFICIENT_STORAGE = null; + public static HttpResponseStatus INTERNAL_SERVER_ERROR = null; + public static HttpResponseStatus LENGTH_REQUIRED = null; + public static HttpResponseStatus LOCKED = null; + public static HttpResponseStatus METHOD_NOT_ALLOWED = null; + public static HttpResponseStatus MISDIRECTED_REQUEST = null; + public static HttpResponseStatus MOVED_PERMANENTLY = null; + public static HttpResponseStatus MULTIPLE_CHOICES = null; + public static HttpResponseStatus MULTI_STATUS = null; + public static HttpResponseStatus NETWORK_AUTHENTICATION_REQUIRED = null; + public static HttpResponseStatus NON_AUTHORITATIVE_INFORMATION = null; + public static HttpResponseStatus NOT_ACCEPTABLE = null; + public static HttpResponseStatus NOT_EXTENDED = null; + public static HttpResponseStatus NOT_FOUND = null; + public static HttpResponseStatus NOT_IMPLEMENTED = null; + public static HttpResponseStatus NOT_MODIFIED = null; + public static HttpResponseStatus NO_CONTENT = null; + public static HttpResponseStatus OK = null; + public static HttpResponseStatus PARTIAL_CONTENT = null; + public static HttpResponseStatus PAYMENT_REQUIRED = null; + public static HttpResponseStatus PERMANENT_REDIRECT = null; + public static HttpResponseStatus PRECONDITION_FAILED = null; + public static HttpResponseStatus PRECONDITION_REQUIRED = null; + public static HttpResponseStatus PROCESSING = null; + public static HttpResponseStatus PROXY_AUTHENTICATION_REQUIRED = null; + public static HttpResponseStatus REQUESTED_RANGE_NOT_SATISFIABLE = null; + public static HttpResponseStatus REQUEST_ENTITY_TOO_LARGE = null; + public static HttpResponseStatus REQUEST_HEADER_FIELDS_TOO_LARGE = null; + public static HttpResponseStatus REQUEST_TIMEOUT = null; + public static HttpResponseStatus REQUEST_URI_TOO_LONG = null; + public static HttpResponseStatus RESET_CONTENT = null; + public static HttpResponseStatus SEE_OTHER = null; + public static HttpResponseStatus SERVICE_UNAVAILABLE = null; + public static HttpResponseStatus SWITCHING_PROTOCOLS = null; + public static HttpResponseStatus TEMPORARY_REDIRECT = null; + public static HttpResponseStatus TOO_MANY_REQUESTS = null; + public static HttpResponseStatus UNAUTHORIZED = null; + public static HttpResponseStatus UNORDERED_COLLECTION = null; + public static HttpResponseStatus UNPROCESSABLE_ENTITY = null; + public static HttpResponseStatus UNSUPPORTED_MEDIA_TYPE = null; + public static HttpResponseStatus UPGRADE_REQUIRED = null; + public static HttpResponseStatus USE_PROXY = null; + public static HttpResponseStatus VARIANT_ALSO_NEGOTIATES = null; + public static HttpResponseStatus parseLine(AsciiString p0){ return null; } + public static HttpResponseStatus parseLine(CharSequence p0){ return null; } + public static HttpResponseStatus parseLine(String p0){ return null; } + public static HttpResponseStatus valueOf(int p0){ return null; } + public static HttpResponseStatus valueOf(int p0, String p1){ return null; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpStatusClass.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpStatusClass.java new file mode 100644 index 00000000000..15516633bf2 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpStatusClass.java @@ -0,0 +1,11 @@ +// Generated automatically from io.netty.handler.codec.http.HttpStatusClass for testing purposes + +package io.netty.handler.codec.http; + + +public enum HttpStatusClass +{ + CLIENT_ERROR, INFORMATIONAL, REDIRECTION, SERVER_ERROR, SUCCESS, UNKNOWN; + private HttpStatusClass() {} + public boolean contains(int p0){ return false; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpVersion.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpVersion.java new file mode 100644 index 00000000000..50d133986c7 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/HttpVersion.java @@ -0,0 +1,23 @@ +// Generated automatically from io.netty.handler.codec.http.HttpVersion for testing purposes + +package io.netty.handler.codec.http; + + +public class HttpVersion implements Comparable +{ + protected HttpVersion() {} + public HttpVersion(String p0, boolean p1){} + public HttpVersion(String p0, int p1, int p2, boolean p3){} + public String protocolName(){ return null; } + public String text(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isKeepAliveDefault(){ return false; } + public int compareTo(HttpVersion p0){ return 0; } + public int hashCode(){ return 0; } + public int majorVersion(){ return 0; } + public int minorVersion(){ return 0; } + public static HttpVersion HTTP_1_0 = null; + public static HttpVersion HTTP_1_1 = null; + public static HttpVersion valueOf(String p0){ return null; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/LastHttpContent.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/LastHttpContent.java new file mode 100644 index 00000000000..d5a6044926b --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/LastHttpContent.java @@ -0,0 +1,21 @@ +// Generated automatically from io.netty.handler.codec.http.LastHttpContent for testing purposes + +package io.netty.handler.codec.http; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.HttpContent; +import io.netty.handler.codec.http.HttpHeaders; + +public interface LastHttpContent extends HttpContent +{ + HttpHeaders trailingHeaders(); + LastHttpContent copy(); + LastHttpContent duplicate(); + LastHttpContent replace(ByteBuf p0); + LastHttpContent retain(); + LastHttpContent retain(int p0); + LastHttpContent retainedDuplicate(); + LastHttpContent touch(); + LastHttpContent touch(Object p0); + static LastHttpContent EMPTY_LAST_CONTENT = null; +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/QueryStringDecoder.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/QueryStringDecoder.java new file mode 100644 index 00000000000..f2d25b3b9f9 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/QueryStringDecoder.java @@ -0,0 +1,31 @@ +// Generated automatically from io.netty.handler.codec.http.QueryStringDecoder for testing purposes + +package io.netty.handler.codec.http; + +import java.net.URI; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Map; + +public class QueryStringDecoder +{ + protected QueryStringDecoder() {} + public Map> parameters(){ return null; } + public QueryStringDecoder(String p0){} + public QueryStringDecoder(String p0, Charset p1){} + public QueryStringDecoder(String p0, Charset p1, boolean p2){} + public QueryStringDecoder(String p0, Charset p1, boolean p2, int p3){} + public QueryStringDecoder(String p0, Charset p1, boolean p2, int p3, boolean p4){} + public QueryStringDecoder(String p0, boolean p1){} + public QueryStringDecoder(URI p0){} + public QueryStringDecoder(URI p0, Charset p1){} + public QueryStringDecoder(URI p0, Charset p1, int p2){} + public QueryStringDecoder(URI p0, Charset p1, int p2, boolean p3){} + public String path(){ return null; } + public String rawPath(){ return null; } + public String rawQuery(){ return null; } + public String toString(){ return null; } + public String uri(){ return null; } + public static String decodeComponent(String p0){ return null; } + public static String decodeComponent(String p0, Charset p1){ return null; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/Cookie.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/Cookie.java index ecb0c689438..8bc8766fe18 100644 --- a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/Cookie.java +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/Cookie.java @@ -1,146 +1,24 @@ -/* - * Copyright 2015 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ +// Generated automatically from io.netty.handler.codec.http.cookie.Cookie for testing purposes + package io.netty.handler.codec.http.cookie; -/** - * An interface defining an - * HTTP cookie. - */ -public interface Cookie extends Comparable { - /** - * Constant for undefined MaxAge attribute value. - */ - long UNDEFINED_MAX_AGE = Long.MIN_VALUE; - - /** - * Returns the name of this {@link Cookie}. - * - * @return The name of this {@link Cookie} - */ - String name(); - - /** - * Returns the value of this {@link Cookie}. - * - * @return The value of this {@link Cookie} - */ - String value(); - - /** - * Sets the value of this {@link Cookie}. - * - * @param value The value to set - */ - void setValue(String value); - - /** - * Returns true if the raw value of this {@link Cookie}, - * was wrapped with double quotes in original Set-Cookie header. - * - * @return If the value of this {@link Cookie} is to be wrapped - */ - boolean wrap(); - - /** - * Sets true if the value of this {@link Cookie} - * is to be wrapped with double quotes. - * - * @param wrap true if wrap - */ - void setWrap(boolean wrap); - - /** - * Returns the domain of this {@link Cookie}. - * - * @return The domain of this {@link Cookie} - */ +public interface Cookie extends Comparable +{ String domain(); - - /** - * Sets the domain of this {@link Cookie}. - * - * @param domain The domain to use - */ - void setDomain(String domain); - - /** - * Returns the path of this {@link Cookie}. - * - * @return The {@link Cookie}'s path - */ + String name(); String path(); - - /** - * Sets the path of this {@link Cookie}. - * - * @param path The path to use for this {@link Cookie} - */ - void setPath(String path); - - /** - * Returns the maximum age of this {@link Cookie} in seconds or {@link Cookie#UNDEFINED_MAX_AGE} if unspecified - * - * @return The maximum age of this {@link Cookie} - */ - long maxAge(); - - /** - * Sets the maximum age of this {@link Cookie} in seconds. - * If an age of {@code 0} is specified, this {@link Cookie} will be - * automatically removed by browser because it will expire immediately. - * If {@link Cookie#UNDEFINED_MAX_AGE} is specified, this {@link Cookie} will be removed when the - * browser is closed. - * - * @param maxAge The maximum age of this {@link Cookie} in seconds - */ - void setMaxAge(long maxAge); - - /** - * Checks to see if this {@link Cookie} is secure - * - * @return True if this {@link Cookie} is secure, otherwise false - */ - boolean isSecure(); - - /** - * Sets the security getStatus of this {@link Cookie} - * - * @param secure True if this {@link Cookie} is to be secure, otherwise false - */ - void setSecure(boolean secure); - - /** - * Checks to see if this {@link Cookie} can only be accessed via HTTP. - * If this returns true, the {@link Cookie} cannot be accessed through - * client side script - But only if the browser supports it. - * For more information, please look here - * - * @return True if this {@link Cookie} is HTTP-only or false if it isn't - */ + String value(); boolean isHttpOnly(); - - /** - * Determines if this {@link Cookie} is HTTP only. - * If set to true, this {@link Cookie} cannot be accessed by a client - * side script. However, this works only if the browser supports it. - * For for information, please look - * here. - * - * @param httpOnly True if the {@link Cookie} is HTTP only, otherwise false. - */ - void setHttpOnly(boolean httpOnly); -} \ No newline at end of file + boolean isSecure(); + boolean wrap(); + long maxAge(); + static long UNDEFINED_MAX_AGE = 0; + void setDomain(String p0); + void setHttpOnly(boolean p0); + void setMaxAge(long p0); + void setPath(String p0); + void setSecure(boolean p0); + void setValue(String p0); + void setWrap(boolean p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/CookieDecoder.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/CookieDecoder.java new file mode 100644 index 00000000000..294da25f15c --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/CookieDecoder.java @@ -0,0 +1,12 @@ +// Generated automatically from io.netty.handler.codec.http.cookie.CookieDecoder for testing purposes + +package io.netty.handler.codec.http.cookie; + +import io.netty.handler.codec.http.cookie.DefaultCookie; + +abstract public class CookieDecoder +{ + protected CookieDecoder() {} + protected CookieDecoder(boolean p0){} + protected DefaultCookie initCookie(String p0, int p1, int p2, int p3, int p4){ return null; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/CookieEncoder.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/CookieEncoder.java new file mode 100644 index 00000000000..0f0b2b414b7 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/CookieEncoder.java @@ -0,0 +1,12 @@ +// Generated automatically from io.netty.handler.codec.http.cookie.CookieEncoder for testing purposes + +package io.netty.handler.codec.http.cookie; + + +abstract public class CookieEncoder +{ + protected CookieEncoder() {} + protected CookieEncoder(boolean p0){} + protected final boolean strict = false; + protected void validateCookie(String p0, String p1){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/CookieHeaderNames.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/CookieHeaderNames.java new file mode 100644 index 00000000000..432eb7e7ec0 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/CookieHeaderNames.java @@ -0,0 +1,21 @@ +// Generated automatically from io.netty.handler.codec.http.cookie.CookieHeaderNames for testing purposes + +package io.netty.handler.codec.http.cookie; + + +public class CookieHeaderNames +{ + protected CookieHeaderNames() {} + public static String DOMAIN = null; + public static String EXPIRES = null; + public static String HTTPONLY = null; + public static String MAX_AGE = null; + public static String PATH = null; + public static String SAMESITE = null; + public static String SECURE = null; + static public enum SameSite + { + Lax, None, Strict; + private SameSite() {} + } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/DefaultCookie.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/DefaultCookie.java new file mode 100644 index 00000000000..1a6ced92907 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/DefaultCookie.java @@ -0,0 +1,34 @@ +// Generated automatically from io.netty.handler.codec.http.cookie.DefaultCookie for testing purposes + +package io.netty.handler.codec.http.cookie; + +import io.netty.handler.codec.http.cookie.Cookie; +import io.netty.handler.codec.http.cookie.CookieHeaderNames; + +public class DefaultCookie implements Cookie +{ + protected DefaultCookie() {} + protected String validateValue(String p0, String p1){ return null; } + public CookieHeaderNames.SameSite sameSite(){ return null; } + public DefaultCookie(String p0, String p1){} + public String domain(){ return null; } + public String name(){ return null; } + public String path(){ return null; } + public String toString(){ return null; } + public String value(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isHttpOnly(){ return false; } + public boolean isSecure(){ return false; } + public boolean wrap(){ return false; } + public int compareTo(Cookie p0){ return 0; } + public int hashCode(){ return 0; } + public long maxAge(){ return 0; } + public void setDomain(String p0){} + public void setHttpOnly(boolean p0){} + public void setMaxAge(long p0){} + public void setPath(String p0){} + public void setSameSite(CookieHeaderNames.SameSite p0){} + public void setSecure(boolean p0){} + public void setValue(String p0){} + public void setWrap(boolean p0){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/ServerCookieDecoder.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/ServerCookieDecoder.java new file mode 100644 index 00000000000..3621d83f597 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/ServerCookieDecoder.java @@ -0,0 +1,17 @@ +// Generated automatically from io.netty.handler.codec.http.cookie.ServerCookieDecoder for testing purposes + +package io.netty.handler.codec.http.cookie; + +import io.netty.handler.codec.http.cookie.Cookie; +import io.netty.handler.codec.http.cookie.CookieDecoder; +import java.util.List; +import java.util.Set; + +public class ServerCookieDecoder extends CookieDecoder +{ + protected ServerCookieDecoder() {} + public List decodeAll(String p0){ return null; } + public Set decode(String p0){ return null; } + public static ServerCookieDecoder LAX = null; + public static ServerCookieDecoder STRICT = null; +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/ServerCookieEncoder.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/ServerCookieEncoder.java new file mode 100644 index 00000000000..21c0dfd7c8e --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/cookie/ServerCookieEncoder.java @@ -0,0 +1,20 @@ +// Generated automatically from io.netty.handler.codec.http.cookie.ServerCookieEncoder for testing purposes + +package io.netty.handler.codec.http.cookie; + +import io.netty.handler.codec.http.cookie.Cookie; +import io.netty.handler.codec.http.cookie.CookieEncoder; +import java.util.Collection; +import java.util.List; + +public class ServerCookieEncoder extends CookieEncoder +{ + protected ServerCookieEncoder() {} + public List encode(Collection p0){ return null; } + public List encode(Cookie... p0){ return null; } + public List encode(Iterable p0){ return null; } + public String encode(Cookie p0){ return null; } + public String encode(String p0, String p1){ return null; } + public static ServerCookieEncoder LAX = null; + public static ServerCookieEncoder STRICT = null; +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/Attribute.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/Attribute.java new file mode 100644 index 00000000000..b87dedf1a3f --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/Attribute.java @@ -0,0 +1,20 @@ +// Generated automatically from io.netty.handler.codec.http.multipart.Attribute for testing purposes + +package io.netty.handler.codec.http.multipart; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.multipart.HttpData; + +public interface Attribute extends HttpData +{ + Attribute copy(); + Attribute duplicate(); + Attribute replace(ByteBuf p0); + Attribute retain(); + Attribute retain(int p0); + Attribute retainedDuplicate(); + Attribute touch(); + Attribute touch(Object p0); + String getValue(); + void setValue(String p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/FileUpload.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/FileUpload.java new file mode 100644 index 00000000000..5f8c20ad6bb --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/FileUpload.java @@ -0,0 +1,24 @@ +// Generated automatically from io.netty.handler.codec.http.multipart.FileUpload for testing purposes + +package io.netty.handler.codec.http.multipart; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.multipart.HttpData; + +public interface FileUpload extends HttpData +{ + FileUpload copy(); + FileUpload duplicate(); + FileUpload replace(ByteBuf p0); + FileUpload retain(); + FileUpload retain(int p0); + FileUpload retainedDuplicate(); + FileUpload touch(); + FileUpload touch(Object p0); + String getContentTransferEncoding(); + String getContentType(); + String getFilename(); + void setContentTransferEncoding(String p0); + void setContentType(String p0); + void setFilename(String p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/HttpData.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/HttpData.java new file mode 100644 index 00000000000..c96054d9173 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/HttpData.java @@ -0,0 +1,43 @@ +// Generated automatically from io.netty.handler.codec.http.multipart.HttpData for testing purposes + +package io.netty.handler.codec.http.multipart; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufHolder; +import io.netty.handler.codec.http.multipart.InterfaceHttpData; +import java.io.File; +import java.io.InputStream; +import java.nio.charset.Charset; + +public interface HttpData extends ByteBufHolder, InterfaceHttpData +{ + ByteBuf getByteBuf(); + ByteBuf getChunk(int p0); + Charset getCharset(); + File getFile(); + HttpData copy(); + HttpData duplicate(); + HttpData replace(ByteBuf p0); + HttpData retain(); + HttpData retain(int p0); + HttpData retainedDuplicate(); + HttpData touch(); + HttpData touch(Object p0); + String getString(); + String getString(Charset p0); + boolean isCompleted(); + boolean isInMemory(); + boolean renameTo(File p0); + byte[] get(); + long definedLength(); + long getMaxSize(); + long length(); + void addContent(ByteBuf p0, boolean p1); + void checkSize(long p0); + void delete(); + void setCharset(Charset p0); + void setContent(ByteBuf p0); + void setContent(File p0); + void setContent(InputStream p0); + void setMaxSize(long p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/HttpDataFactory.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/HttpDataFactory.java new file mode 100644 index 00000000000..70acdf0a0ff --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/HttpDataFactory.java @@ -0,0 +1,23 @@ +// Generated automatically from io.netty.handler.codec.http.multipart.HttpDataFactory for testing purposes + +package io.netty.handler.codec.http.multipart; + +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.multipart.Attribute; +import io.netty.handler.codec.http.multipart.FileUpload; +import io.netty.handler.codec.http.multipart.InterfaceHttpData; +import java.nio.charset.Charset; + +public interface HttpDataFactory +{ + Attribute createAttribute(HttpRequest p0, String p1); + Attribute createAttribute(HttpRequest p0, String p1, String p2); + Attribute createAttribute(HttpRequest p0, String p1, long p2); + FileUpload createFileUpload(HttpRequest p0, String p1, String p2, String p3, String p4, Charset p5, long p6); + void cleanAllHttpData(); + void cleanAllHttpDatas(); + void cleanRequestHttpData(HttpRequest p0); + void cleanRequestHttpDatas(HttpRequest p0); + void removeHttpDataFromClean(HttpRequest p0, InterfaceHttpData p1); + void setMaxLimit(long p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java new file mode 100644 index 00000000000..0b2013b55e6 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java @@ -0,0 +1,34 @@ +// Generated automatically from io.netty.handler.codec.http.multipart.HttpPostMultipartRequestDecoder for testing purposes + +package io.netty.handler.codec.http.multipart; + +import io.netty.handler.codec.http.HttpContent; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.multipart.HttpDataFactory; +import io.netty.handler.codec.http.multipart.InterfaceHttpData; +import io.netty.handler.codec.http.multipart.InterfaceHttpPostRequestDecoder; +import java.nio.charset.Charset; +import java.util.List; + +public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequestDecoder +{ + protected HttpPostMultipartRequestDecoder() {} + protected InterfaceHttpData getFileUpload(String p0){ return null; } + protected void addHttpData(InterfaceHttpData p0){} + public HttpPostMultipartRequestDecoder offer(HttpContent p0){ return null; } + public HttpPostMultipartRequestDecoder(HttpDataFactory p0, HttpRequest p1){} + public HttpPostMultipartRequestDecoder(HttpDataFactory p0, HttpRequest p1, Charset p2){} + public HttpPostMultipartRequestDecoder(HttpRequest p0){} + public InterfaceHttpData currentPartialHttpData(){ return null; } + public InterfaceHttpData getBodyHttpData(String p0){ return null; } + public InterfaceHttpData next(){ return null; } + public List getBodyHttpDatas(){ return null; } + public List getBodyHttpDatas(String p0){ return null; } + public boolean hasNext(){ return false; } + public boolean isMultipart(){ return false; } + public int getDiscardThreshold(){ return 0; } + public void cleanFiles(){} + public void destroy(){} + public void removeHttpDataFromClean(InterfaceHttpData p0){} + public void setDiscardThreshold(int p0){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java new file mode 100644 index 00000000000..a1b4d59817b --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java @@ -0,0 +1,34 @@ +// Generated automatically from io.netty.handler.codec.http.multipart.HttpPostRequestDecoder for testing purposes + +package io.netty.handler.codec.http.multipart; + +import io.netty.handler.codec.http.HttpContent; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.multipart.HttpDataFactory; +import io.netty.handler.codec.http.multipart.InterfaceHttpData; +import io.netty.handler.codec.http.multipart.InterfaceHttpPostRequestDecoder; +import java.nio.charset.Charset; +import java.util.List; + +public class HttpPostRequestDecoder implements InterfaceHttpPostRequestDecoder +{ + protected HttpPostRequestDecoder() {} + protected static String[] getMultipartDataBoundary(String p0){ return null; } + public HttpPostRequestDecoder(HttpDataFactory p0, HttpRequest p1){} + public HttpPostRequestDecoder(HttpDataFactory p0, HttpRequest p1, Charset p2){} + public HttpPostRequestDecoder(HttpRequest p0){} + public InterfaceHttpData currentPartialHttpData(){ return null; } + public InterfaceHttpData getBodyHttpData(String p0){ return null; } + public InterfaceHttpData next(){ return null; } + public InterfaceHttpPostRequestDecoder offer(HttpContent p0){ return null; } + public List getBodyHttpDatas(){ return null; } + public List getBodyHttpDatas(String p0){ return null; } + public boolean hasNext(){ return false; } + public boolean isMultipart(){ return false; } + public int getDiscardThreshold(){ return 0; } + public static boolean isMultipart(HttpRequest p0){ return false; } + public void cleanFiles(){} + public void destroy(){} + public void removeHttpDataFromClean(InterfaceHttpData p0){} + public void setDiscardThreshold(int p0){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java new file mode 100644 index 00000000000..7b228470faa --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java @@ -0,0 +1,33 @@ +// Generated automatically from io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder for testing purposes + +package io.netty.handler.codec.http.multipart; + +import io.netty.handler.codec.http.HttpContent; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.multipart.HttpDataFactory; +import io.netty.handler.codec.http.multipart.InterfaceHttpData; +import io.netty.handler.codec.http.multipart.InterfaceHttpPostRequestDecoder; +import java.nio.charset.Charset; +import java.util.List; + +public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestDecoder +{ + protected HttpPostStandardRequestDecoder() {} + protected void addHttpData(InterfaceHttpData p0){} + public HttpPostStandardRequestDecoder offer(HttpContent p0){ return null; } + public HttpPostStandardRequestDecoder(HttpDataFactory p0, HttpRequest p1){} + public HttpPostStandardRequestDecoder(HttpDataFactory p0, HttpRequest p1, Charset p2){} + public HttpPostStandardRequestDecoder(HttpRequest p0){} + public InterfaceHttpData currentPartialHttpData(){ return null; } + public InterfaceHttpData getBodyHttpData(String p0){ return null; } + public InterfaceHttpData next(){ return null; } + public List getBodyHttpDatas(){ return null; } + public List getBodyHttpDatas(String p0){ return null; } + public boolean hasNext(){ return false; } + public boolean isMultipart(){ return false; } + public int getDiscardThreshold(){ return 0; } + public void cleanFiles(){} + public void destroy(){} + public void removeHttpDataFromClean(InterfaceHttpData p0){} + public void setDiscardThreshold(int p0){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/InterfaceHttpData.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/InterfaceHttpData.java new file mode 100644 index 00000000000..3f46a06a085 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/InterfaceHttpData.java @@ -0,0 +1,20 @@ +// Generated automatically from io.netty.handler.codec.http.multipart.InterfaceHttpData for testing purposes + +package io.netty.handler.codec.http.multipart; + +import io.netty.util.ReferenceCounted; + +public interface InterfaceHttpData extends Comparable, ReferenceCounted +{ + InterfaceHttpData retain(); + InterfaceHttpData retain(int p0); + InterfaceHttpData touch(); + InterfaceHttpData touch(Object p0); + InterfaceHttpData.HttpDataType getHttpDataType(); + String getName(); + static public enum HttpDataType + { + Attribute, FileUpload, InternalAttribute; + private HttpDataType() {} + } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/InterfaceHttpPostRequestDecoder.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/InterfaceHttpPostRequestDecoder.java new file mode 100644 index 00000000000..fa72ac7b57d --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/multipart/InterfaceHttpPostRequestDecoder.java @@ -0,0 +1,24 @@ +// Generated automatically from io.netty.handler.codec.http.multipart.InterfaceHttpPostRequestDecoder for testing purposes + +package io.netty.handler.codec.http.multipart; + +import io.netty.handler.codec.http.HttpContent; +import io.netty.handler.codec.http.multipart.InterfaceHttpData; +import java.util.List; + +public interface InterfaceHttpPostRequestDecoder +{ + InterfaceHttpData currentPartialHttpData(); + InterfaceHttpData getBodyHttpData(String p0); + InterfaceHttpData next(); + InterfaceHttpPostRequestDecoder offer(HttpContent p0); + List getBodyHttpDatas(); + List getBodyHttpDatas(String p0); + boolean hasNext(); + boolean isMultipart(); + int getDiscardThreshold(); + void cleanFiles(); + void destroy(); + void removeHttpDataFromClean(InterfaceHttpData p0); + void setDiscardThreshold(int p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/BinaryWebSocketFrame.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/BinaryWebSocketFrame.java new file mode 100644 index 00000000000..8ca9ea4ad93 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/BinaryWebSocketFrame.java @@ -0,0 +1,21 @@ +// Generated automatically from io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame for testing purposes + +package io.netty.handler.codec.http.websocketx; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.websocketx.WebSocketFrame; + +public class BinaryWebSocketFrame extends WebSocketFrame +{ + public BinaryWebSocketFrame copy(){ return null; } + public BinaryWebSocketFrame duplicate(){ return null; } + public BinaryWebSocketFrame replace(ByteBuf p0){ return null; } + public BinaryWebSocketFrame retain(){ return null; } + public BinaryWebSocketFrame retain(int p0){ return null; } + public BinaryWebSocketFrame retainedDuplicate(){ return null; } + public BinaryWebSocketFrame touch(){ return null; } + public BinaryWebSocketFrame touch(Object p0){ return null; } + public BinaryWebSocketFrame(){} + public BinaryWebSocketFrame(ByteBuf p0){} + public BinaryWebSocketFrame(boolean p0, int p1, ByteBuf p2){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/CloseWebSocketFrame.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/CloseWebSocketFrame.java new file mode 100644 index 00000000000..e2262cee001 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/CloseWebSocketFrame.java @@ -0,0 +1,28 @@ +// Generated automatically from io.netty.handler.codec.http.websocketx.CloseWebSocketFrame for testing purposes + +package io.netty.handler.codec.http.websocketx; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.websocketx.WebSocketCloseStatus; +import io.netty.handler.codec.http.websocketx.WebSocketFrame; + +public class CloseWebSocketFrame extends WebSocketFrame +{ + public CloseWebSocketFrame copy(){ return null; } + public CloseWebSocketFrame duplicate(){ return null; } + public CloseWebSocketFrame replace(ByteBuf p0){ return null; } + public CloseWebSocketFrame retain(){ return null; } + public CloseWebSocketFrame retain(int p0){ return null; } + public CloseWebSocketFrame retainedDuplicate(){ return null; } + public CloseWebSocketFrame touch(){ return null; } + public CloseWebSocketFrame touch(Object p0){ return null; } + public CloseWebSocketFrame(){} + public CloseWebSocketFrame(WebSocketCloseStatus p0){} + public CloseWebSocketFrame(WebSocketCloseStatus p0, String p1){} + public CloseWebSocketFrame(boolean p0, int p1){} + public CloseWebSocketFrame(boolean p0, int p1, ByteBuf p2){} + public CloseWebSocketFrame(boolean p0, int p1, int p2, String p3){} + public CloseWebSocketFrame(int p0, String p1){} + public String reasonText(){ return null; } + public int statusCode(){ return 0; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/ContinuationWebSocketFrame.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/ContinuationWebSocketFrame.java new file mode 100644 index 00000000000..1712af49f0c --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/ContinuationWebSocketFrame.java @@ -0,0 +1,23 @@ +// Generated automatically from io.netty.handler.codec.http.websocketx.ContinuationWebSocketFrame for testing purposes + +package io.netty.handler.codec.http.websocketx; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.websocketx.WebSocketFrame; + +public class ContinuationWebSocketFrame extends WebSocketFrame +{ + public ContinuationWebSocketFrame copy(){ return null; } + public ContinuationWebSocketFrame duplicate(){ return null; } + public ContinuationWebSocketFrame replace(ByteBuf p0){ return null; } + public ContinuationWebSocketFrame retain(){ return null; } + public ContinuationWebSocketFrame retain(int p0){ return null; } + public ContinuationWebSocketFrame retainedDuplicate(){ return null; } + public ContinuationWebSocketFrame touch(){ return null; } + public ContinuationWebSocketFrame touch(Object p0){ return null; } + public ContinuationWebSocketFrame(){} + public ContinuationWebSocketFrame(ByteBuf p0){} + public ContinuationWebSocketFrame(boolean p0, int p1, ByteBuf p2){} + public ContinuationWebSocketFrame(boolean p0, int p1, String p2){} + public String text(){ return null; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/PingWebSocketFrame.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/PingWebSocketFrame.java new file mode 100644 index 00000000000..f860f0ee9a2 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/PingWebSocketFrame.java @@ -0,0 +1,21 @@ +// Generated automatically from io.netty.handler.codec.http.websocketx.PingWebSocketFrame for testing purposes + +package io.netty.handler.codec.http.websocketx; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.websocketx.WebSocketFrame; + +public class PingWebSocketFrame extends WebSocketFrame +{ + public PingWebSocketFrame copy(){ return null; } + public PingWebSocketFrame duplicate(){ return null; } + public PingWebSocketFrame replace(ByteBuf p0){ return null; } + public PingWebSocketFrame retain(){ return null; } + public PingWebSocketFrame retain(int p0){ return null; } + public PingWebSocketFrame retainedDuplicate(){ return null; } + public PingWebSocketFrame touch(){ return null; } + public PingWebSocketFrame touch(Object p0){ return null; } + public PingWebSocketFrame(){} + public PingWebSocketFrame(ByteBuf p0){} + public PingWebSocketFrame(boolean p0, int p1, ByteBuf p2){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/PongWebSocketFrame.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/PongWebSocketFrame.java new file mode 100644 index 00000000000..548ebf5abb9 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/PongWebSocketFrame.java @@ -0,0 +1,21 @@ +// Generated automatically from io.netty.handler.codec.http.websocketx.PongWebSocketFrame for testing purposes + +package io.netty.handler.codec.http.websocketx; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.websocketx.WebSocketFrame; + +public class PongWebSocketFrame extends WebSocketFrame +{ + public PongWebSocketFrame copy(){ return null; } + public PongWebSocketFrame duplicate(){ return null; } + public PongWebSocketFrame replace(ByteBuf p0){ return null; } + public PongWebSocketFrame retain(){ return null; } + public PongWebSocketFrame retain(int p0){ return null; } + public PongWebSocketFrame retainedDuplicate(){ return null; } + public PongWebSocketFrame touch(){ return null; } + public PongWebSocketFrame touch(Object p0){ return null; } + public PongWebSocketFrame(){} + public PongWebSocketFrame(ByteBuf p0){} + public PongWebSocketFrame(boolean p0, int p1, ByteBuf p2){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/TextWebSocketFrame.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/TextWebSocketFrame.java new file mode 100644 index 00000000000..f473d8e166a --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/TextWebSocketFrame.java @@ -0,0 +1,24 @@ +// Generated automatically from io.netty.handler.codec.http.websocketx.TextWebSocketFrame for testing purposes + +package io.netty.handler.codec.http.websocketx; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.websocketx.WebSocketFrame; + +public class TextWebSocketFrame extends WebSocketFrame +{ + public String text(){ return null; } + public TextWebSocketFrame copy(){ return null; } + public TextWebSocketFrame duplicate(){ return null; } + public TextWebSocketFrame replace(ByteBuf p0){ return null; } + public TextWebSocketFrame retain(){ return null; } + public TextWebSocketFrame retain(int p0){ return null; } + public TextWebSocketFrame retainedDuplicate(){ return null; } + public TextWebSocketFrame touch(){ return null; } + public TextWebSocketFrame touch(Object p0){ return null; } + public TextWebSocketFrame(){} + public TextWebSocketFrame(ByteBuf p0){} + public TextWebSocketFrame(String p0){} + public TextWebSocketFrame(boolean p0, int p1, ByteBuf p2){} + public TextWebSocketFrame(boolean p0, int p1, String p2){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/WebSocketCloseStatus.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/WebSocketCloseStatus.java new file mode 100644 index 00000000000..20742532a32 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/WebSocketCloseStatus.java @@ -0,0 +1,34 @@ +// Generated automatically from io.netty.handler.codec.http.websocketx.WebSocketCloseStatus for testing purposes + +package io.netty.handler.codec.http.websocketx; + + +public class WebSocketCloseStatus implements Comparable +{ + protected WebSocketCloseStatus() {} + public String reasonText(){ return null; } + public String toString(){ return null; } + public WebSocketCloseStatus(int p0, String p1){} + public WebSocketCloseStatus(int p0, String p1, boolean p2){} + public boolean equals(Object p0){ return false; } + public int code(){ return 0; } + public int compareTo(WebSocketCloseStatus p0){ return 0; } + public int hashCode(){ return 0; } + public static WebSocketCloseStatus ABNORMAL_CLOSURE = null; + public static WebSocketCloseStatus BAD_GATEWAY = null; + public static WebSocketCloseStatus EMPTY = null; + public static WebSocketCloseStatus ENDPOINT_UNAVAILABLE = null; + public static WebSocketCloseStatus INTERNAL_SERVER_ERROR = null; + public static WebSocketCloseStatus INVALID_MESSAGE_TYPE = null; + public static WebSocketCloseStatus INVALID_PAYLOAD_DATA = null; + public static WebSocketCloseStatus MANDATORY_EXTENSION = null; + public static WebSocketCloseStatus MESSAGE_TOO_BIG = null; + public static WebSocketCloseStatus NORMAL_CLOSURE = null; + public static WebSocketCloseStatus POLICY_VIOLATION = null; + public static WebSocketCloseStatus PROTOCOL_ERROR = null; + public static WebSocketCloseStatus SERVICE_RESTART = null; + public static WebSocketCloseStatus TLS_HANDSHAKE_FAILED = null; + public static WebSocketCloseStatus TRY_AGAIN_LATER = null; + public static WebSocketCloseStatus valueOf(int p0){ return null; } + public static boolean isValidStatusCode(int p0){ return false; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/WebSocketFrame.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/WebSocketFrame.java new file mode 100644 index 00000000000..4e18beee70f --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http/websocketx/WebSocketFrame.java @@ -0,0 +1,24 @@ +// Generated automatically from io.netty.handler.codec.http.websocketx.WebSocketFrame for testing purposes + +package io.netty.handler.codec.http.websocketx; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.DefaultByteBufHolder; + +abstract public class WebSocketFrame extends DefaultByteBufHolder +{ + protected WebSocketFrame() {} + protected WebSocketFrame(ByteBuf p0){} + protected WebSocketFrame(boolean p0, int p1, ByteBuf p2){} + public String toString(){ return null; } + public WebSocketFrame copy(){ return null; } + public WebSocketFrame duplicate(){ return null; } + public WebSocketFrame retain(){ return null; } + public WebSocketFrame retain(int p0){ return null; } + public WebSocketFrame retainedDuplicate(){ return null; } + public WebSocketFrame touch(){ return null; } + public WebSocketFrame touch(Object p0){ return null; } + public abstract WebSocketFrame replace(ByteBuf p0); + public boolean isFinalFragment(){ return false; } + public int rsv(){ return 0; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Connection.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Connection.java new file mode 100644 index 00000000000..02aa022109c --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Connection.java @@ -0,0 +1,65 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2Connection for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http2.Http2FlowController; +import io.netty.handler.codec.http2.Http2LocalFlowController; +import io.netty.handler.codec.http2.Http2RemoteFlowController; +import io.netty.handler.codec.http2.Http2Stream; +import io.netty.handler.codec.http2.Http2StreamVisitor; +import io.netty.util.concurrent.Promise; + +public interface Http2Connection +{ + Http2Connection.Endpoint local(); + Http2Connection.Endpoint remote(); + Http2Connection.PropertyKey newKey(); + Http2Stream connectionStream(); + Http2Stream forEachActiveStream(Http2StreamVisitor p0); + Http2Stream stream(int p0); + boolean goAwayReceived(); + boolean goAwaySent(); + boolean goAwaySent(int p0, long p1, ByteBuf p2); + boolean isServer(); + boolean streamMayHaveExisted(int p0); + int numActiveStreams(); + io.netty.util.concurrent.Future close(Promise p0); + static public interface Endpoint + { + F flowController(); + Http2Connection.Endpoint opposite(); + Http2Stream createStream(int p0, boolean p1); + Http2Stream reservePushStream(int p0, Http2Stream p1); + boolean allowPushTo(); + boolean canOpenStream(); + boolean created(Http2Stream p0); + boolean isServer(); + boolean isValidStreamId(int p0); + boolean mayHaveCreatedStream(int p0); + int incrementAndGetNextStreamId(); + int lastStreamCreated(); + int lastStreamKnownByPeer(); + int maxActiveStreams(); + int numActiveStreams(); + void allowPushTo(boolean p0); + void flowController(F p0); + void maxActiveStreams(int p0); + } + static public interface Listener + { + void onGoAwayReceived(int p0, long p1, ByteBuf p2); + void onGoAwaySent(int p0, long p1, ByteBuf p2); + void onStreamActive(Http2Stream p0); + void onStreamAdded(Http2Stream p0); + void onStreamClosed(Http2Stream p0); + void onStreamHalfClosed(Http2Stream p0); + void onStreamRemoved(Http2Stream p0); + } + static public interface PropertyKey + { + } + void addListener(Http2Connection.Listener p0); + void goAwayReceived(int p0, long p1, ByteBuf p2); + void removeListener(Http2Connection.Listener p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2DataWriter.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2DataWriter.java new file mode 100644 index 00000000000..545bb56c75c --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2DataWriter.java @@ -0,0 +1,13 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2DataWriter for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; + +public interface Http2DataWriter +{ + ChannelFuture writeData(ChannelHandlerContext p0, int p1, ByteBuf p2, int p3, boolean p4, ChannelPromise p5); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Flags.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Flags.java new file mode 100644 index 00000000000..5f3720ba581 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Flags.java @@ -0,0 +1,33 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2Flags for testing purposes + +package io.netty.handler.codec.http2; + + +public class Http2Flags +{ + public Http2Flags ack(boolean p0){ return null; } + public Http2Flags endOfHeaders(boolean p0){ return null; } + public Http2Flags endOfStream(boolean p0){ return null; } + public Http2Flags paddingPresent(boolean p0){ return null; } + public Http2Flags priorityPresent(boolean p0){ return null; } + public Http2Flags setFlag(boolean p0, short p1){ return null; } + public Http2Flags(){} + public Http2Flags(short p0){} + public String toString(){ return null; } + public boolean ack(){ return false; } + public boolean endOfHeaders(){ return false; } + public boolean endOfStream(){ return false; } + public boolean equals(Object p0){ return false; } + public boolean isFlagSet(short p0){ return false; } + public boolean paddingPresent(){ return false; } + public boolean priorityPresent(){ return false; } + public int getNumPriorityBytes(){ return 0; } + public int getPaddingPresenceFieldLength(){ return 0; } + public int hashCode(){ return 0; } + public short value(){ return 0; } + public static short ACK = 0; + public static short END_HEADERS = 0; + public static short END_STREAM = 0; + public static short PADDED = 0; + public static short PRIORITY = 0; +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FlowController.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FlowController.java new file mode 100644 index 00000000000..28b89d0f24f --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FlowController.java @@ -0,0 +1,15 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2FlowController for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http2.Http2Stream; + +public interface Http2FlowController +{ + int initialWindowSize(); + int windowSize(Http2Stream p0); + void channelHandlerContext(ChannelHandlerContext p0); + void incrementWindowSize(Http2Stream p0, int p1); + void initialWindowSize(int p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Frame.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Frame.java new file mode 100644 index 00000000000..51daf95b02f --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Frame.java @@ -0,0 +1,9 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2Frame for testing purposes + +package io.netty.handler.codec.http2; + + +public interface Http2Frame +{ + String name(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FrameAdapter.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FrameAdapter.java new file mode 100644 index 00000000000..b4a12ef3d48 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FrameAdapter.java @@ -0,0 +1,28 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2FrameAdapter for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http2.Http2Flags; +import io.netty.handler.codec.http2.Http2FrameListener; +import io.netty.handler.codec.http2.Http2Headers; +import io.netty.handler.codec.http2.Http2Settings; + +public class Http2FrameAdapter implements Http2FrameListener +{ + public Http2FrameAdapter(){} + public int onDataRead(ChannelHandlerContext p0, int p1, ByteBuf p2, int p3, boolean p4){ return 0; } + public void onGoAwayRead(ChannelHandlerContext p0, int p1, long p2, ByteBuf p3){} + public void onHeadersRead(ChannelHandlerContext p0, int p1, Http2Headers p2, int p3, boolean p4){} + public void onHeadersRead(ChannelHandlerContext p0, int p1, Http2Headers p2, int p3, short p4, boolean p5, int p6, boolean p7){} + public void onPingAckRead(ChannelHandlerContext p0, long p1){} + public void onPingRead(ChannelHandlerContext p0, long p1){} + public void onPriorityRead(ChannelHandlerContext p0, int p1, int p2, short p3, boolean p4){} + public void onPushPromiseRead(ChannelHandlerContext p0, int p1, int p2, Http2Headers p3, int p4){} + public void onRstStreamRead(ChannelHandlerContext p0, int p1, long p2){} + public void onSettingsAckRead(ChannelHandlerContext p0){} + public void onSettingsRead(ChannelHandlerContext p0, Http2Settings p1){} + public void onUnknownFrame(ChannelHandlerContext p0, byte p1, int p2, Http2Flags p3, ByteBuf p4){} + public void onWindowUpdateRead(ChannelHandlerContext p0, int p1, int p2){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FrameListener.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FrameListener.java new file mode 100644 index 00000000000..5cdae13b92a --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FrameListener.java @@ -0,0 +1,26 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2FrameListener for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http2.Http2Flags; +import io.netty.handler.codec.http2.Http2Headers; +import io.netty.handler.codec.http2.Http2Settings; + +public interface Http2FrameListener +{ + int onDataRead(ChannelHandlerContext p0, int p1, ByteBuf p2, int p3, boolean p4); + void onGoAwayRead(ChannelHandlerContext p0, int p1, long p2, ByteBuf p3); + void onHeadersRead(ChannelHandlerContext p0, int p1, Http2Headers p2, int p3, boolean p4); + void onHeadersRead(ChannelHandlerContext p0, int p1, Http2Headers p2, int p3, short p4, boolean p5, int p6, boolean p7); + void onPingAckRead(ChannelHandlerContext p0, long p1); + void onPingRead(ChannelHandlerContext p0, long p1); + void onPriorityRead(ChannelHandlerContext p0, int p1, int p2, short p3, boolean p4); + void onPushPromiseRead(ChannelHandlerContext p0, int p1, int p2, Http2Headers p3, int p4); + void onRstStreamRead(ChannelHandlerContext p0, int p1, long p2); + void onSettingsAckRead(ChannelHandlerContext p0); + void onSettingsRead(ChannelHandlerContext p0, Http2Settings p1); + void onUnknownFrame(ChannelHandlerContext p0, byte p1, int p2, Http2Flags p3, ByteBuf p4); + void onWindowUpdateRead(ChannelHandlerContext p0, int p1, int p2); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FrameSizePolicy.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FrameSizePolicy.java new file mode 100644 index 00000000000..494a505a5c5 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FrameSizePolicy.java @@ -0,0 +1,10 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2FrameSizePolicy for testing purposes + +package io.netty.handler.codec.http2; + + +public interface Http2FrameSizePolicy +{ + int maxFrameSize(); + void maxFrameSize(int p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FrameStream.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FrameStream.java new file mode 100644 index 00000000000..607f176998d --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FrameStream.java @@ -0,0 +1,11 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2FrameStream for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.handler.codec.http2.Http2Stream; + +public interface Http2FrameStream +{ + Http2Stream.State state(); + int id(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FrameWriter.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FrameWriter.java new file mode 100644 index 00000000000..de8626737c4 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2FrameWriter.java @@ -0,0 +1,37 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2FrameWriter for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.handler.codec.http2.Http2DataWriter; +import io.netty.handler.codec.http2.Http2Flags; +import io.netty.handler.codec.http2.Http2FrameSizePolicy; +import io.netty.handler.codec.http2.Http2Headers; +import io.netty.handler.codec.http2.Http2HeadersEncoder; +import io.netty.handler.codec.http2.Http2Settings; +import java.io.Closeable; + +public interface Http2FrameWriter extends Closeable, Http2DataWriter +{ + ChannelFuture writeFrame(ChannelHandlerContext p0, byte p1, int p2, Http2Flags p3, ByteBuf p4, ChannelPromise p5); + ChannelFuture writeGoAway(ChannelHandlerContext p0, int p1, long p2, ByteBuf p3, ChannelPromise p4); + ChannelFuture writeHeaders(ChannelHandlerContext p0, int p1, Http2Headers p2, int p3, boolean p4, ChannelPromise p5); + ChannelFuture writeHeaders(ChannelHandlerContext p0, int p1, Http2Headers p2, int p3, short p4, boolean p5, int p6, boolean p7, ChannelPromise p8); + ChannelFuture writePing(ChannelHandlerContext p0, boolean p1, long p2, ChannelPromise p3); + ChannelFuture writePriority(ChannelHandlerContext p0, int p1, int p2, short p3, boolean p4, ChannelPromise p5); + ChannelFuture writePushPromise(ChannelHandlerContext p0, int p1, int p2, Http2Headers p3, int p4, ChannelPromise p5); + ChannelFuture writeRstStream(ChannelHandlerContext p0, int p1, long p2, ChannelPromise p3); + ChannelFuture writeSettings(ChannelHandlerContext p0, Http2Settings p1, ChannelPromise p2); + ChannelFuture writeSettingsAck(ChannelHandlerContext p0, ChannelPromise p1); + ChannelFuture writeWindowUpdate(ChannelHandlerContext p0, int p1, int p2, ChannelPromise p3); + Http2FrameWriter.Configuration configuration(); + static public interface Configuration + { + Http2FrameSizePolicy frameSizePolicy(); + Http2HeadersEncoder.Configuration headersConfiguration(); + } + void close(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Headers.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Headers.java new file mode 100644 index 00000000000..0196b60df27 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Headers.java @@ -0,0 +1,24 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2Headers for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.handler.codec.Headers; +import java.util.Iterator; +import java.util.Map; + +public interface Http2Headers extends Headers +{ + CharSequence authority(); + CharSequence method(); + CharSequence path(); + CharSequence scheme(); + CharSequence status(); + Http2Headers authority(CharSequence p0); + Http2Headers method(CharSequence p0); + Http2Headers path(CharSequence p0); + Http2Headers scheme(CharSequence p0); + Http2Headers status(CharSequence p0); + Iterator valueIterator(CharSequence p0); + Iterator> iterator(); + boolean contains(CharSequence p0, CharSequence p1, boolean p2); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2HeadersEncoder.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2HeadersEncoder.java new file mode 100644 index 00000000000..26d778433d3 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2HeadersEncoder.java @@ -0,0 +1,25 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2HeadersEncoder for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http2.Http2Headers; + +public interface Http2HeadersEncoder +{ + Http2HeadersEncoder.Configuration configuration(); + static Http2HeadersEncoder.SensitivityDetector ALWAYS_SENSITIVE = null; + static Http2HeadersEncoder.SensitivityDetector NEVER_SENSITIVE = null; + static public interface Configuration + { + long maxHeaderListSize(); + long maxHeaderTableSize(); + void maxHeaderListSize(long p0); + void maxHeaderTableSize(long p0); + } + static public interface SensitivityDetector + { + boolean isSensitive(CharSequence p0, CharSequence p1); + } + void encodeHeaders(int p0, Http2Headers p1, ByteBuf p2); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2HeadersFrame.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2HeadersFrame.java new file mode 100644 index 00000000000..1b4c1ebebb1 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2HeadersFrame.java @@ -0,0 +1,13 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2HeadersFrame for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.handler.codec.http2.Http2Headers; +import io.netty.handler.codec.http2.Http2StreamFrame; + +public interface Http2HeadersFrame extends Http2StreamFrame +{ + Http2Headers headers(); + boolean isEndStream(); + int padding(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2LocalFlowController.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2LocalFlowController.java new file mode 100644 index 00000000000..d60ab505ee0 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2LocalFlowController.java @@ -0,0 +1,17 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2LocalFlowController for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http2.Http2FlowController; +import io.netty.handler.codec.http2.Http2FrameWriter; +import io.netty.handler.codec.http2.Http2Stream; + +public interface Http2LocalFlowController extends Http2FlowController +{ + Http2LocalFlowController frameWriter(Http2FrameWriter p0); + boolean consumeBytes(Http2Stream p0, int p1); + int initialWindowSize(Http2Stream p0); + int unconsumedBytes(Http2Stream p0); + void receiveFlowControlledFrame(Http2Stream p0, ByteBuf p1, int p2, boolean p3); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2PushPromiseFrame.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2PushPromiseFrame.java new file mode 100644 index 00000000000..17025825958 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2PushPromiseFrame.java @@ -0,0 +1,17 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2PushPromiseFrame for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.handler.codec.http2.Http2FrameStream; +import io.netty.handler.codec.http2.Http2Headers; +import io.netty.handler.codec.http2.Http2StreamFrame; + +public interface Http2PushPromiseFrame extends Http2StreamFrame +{ + Http2FrameStream pushStream(); + Http2Headers http2Headers(); + Http2PushPromiseFrame stream(Http2FrameStream p0); + Http2StreamFrame pushStream(Http2FrameStream p0); + int padding(); + int promisedStreamId(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2RemoteFlowController.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2RemoteFlowController.java new file mode 100644 index 00000000000..f20af5c9790 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2RemoteFlowController.java @@ -0,0 +1,31 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2RemoteFlowController for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http2.Http2FlowController; +import io.netty.handler.codec.http2.Http2Stream; + +public interface Http2RemoteFlowController extends Http2FlowController +{ + ChannelHandlerContext channelHandlerContext(); + boolean hasFlowControlled(Http2Stream p0); + boolean isWritable(Http2Stream p0); + static public interface FlowControlled + { + boolean merge(ChannelHandlerContext p0, Http2RemoteFlowController.FlowControlled p1); + int size(); + void error(ChannelHandlerContext p0, Throwable p1); + void write(ChannelHandlerContext p0, int p1); + void writeComplete(); + } + static public interface Listener + { + void writabilityChanged(Http2Stream p0); + } + void addFlowControlled(Http2Stream p0, Http2RemoteFlowController.FlowControlled p1); + void channelWritabilityChanged(); + void listener(Http2RemoteFlowController.Listener p0); + void updateDependencyTree(int p0, int p1, short p2, boolean p3); + void writePendingBytes(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Settings.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Settings.java new file mode 100644 index 00000000000..7aa14ef63bb --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Settings.java @@ -0,0 +1,29 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2Settings for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.util.collection.CharObjectHashMap; + +public class Http2Settings extends CharObjectHashMap +{ + protected String keyToString(char p0){ return null; } + public Boolean pushEnabled(){ return null; } + public Http2Settings copyFrom(Http2Settings p0){ return null; } + public Http2Settings headerTableSize(long p0){ return null; } + public Http2Settings initialWindowSize(int p0){ return null; } + public Http2Settings maxConcurrentStreams(long p0){ return null; } + public Http2Settings maxFrameSize(int p0){ return null; } + public Http2Settings maxHeaderListSize(long p0){ return null; } + public Http2Settings pushEnabled(boolean p0){ return null; } + public Http2Settings(){} + public Http2Settings(int p0){} + public Http2Settings(int p0, float p1){} + public Integer getIntValue(char p0){ return null; } + public Integer initialWindowSize(){ return null; } + public Integer maxFrameSize(){ return null; } + public Long headerTableSize(){ return null; } + public Long maxConcurrentStreams(){ return null; } + public Long maxHeaderListSize(){ return null; } + public Long put(char p0, Long p1){ return null; } + public static Http2Settings defaultSettings(){ return null; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Stream.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Stream.java new file mode 100644 index 00000000000..83bd0496e26 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2Stream.java @@ -0,0 +1,35 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2Stream for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.handler.codec.http2.Http2Connection; + +public interface Http2Stream +{ + V getProperty(Http2Connection.PropertyKey p0); + V removeProperty(Http2Connection.PropertyKey p0); + V setProperty(Http2Connection.PropertyKey p0, V p1); + Http2Stream close(); + Http2Stream closeLocalSide(); + Http2Stream closeRemoteSide(); + Http2Stream headersReceived(boolean p0); + Http2Stream headersSent(boolean p0); + Http2Stream open(boolean p0); + Http2Stream pushPromiseSent(); + Http2Stream resetSent(); + Http2Stream.State state(); + boolean isHeadersReceived(); + boolean isHeadersSent(); + boolean isPushPromiseSent(); + boolean isResetSent(); + boolean isTrailersReceived(); + boolean isTrailersSent(); + int id(); + static public enum State + { + CLOSED, HALF_CLOSED_LOCAL, HALF_CLOSED_REMOTE, IDLE, OPEN, RESERVED_LOCAL, RESERVED_REMOTE; + private State() {} + public boolean localSideOpen(){ return false; } + public boolean remoteSideOpen(){ return false; } + } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2StreamFrame.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2StreamFrame.java new file mode 100644 index 00000000000..acad086e05f --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2StreamFrame.java @@ -0,0 +1,12 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2StreamFrame for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.handler.codec.http2.Http2Frame; +import io.netty.handler.codec.http2.Http2FrameStream; + +public interface Http2StreamFrame extends Http2Frame +{ + Http2FrameStream stream(); + Http2StreamFrame stream(Http2FrameStream p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2StreamVisitor.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2StreamVisitor.java new file mode 100644 index 00000000000..a3cb43954c9 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/Http2StreamVisitor.java @@ -0,0 +1,10 @@ +// Generated automatically from io.netty.handler.codec.http2.Http2StreamVisitor for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.handler.codec.http2.Http2Stream; + +public interface Http2StreamVisitor +{ + boolean visit(Http2Stream p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/HttpConversionUtil.java b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/HttpConversionUtil.java new file mode 100644 index 00000000000..ce7244b42d3 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/handler/codec/http2/HttpConversionUtil.java @@ -0,0 +1,37 @@ +// Generated automatically from io.netty.handler.codec.http2.HttpConversionUtil for testing purposes + +package io.netty.handler.codec.http2; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.handler.codec.http.FullHttpMessage; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpMessage; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpRequest; +import io.netty.handler.codec.http.HttpResponse; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; +import io.netty.handler.codec.http2.Http2Headers; + +public class HttpConversionUtil +{ + protected HttpConversionUtil() {} + public static FullHttpRequest toFullHttpRequest(int p0, Http2Headers p1, ByteBuf p2, boolean p3){ return null; } + public static FullHttpRequest toFullHttpRequest(int p0, Http2Headers p1, ByteBufAllocator p2, boolean p3){ return null; } + public static FullHttpResponse toFullHttpResponse(int p0, Http2Headers p1, ByteBuf p2, boolean p3){ return null; } + public static FullHttpResponse toFullHttpResponse(int p0, Http2Headers p1, ByteBufAllocator p2, boolean p3){ return null; } + public static Http2Headers toHttp2Headers(HttpHeaders p0, boolean p1){ return null; } + public static Http2Headers toHttp2Headers(HttpMessage p0, boolean p1){ return null; } + public static HttpMethod OUT_OF_MESSAGE_SEQUENCE_METHOD = null; + public static HttpRequest toHttpRequest(int p0, Http2Headers p1, boolean p2){ return null; } + public static HttpResponse toHttpResponse(int p0, Http2Headers p1, boolean p2){ return null; } + public static HttpResponseStatus OUT_OF_MESSAGE_SEQUENCE_RETURN_CODE = null; + public static HttpResponseStatus parseStatus(CharSequence p0){ return null; } + public static String OUT_OF_MESSAGE_SEQUENCE_PATH = null; + public static void addHttp2ToHttpHeaders(int p0, Http2Headers p1, FullHttpMessage p2, boolean p3){} + public static void addHttp2ToHttpHeaders(int p0, Http2Headers p1, HttpHeaders p2, HttpVersion p3, boolean p4, boolean p5){} + public static void toHttp2Headers(HttpHeaders p0, Http2Headers p1){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/util/AbstractConstant.java b/java/ql/test/stubs/netty-4.1.x/io/netty/util/AbstractConstant.java new file mode 100644 index 00000000000..e658440075f --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/util/AbstractConstant.java @@ -0,0 +1,17 @@ +// Generated automatically from io.netty.util.AbstractConstant for testing purposes + +package io.netty.util; + +import io.netty.util.Constant; + +abstract public class AbstractConstant> implements Constant +{ + protected AbstractConstant() {} + protected AbstractConstant(int p0, String p1){} + public final String name(){ return null; } + public final String toString(){ return null; } + public final boolean equals(Object p0){ return false; } + public final int compareTo(T p0){ return 0; } + public final int hashCode(){ return 0; } + public final int id(){ return 0; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/util/AbstractReferenceCounted.java b/java/ql/test/stubs/netty-4.1.x/io/netty/util/AbstractReferenceCounted.java new file mode 100644 index 00000000000..17241013a37 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/util/AbstractReferenceCounted.java @@ -0,0 +1,18 @@ +// Generated automatically from io.netty.util.AbstractReferenceCounted for testing purposes + +package io.netty.util; + +import io.netty.util.ReferenceCounted; + +abstract public class AbstractReferenceCounted implements ReferenceCounted +{ + protected abstract void deallocate(); + protected final void setRefCnt(int p0){} + public AbstractReferenceCounted(){} + public ReferenceCounted retain(){ return null; } + public ReferenceCounted retain(int p0){ return null; } + public ReferenceCounted touch(){ return null; } + public boolean release(){ return false; } + public boolean release(int p0){ return false; } + public int refCnt(){ return 0; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/util/AsciiString.java b/java/ql/test/stubs/netty-4.1.x/io/netty/util/AsciiString.java new file mode 100644 index 00000000000..deff60c029b --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/util/AsciiString.java @@ -0,0 +1,119 @@ +// Generated automatically from io.netty.util.AsciiString for testing purposes + +package io.netty.util; + +import io.netty.util.ByteProcessor; +import io.netty.util.HashingStrategy; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.util.Collection; + +public class AsciiString implements CharSequence, Comparable +{ + protected AsciiString() {} + public AsciiString concat(CharSequence p0){ return null; } + public AsciiString replace(char p0, char p1){ return null; } + public AsciiString subSequence(int p0){ return null; } + public AsciiString subSequence(int p0, int p1){ return null; } + public AsciiString subSequence(int p0, int p1, boolean p2){ return null; } + public AsciiString toLowerCase(){ return null; } + public AsciiString toUpperCase(){ return null; } + public AsciiString trim(){ return null; } + public AsciiString(ByteBuffer p0){} + public AsciiString(ByteBuffer p0, boolean p1){} + public AsciiString(ByteBuffer p0, int p1, int p2, boolean p3){} + public AsciiString(CharSequence p0){} + public AsciiString(CharSequence p0, Charset p1){} + public AsciiString(CharSequence p0, Charset p1, int p2, int p3){} + public AsciiString(CharSequence p0, int p1, int p2){} + public AsciiString(byte[] p0){} + public AsciiString(byte[] p0, boolean p1){} + public AsciiString(byte[] p0, int p1, int p2, boolean p3){} + public AsciiString(char[] p0){} + public AsciiString(char[] p0, Charset p1){} + public AsciiString(char[] p0, Charset p1, int p2, int p3){} + public AsciiString(char[] p0, int p1, int p2){} + public AsciiString[] split(String p0, int p1){ return null; } + public AsciiString[] split(char p0){ return null; } + public String toString(){ return null; } + public String toString(int p0){ return null; } + public String toString(int p0, int p1){ return null; } + public boolean contains(CharSequence p0){ return false; } + public boolean contentEquals(CharSequence p0){ return false; } + public boolean contentEqualsIgnoreCase(CharSequence p0){ return false; } + public boolean endsWith(CharSequence p0){ return false; } + public boolean equals(Object p0){ return false; } + public boolean isEmpty(){ return false; } + public boolean isEntireArrayUsed(){ return false; } + public boolean matches(String p0){ return false; } + public boolean parseBoolean(){ return false; } + public boolean regionMatches(boolean p0, int p1, CharSequence p2, int p3, int p4){ return false; } + public boolean regionMatches(int p0, CharSequence p1, int p2, int p3){ return false; } + public boolean startsWith(CharSequence p0){ return false; } + public boolean startsWith(CharSequence p0, int p1){ return false; } + public byte byteAt(int p0){ return 0; } + public byte[] array(){ return null; } + public byte[] toByteArray(){ return null; } + public byte[] toByteArray(int p0, int p1){ return null; } + public char charAt(int p0){ return '0'; } + public char parseChar(){ return '0'; } + public char parseChar(int p0){ return '0'; } + public char[] toCharArray(){ return null; } + public char[] toCharArray(int p0, int p1){ return null; } + public double parseDouble(){ return 0; } + public double parseDouble(int p0, int p1){ return 0; } + public float parseFloat(){ return 0; } + public float parseFloat(int p0, int p1){ return 0; } + public int arrayOffset(){ return 0; } + public int compareTo(CharSequence p0){ return 0; } + public int forEachByte(ByteProcessor p0){ return 0; } + public int forEachByte(int p0, int p1, ByteProcessor p2){ return 0; } + public int forEachByteDesc(ByteProcessor p0){ return 0; } + public int forEachByteDesc(int p0, int p1, ByteProcessor p2){ return 0; } + public int hashCode(){ return 0; } + public int indexOf(CharSequence p0){ return 0; } + public int indexOf(CharSequence p0, int p1){ return 0; } + public int indexOf(char p0, int p1){ return 0; } + public int lastIndexOf(CharSequence p0){ return 0; } + public int lastIndexOf(CharSequence p0, int p1){ return 0; } + public int length(){ return 0; } + public int parseInt(){ return 0; } + public int parseInt(int p0){ return 0; } + public int parseInt(int p0, int p1){ return 0; } + public int parseInt(int p0, int p1, int p2){ return 0; } + public long parseLong(){ return 0; } + public long parseLong(int p0){ return 0; } + public long parseLong(int p0, int p1){ return 0; } + public long parseLong(int p0, int p1, int p2){ return 0; } + public short parseShort(){ return 0; } + public short parseShort(int p0){ return 0; } + public short parseShort(int p0, int p1){ return 0; } + public short parseShort(int p0, int p1, int p2){ return 0; } + public static AsciiString EMPTY_STRING = null; + public static AsciiString cached(String p0){ return null; } + public static AsciiString of(CharSequence p0){ return null; } + public static CharSequence trim(CharSequence p0){ return null; } + public static HashingStrategy CASE_INSENSITIVE_HASHER = null; + public static HashingStrategy CASE_SENSITIVE_HASHER = null; + public static boolean contains(CharSequence p0, CharSequence p1){ return false; } + public static boolean containsAllContentEqualsIgnoreCase(Collection p0, Collection p1){ return false; } + public static boolean containsContentEqualsIgnoreCase(Collection p0, CharSequence p1){ return false; } + public static boolean containsIgnoreCase(CharSequence p0, CharSequence p1){ return false; } + public static boolean contentEquals(CharSequence p0, CharSequence p1){ return false; } + public static boolean contentEqualsIgnoreCase(CharSequence p0, CharSequence p1){ return false; } + public static boolean isUpperCase(byte p0){ return false; } + public static boolean isUpperCase(char p0){ return false; } + public static boolean regionMatches(CharSequence p0, boolean p1, int p2, CharSequence p3, int p4, int p5){ return false; } + public static boolean regionMatchesAscii(CharSequence p0, boolean p1, int p2, CharSequence p3, int p4, int p5){ return false; } + public static byte c2b(char p0){ return 0; } + public static char b2c(byte p0){ return '0'; } + public static char toLowerCase(char p0){ return '0'; } + public static int INDEX_NOT_FOUND = 0; + public static int hashCode(CharSequence p0){ return 0; } + public static int indexOf(CharSequence p0, char p1, int p2){ return 0; } + public static int indexOfIgnoreCase(CharSequence p0, CharSequence p1, int p2){ return 0; } + public static int indexOfIgnoreCaseAscii(CharSequence p0, CharSequence p1, int p2){ return 0; } + public void arrayChanged(){} + public void copy(int p0, byte[] p1, int p2, int p3){} + public void copy(int p0, char[] p1, int p2, int p3){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/util/Attribute.java b/java/ql/test/stubs/netty-4.1.x/io/netty/util/Attribute.java new file mode 100644 index 00000000000..7ff2a84793f --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/util/Attribute.java @@ -0,0 +1,17 @@ +// Generated automatically from io.netty.util.Attribute for testing purposes + +package io.netty.util; + +import io.netty.util.AttributeKey; + +public interface Attribute +{ + T get(); + T getAndRemove(); + T getAndSet(T p0); + T setIfAbsent(T p0); + boolean compareAndSet(T p0, T p1); + io.netty.util.AttributeKey key(); + void remove(); + void set(T p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/util/AttributeKey.java b/java/ql/test/stubs/netty-4.1.x/io/netty/util/AttributeKey.java new file mode 100644 index 00000000000..9b8eedd4eac --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/util/AttributeKey.java @@ -0,0 +1,14 @@ +// Generated automatically from io.netty.util.AttributeKey for testing purposes + +package io.netty.util; + +import io.netty.util.AbstractConstant; + +public class AttributeKey extends AbstractConstant> +{ + protected AttributeKey() {} + public static io.netty.util.AttributeKey newInstance(String p0){ return null; } + public static io.netty.util.AttributeKey valueOf(Class p0, String p1){ return null; } + public static io.netty.util.AttributeKey valueOf(String p0){ return null; } + public static boolean exists(String p0){ return false; } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/util/AttributeMap.java b/java/ql/test/stubs/netty-4.1.x/io/netty/util/AttributeMap.java new file mode 100644 index 00000000000..ff1e835ca34 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/util/AttributeMap.java @@ -0,0 +1,12 @@ +// Generated automatically from io.netty.util.AttributeMap for testing purposes + +package io.netty.util; + +import io.netty.util.Attribute; +import io.netty.util.AttributeKey; + +public interface AttributeMap +{ + boolean hasAttr(io.netty.util.AttributeKey p0); + io.netty.util.Attribute attr(io.netty.util.AttributeKey p0); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/util/ByteProcessor.java b/java/ql/test/stubs/netty-4.1.x/io/netty/util/ByteProcessor.java new file mode 100644 index 00000000000..197b5718d3e --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/util/ByteProcessor.java @@ -0,0 +1,22 @@ +// Generated automatically from io.netty.util.ByteProcessor for testing purposes + +package io.netty.util; + + +public interface ByteProcessor +{ + boolean process(byte p0); + static ByteProcessor FIND_ASCII_SPACE = null; + static ByteProcessor FIND_COMMA = null; + static ByteProcessor FIND_CR = null; + static ByteProcessor FIND_CRLF = null; + static ByteProcessor FIND_LF = null; + static ByteProcessor FIND_LINEAR_WHITESPACE = null; + static ByteProcessor FIND_NON_CR = null; + static ByteProcessor FIND_NON_CRLF = null; + static ByteProcessor FIND_NON_LF = null; + static ByteProcessor FIND_NON_LINEAR_WHITESPACE = null; + static ByteProcessor FIND_NON_NUL = null; + static ByteProcessor FIND_NUL = null; + static ByteProcessor FIND_SEMI_COLON = null; +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/util/Constant.java b/java/ql/test/stubs/netty-4.1.x/io/netty/util/Constant.java new file mode 100644 index 00000000000..81b3077356b --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/util/Constant.java @@ -0,0 +1,10 @@ +// Generated automatically from io.netty.util.Constant for testing purposes + +package io.netty.util; + + +public interface Constant> extends java.lang.Comparable +{ + String name(); + int id(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/util/HashingStrategy.java b/java/ql/test/stubs/netty-4.1.x/io/netty/util/HashingStrategy.java new file mode 100644 index 00000000000..ae15407bd09 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/util/HashingStrategy.java @@ -0,0 +1,11 @@ +// Generated automatically from io.netty.util.HashingStrategy for testing purposes + +package io.netty.util; + + +public interface HashingStrategy +{ + boolean equals(T p0, T p1); + int hashCode(T p0); + static HashingStrategy JAVA_HASHER = null; +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/util/ReferenceCounted.java b/java/ql/test/stubs/netty-4.1.x/io/netty/util/ReferenceCounted.java new file mode 100644 index 00000000000..219a5523ed3 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/util/ReferenceCounted.java @@ -0,0 +1,15 @@ +// Generated automatically from io.netty.util.ReferenceCounted for testing purposes + +package io.netty.util; + + +public interface ReferenceCounted +{ + ReferenceCounted retain(); + ReferenceCounted retain(int p0); + ReferenceCounted touch(); + ReferenceCounted touch(Object p0); + boolean release(); + boolean release(int p0); + int refCnt(); +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/util/Signal.java b/java/ql/test/stubs/netty-4.1.x/io/netty/util/Signal.java new file mode 100644 index 00000000000..1d6b4915b8e --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/util/Signal.java @@ -0,0 +1,21 @@ +// Generated automatically from io.netty.util.Signal for testing purposes + +package io.netty.util; + +import io.netty.util.Constant; + +public class Signal extends Error implements Constant +{ + protected Signal() {} + public String name(){ return null; } + public String toString(){ return null; } + public Throwable fillInStackTrace(){ return null; } + public Throwable initCause(Throwable p0){ return null; } + public boolean equals(Object p0){ return false; } + public int compareTo(Signal p0){ return 0; } + public int hashCode(){ return 0; } + public int id(){ return 0; } + public static Signal valueOf(Class p0, String p1){ return null; } + public static Signal valueOf(String p0){ return null; } + public void expect(Signal p0){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/util/collection/CharObjectHashMap.java b/java/ql/test/stubs/netty-4.1.x/io/netty/util/collection/CharObjectHashMap.java new file mode 100644 index 00000000000..2c90b798889 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/util/collection/CharObjectHashMap.java @@ -0,0 +1,38 @@ +// Generated automatically from io.netty.util.collection.CharObjectHashMap for testing purposes + +package io.netty.util.collection; + +import io.netty.util.collection.CharObjectMap; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +public class CharObjectHashMap implements CharObjectMap +{ + protected String keyToString(char p0){ return null; } + public CharObjectHashMap(){} + public CharObjectHashMap(int p0){} + public CharObjectHashMap(int p0, float p1){} + public Set keySet(){ return null; } + public String toString(){ return null; } + public V get(Object p0){ return null; } + public V get(char p0){ return null; } + public V put(Character p0, V p1){ return null; } + public V put(char p0, V p1){ return null; } + public V remove(Object p0){ return null; } + public V remove(char p0){ return null; } + public boolean containsKey(Object p0){ return false; } + public boolean containsKey(char p0){ return false; } + public boolean containsValue(Object p0){ return false; } + public boolean equals(Object p0){ return false; } + public boolean isEmpty(){ return false; } + public int hashCode(){ return 0; } + public int size(){ return 0; } + public java.lang.Iterable> entries(){ return null; } + public java.util.Collection values(){ return null; } + public java.util.Set> entrySet(){ return null; } + public static float DEFAULT_LOAD_FACTOR = 0; + public static int DEFAULT_CAPACITY = 0; + public void clear(){} + public void putAll(java.util.Map p0){} +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/util/collection/CharObjectMap.java b/java/ql/test/stubs/netty-4.1.x/io/netty/util/collection/CharObjectMap.java new file mode 100644 index 00000000000..1627dad1d54 --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/util/collection/CharObjectMap.java @@ -0,0 +1,20 @@ +// Generated automatically from io.netty.util.collection.CharObjectMap for testing purposes + +package io.netty.util.collection; + +import java.util.Map; + +public interface CharObjectMap extends java.util.Map +{ + V get(char p0); + V put(char p0, V p1); + V remove(char p0); + boolean containsKey(char p0); + java.lang.Iterable> entries(); + static public interface PrimitiveEntry + { + V value(); + char key(); + void setValue(V p0); + } +} diff --git a/java/ql/test/stubs/netty-4.1.x/io/netty/util/concurrent/OrderedEventExecutor.java b/java/ql/test/stubs/netty-4.1.x/io/netty/util/concurrent/OrderedEventExecutor.java new file mode 100644 index 00000000000..273107cb6db --- /dev/null +++ b/java/ql/test/stubs/netty-4.1.x/io/netty/util/concurrent/OrderedEventExecutor.java @@ -0,0 +1,9 @@ +// Generated automatically from io.netty.util.concurrent.OrderedEventExecutor for testing purposes + +package io.netty.util.concurrent; + +import io.netty.util.concurrent.EventExecutor; + +public interface OrderedEventExecutor extends EventExecutor +{ +} diff --git a/javascript/documentation/library-customization.rst b/javascript/documentation/library-customization.rst index 62d8756e0a1..b06e5b5cab1 100644 --- a/javascript/documentation/library-customization.rst +++ b/javascript/documentation/library-customization.rst @@ -2,7 +2,7 @@ Customizing the JavaScript analysis =================================== This document describes the main extension points offered by the JavaScript analysis for customizing -analysis behavior without editing the queries or libraries themselves. +analysis behavior from CodeQL without editing the queries or libraries themselves. Customization mechanisms ------------------------ diff --git a/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/diagnostics.expected b/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/diagnostics.expected new file mode 100644 index 00000000000..72108d0ebb5 --- /dev/null +++ b/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/diagnostics.expected @@ -0,0 +1,15 @@ +{ + "timestamp": "2023-03-23T12:04:41.317+00:00", + "source": { + "id": "js/internal-error", + "name": "Internal error", + "extractorName": "javascript" + }, + "markdownMessage": "Internal error: com.semmle.util.exception.CatastrophicError: The TypeScript parser wrapper crashed with exit code 1", + "severity": "unknown", + "visibility": { + "cliSummaryTable": true, + "statusPage": false, + "telemetry": true + } +} \ No newline at end of file diff --git a/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/src/my_failure.ts b/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/src/my_failure.ts new file mode 100644 index 00000000000..29e78b136e8 --- /dev/null +++ b/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/src/my_failure.ts @@ -0,0 +1,17 @@ +type Output = { + (...args: S): any; +}; + +declare function createThing( + type: K, + fn: (...args: S) => any +): Output; + +const one = createThing("one", () => ({})); + +const two = createThing("two", () => ({})); + +const three = createThing("three", (cursor: string) => null); +const four = createThing("four", (error: number) => null); + +type Events = Array; diff --git a/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/test.py b/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/test.py new file mode 100644 index 00000000000..3f6c33bf31c --- /dev/null +++ b/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/test.py @@ -0,0 +1,7 @@ +import os +from create_database_utils import * +from diagnostics_test_utils import * + +run_codeql_database_create([], lang="javascript", runFunction = runUnsuccessfully, db = None) + +check_diagnostics() diff --git a/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/tsconfig.json b/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/tsconfig.json new file mode 100644 index 00000000000..9e26dfeeb6e --- /dev/null +++ b/javascript/ql/integration-tests/all-platforms/diagnostics/internal-error/tsconfig.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/javascript/ql/lib/qlpack.yml b/javascript/ql/lib/qlpack.yml index 5c650164c39..99f044a6431 100644 --- a/javascript/ql/lib/qlpack.yml +++ b/javascript/ql/lib/qlpack.yml @@ -8,5 +8,6 @@ upgrades: upgrades dependencies: codeql/regex: ${workspace} codeql/tutorial: ${workspace} + codeql/util: ${workspace} dataExtensions: - semmle/javascript/frameworks/**/model.yml diff --git a/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll index dc28e44ecdd..e9828e5bf25 100644 --- a/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll @@ -243,6 +243,11 @@ module AccessPath { root.isGlobal() ) or + exists(Assignment assign | + fromReference(assign.getLhs().flow(), root) = result and + node = assign.getRhs().flow() + ) + or exists(FunctionDeclStmt fun | node = DataFlow::valueNode(fun) and result = fun.getIdentifier().(GlobalVarDecl).getName() and @@ -270,6 +275,19 @@ module AccessPath { /** A module for computing an access to a variable that happens after a property has been written onto it */ private module GetLaterAccess { + /** + * Gets an reference to the SSA variable `variable`. + * Either the definition or a use of the SSA variable + */ + private VarRef getAVariableRef(SsaVariable variable) { + ( + result = variable.getAUse() + or + result = variable.getDefinition().(SsaExplicitDefinition).getDef().getTarget() + ) and + variable = getARelevantVariableSimple() + } + /** * Gets an access to a variable that is written to in `write`, where the access is after the write. * @@ -286,7 +304,7 @@ module AccessPath { pragma[noopt] DataFlow::Node getLaterBaseAccess(DataFlow::PropWrite write) { exists( - ControlFlowNode writeNode, BindingPattern access, VarRef otherAccess, Variable variable, + ControlFlowNode writeNode, BindingPattern access, VarRef otherAccess, SsaVariable variable, StmtContainer container | access = getBaseVar(write) and @@ -303,7 +321,7 @@ module AccessPath { i < j ) or - otherAccess.getBasicBlock() = getASuccessorBBThatReadsVar(write) // more manual magic - outlined into a helper predicate. + otherAccess.getBasicBlock() = getASuccessorBBThatReadsVar(write) ) } @@ -323,24 +341,34 @@ module AccessPath { } /** Gets an access to `var` inside `container` where `usedInWrite` indicates whether the access is the base of a property write. */ - private VarRef getAnAccessInContainer(Variable var, StmtContainer container, boolean usedInWrite) { - result.getVariable() = var and + private VarRef getAnAccessInContainer( + SsaVariable var, StmtContainer container, boolean usedInWrite + ) { + result = getAVariableRef(var) and result.getContainer() = container and - var.isLocal() and if result = getBaseVar(_) then usedInWrite = true else usedInWrite = false } - /** Gets a variable that is relevant for the computations in the `GetLaterAccess` module. */ - private Variable getARelevantVariable() { + /** + * Gets a variable that is relevant for the computations in the `GetLaterAccess` module. + * This predicate restricts as much as it can, but without depending on `getAVariableRef`. + */ + pragma[inline] + private SsaVariable getARelevantVariableSimple() { // The variable might be used where `getLaterBaseAccess()` is called. exists(DataFlow::Node node | exists(fromRhs(node, _)) and - node.asExpr().(VarAccess).getVariable() = result - ) and + node.asExpr() = result.getAUse() + ) + } + + /** + * Gets a variable that is relevant for the computations in the `GetLaterAccess` module. + * This predicate depends on `getAVariableRef`, which in turn depends on `getARelevantVariableSimple`. + */ + private SsaVariable getARelevantVariable() { // There is a write that writes to the variable. - getBaseVar(_).getVariable() = result and - // It's local. - result.isLocal() and // we skip global variables, because that turns messy quick. + getBaseVar(_) = getAVariableRef(result) and // There is both a "write" and "read" in the same container of the variable. exists(StmtContainer container | exists(getAnAccessInContainer(result, container, true)) and // a "write", an access to the variable that is the base of a property reference. @@ -350,15 +378,15 @@ module AccessPath { /** Gets a basic-block that has a read of the variable that is written to by `write`, where the basicblock occurs after `start`. */ private ReachableBasicBlock getASuccessorBBThatReadsVar(DataFlow::PropWrite write) { - exists(VarAccess baseExpr, Variable var, ControlFlowNode writeNode | + exists(VarRef baseExpr, SsaVariable var, ControlFlowNode writeNode | baseExpr = getBaseVar(write) and - var = baseExpr.getVariable() and + getAVariableRef(var) = baseExpr and var = getARelevantVariable() and writeNode = write.getWriteNode() and - writeNode.getBasicBlock().(ReachableBasicBlock).strictlyDominates(result) and - // manual magic. - result = getAnAccessInContainer(getARelevantVariable(), _, false).getBasicBlock() + result.getImmediateDominator() = writeNode.getBasicBlock() ) + or + result.getImmediateDominator() = getASuccessorBBThatReadsVar(write) } } diff --git a/javascript/ql/lib/semmle/javascript/Unit.qll b/javascript/ql/lib/semmle/javascript/Unit.qll index dbc59f541e6..83a4a03321d 100644 --- a/javascript/ql/lib/semmle/javascript/Unit.qll +++ b/javascript/ql/lib/semmle/javascript/Unit.qll @@ -1,10 +1,3 @@ /** Provides the `Unit` class. */ -/** The unit type. */ -private newtype TUnit = TMkUnit() - -/** The trivial type with a single element. */ -class Unit extends TUnit { - /** Gets a textual representation of this element. */ - string toString() { result = "Unit" } -} +import codeql.util.Unit diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll index 1b7e8cb326a..227f4ea22fb 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll @@ -63,10 +63,9 @@ * the type is not intended to match a static type. */ +private import codeql.util.Unit private import ApiGraphModelsSpecific as Specific -private class Unit = Specific::Unit; - private module API = Specific::API; private module DataFlow = Specific::DataFlow; diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll index 9ebbe4099db..ee2fd74b5de 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll @@ -22,8 +22,6 @@ private import javascript as JS private import ApiGraphModels -class Unit = JS::Unit; - // Re-export libraries needed by ApiGraphModels.qll module API = JS::API; diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssQuery.qll index 8eb9d6d6849..e26b4eea8c8 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssQuery.qll @@ -122,6 +122,14 @@ class Configuration extends TaintTracking::Configuration { TaintedUrlSuffix::step(src, trg, TaintedUrlSuffix::label(), DataFlow::FlowLabel::taint()) and inlbl = TaintedUrlSuffix::label() and outlbl = prefixLabel() + or + exists(DataFlow::FunctionNode callback, DataFlow::Node arg | + any(JQuery::MethodCall c).interpretsArgumentAsHtml(arg) and + callback = arg.getABoundFunctionValue(_) and + src = callback.getReturnNode() and + trg = callback and + inlbl = outlbl + ) } } diff --git a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql index 0f7e22b7f57..9826ebefe5f 100644 --- a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql +++ b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.ql @@ -21,4 +21,4 @@ where cfg.hasFlowPath(source, sink) and not source.getNode() instanceof CleartextPasswordExpr // flagged by js/insufficient-password-hash select sink.getNode(), source, sink, "A broken or weak cryptographic algorithm depends on $@.", - source.getNode(), "sensitive data from" + source.getNode().(Source).describe() + source.getNode(), "sensitive data from " + source.getNode().(Source).describe() diff --git a/javascript/ql/src/change-notes/2023-03-27-jquery-callback-sinks.md b/javascript/ql/src/change-notes/2023-03-27-jquery-callback-sinks.md new file mode 100644 index 00000000000..166a5c139dc --- /dev/null +++ b/javascript/ql/src/change-notes/2023-03-27-jquery-callback-sinks.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- +* Improved the model of jQuery to account for XSS sinks where the HTML string + is provided via a callback. This may lead to more results for the `js/xss` query. diff --git a/javascript/ql/test/library-tests/CallGraphs/FullTest/tests.expected b/javascript/ql/test/library-tests/CallGraphs/FullTest/tests.expected index 15587d7d5b3..665b52e0b1f 100644 --- a/javascript/ql/test/library-tests/CallGraphs/FullTest/tests.expected +++ b/javascript/ql/test/library-tests/CallGraphs/FullTest/tests.expected @@ -85,6 +85,7 @@ test_getAFunctionValue | es2015.js:35:1:35:3 | sum | es2015.js:31:1:33:1 | functio ... +y+z;\\n} | | es2015.js:36:1:36:3 | sum | es2015.js:31:1:33:1 | functio ... +y+z;\\n} | | m2.js:2:6:2:18 | function() {} | m2.js:2:6:2:18 | function() {} | +| m.js:1:1:1:9 | exports.f | m.js:1:13:1:25 | function() {} | | m.js:1:1:1:25 | exports ... on() {} | m.js:1:13:1:25 | function() {} | | m.js:1:13:1:25 | function() {} | m.js:1:13:1:25 | function() {} | | m.js:2:1:2:9 | exports.f | m.js:1:13:1:25 | function() {} | @@ -100,16 +101,19 @@ test_getAFunctionValue | protoclass.js:3:10:3:10 | F | protoclass.js:3:1:5:1 | functio ... it();\\n} | | protoclass.js:4:3:4:11 | this.init | protoclass.js:7:20:11:1 | functio ... m();\\n} | | protoclass.js:7:1:7:1 | F | protoclass.js:3:1:5:1 | functio ... it();\\n} | +| protoclass.js:7:1:7:16 | F.prototype.init | protoclass.js:7:20:11:1 | functio ... m();\\n} | | protoclass.js:7:1:11:1 | F.proto ... m();\\n} | protoclass.js:7:20:11:1 | functio ... m();\\n} | | protoclass.js:7:20:11:1 | functio ... m();\\n} | protoclass.js:7:20:11:1 | functio ... m();\\n} | | protoclass.js:8:3:8:13 | this.method | protoclass.js:13:22:13:34 | function() {} | | protoclass.js:9:11:9:21 | this.method | protoclass.js:13:22:13:34 | function() {} | | protoclass.js:13:1:13:1 | F | protoclass.js:3:1:5:1 | functio ... it();\\n} | +| protoclass.js:13:1:13:18 | F.prototype.method | protoclass.js:13:22:13:34 | function() {} | | protoclass.js:13:1:13:34 | F.proto ... on() {} | protoclass.js:13:22:13:34 | function() {} | | protoclass.js:13:22:13:34 | function() {} | protoclass.js:13:22:13:34 | function() {} | | protoclass.js:15:16:15:16 | F | protoclass.js:3:1:5:1 | functio ... it();\\n} | | reflection.js:1:1:3:1 | functio ... x+y;\\n} | reflection.js:1:1:3:1 | functio ... x+y;\\n} | | reflection.js:5:3:5:5 | add | reflection.js:1:1:3:1 | functio ... x+y;\\n} | +| reflection.js:5:3:5:11 | add.apply | reflection.js:5:15:5:39 | functio ... n 56; } | | reflection.js:5:3:5:39 | add.app ... n 56; } | reflection.js:5:15:5:39 | functio ... n 56; } | | reflection.js:5:15:5:14 | this | reflection.js:1:1:3:1 | functio ... x+y;\\n} | | reflection.js:5:15:5:39 | functio ... n 56; } | reflection.js:5:15:5:39 | functio ... n 56; } | @@ -163,11 +167,13 @@ test_getAFunctionValue | tst.js:42:2:42:26 | functio ... rn x; } | tst.js:42:2:42:26 | functio ... rn x; } | | tst.js:44:1:44:15 | function A() {} | tst.js:44:1:44:15 | function A() {} | | tst.js:45:1:45:1 | A | tst.js:44:1:44:15 | function A() {} | +| tst.js:45:1:45:13 | A.prototype.f | tst.js:45:17:47:1 | functio ... .g();\\n} | | tst.js:45:1:47:1 | A.proto ... .g();\\n} | tst.js:45:17:47:1 | functio ... .g();\\n} | | tst.js:45:17:47:1 | functio ... .g();\\n} | tst.js:45:17:47:1 | functio ... .g();\\n} | | tst.js:46:2:46:7 | this.g | tst.js:48:17:48:29 | function() {} | | tst.js:46:2:46:7 | this.g | tst.js:61:17:61:29 | function() {} | | tst.js:48:1:48:1 | A | tst.js:44:1:44:15 | function A() {} | +| tst.js:48:1:48:13 | A.prototype.g | tst.js:48:17:48:29 | function() {} | | tst.js:48:1:48:29 | A.proto ... on() {} | tst.js:48:17:48:29 | function() {} | | tst.js:48:17:48:29 | function() {} | tst.js:48:17:48:29 | function() {} | | tst.js:50:1:50:15 | function B() {} | tst.js:50:1:50:15 | function B() {} | @@ -186,11 +192,13 @@ test_getAFunctionValue | tst.js:60:1:60:1 | C | tst.js:59:1:59:15 | function C() {} | | tst.js:60:19:60:19 | A | tst.js:44:1:44:15 | function A() {} | | tst.js:61:1:61:1 | C | tst.js:59:1:59:15 | function C() {} | +| tst.js:61:1:61:13 | C.prototype.g | tst.js:61:17:61:29 | function() {} | | tst.js:61:1:61:29 | C.proto ... on() {} | tst.js:61:17:61:29 | function() {} | | tst.js:61:17:61:29 | function() {} | tst.js:61:17:61:29 | function() {} | | tst.js:63:1:67:2 | (functi ... f();\\n}) | tst.js:63:2:67:1 | functio ... .f();\\n} | | tst.js:63:2:67:1 | functio ... .f();\\n} | tst.js:63:2:67:1 | functio ... .f();\\n} | | tst.js:64:17:64:17 | B | tst.js:50:1:50:15 | function B() {} | +| tst.js:65:5:65:7 | b.f | tst.js:65:11:65:23 | function() {} | | tst.js:65:5:65:23 | b.f = function() {} | tst.js:65:11:65:23 | function() {} | | tst.js:65:11:65:23 | function() {} | tst.js:65:11:65:23 | function() {} | | tst.js:66:5:66:7 | b.f | tst.js:52:5:54:2 | functio ... g();\\n\\t} | diff --git a/javascript/ql/test/library-tests/TypeTracking/ClassStyle.expected b/javascript/ql/test/library-tests/TypeTracking/ClassStyle.expected index cf561c366f2..4c7ad61df3b 100644 --- a/javascript/ql/test/library-tests/TypeTracking/ClassStyle.expected +++ b/javascript/ql/test/library-tests/TypeTracking/ClassStyle.expected @@ -12,6 +12,7 @@ test_ApiObject test_Connection | client.js:1:10:1:27 | exportedConnection | | tst.js:7:15:7:18 | conn | +| tst.js:8:5:8:19 | this.connection | | tst.js:11:5:11:19 | this.connection | | tst.js:16:10:16:49 | api.cha ... ction() | | tst.js:19:7:19:21 | getConnection() | @@ -20,7 +21,9 @@ test_Connection | tst.js:48:7:48:21 | getConnection() | | tst.js:54:37:54:51 | getConnection() | | tst.js:57:14:57:48 | config. ... ction') | +| tst.js:62:3:62:36 | MyAppli ... nection | | tst.js:62:40:62:79 | api.cha ... ction() | +| tst.js:63:3:63:34 | MyAppli ... onflict | | tst.js:63:38:63:77 | api.cha ... ction() | | tst.js:67:14:67:47 | MyAppli ... nection | | tst.js:78:35:78:49 | getConnection() | @@ -41,6 +44,7 @@ test_Connection | tst.js:118:12:118:26 | getConnection() | | tst.js:120:21:120:24 | conn | | tst.js:126:22:126:25 | conn | +| tst_conflict.js:6:3:6:34 | MyAppli ... onflict | | tst_conflict.js:6:38:6:77 | api.cha ... ction() | test_DataCallback | client.js:3:28:3:34 | x => {} | diff --git a/javascript/ql/test/library-tests/TypeTracking/PredicateStyle.expected b/javascript/ql/test/library-tests/TypeTracking/PredicateStyle.expected index 17ccc170403..0925e1bc58b 100644 --- a/javascript/ql/test/library-tests/TypeTracking/PredicateStyle.expected +++ b/javascript/ql/test/library-tests/TypeTracking/PredicateStyle.expected @@ -11,6 +11,7 @@ apiObject | tst_conflict.js:6:38:6:58 | api.cha ... hain2() | connection | type tracker with call steps | tst.js:7:15:7:18 | conn | +| type tracker with call steps | tst.js:8:5:8:19 | this.connection | | type tracker with call steps | tst.js:11:5:11:19 | this.connection | | type tracker with call steps | tst.js:80:16:80:19 | conn | | type tracker with call steps | tst.js:84:22:84:22 | x | @@ -30,7 +31,9 @@ connection | type tracker without call steps | tst.js:48:7:48:21 | getConnection() | | type tracker without call steps | tst.js:54:37:54:51 | getConnection() | | type tracker without call steps | tst.js:57:14:57:48 | config. ... ction') | +| type tracker without call steps | tst.js:62:3:62:36 | MyAppli ... nection | | type tracker without call steps | tst.js:62:40:62:79 | api.cha ... ction() | +| type tracker without call steps | tst.js:63:3:63:34 | MyAppli ... onflict | | type tracker without call steps | tst.js:63:38:63:77 | api.cha ... ction() | | type tracker without call steps | tst.js:67:14:67:47 | MyAppli ... nection | | type tracker without call steps | tst.js:78:35:78:49 | getConnection() | @@ -43,6 +46,7 @@ connection | type tracker without call steps | tst.js:118:12:118:26 | getConnection() | | type tracker without call steps | tst.js:120:21:120:24 | conn | | type tracker without call steps | tst.js:126:22:126:25 | conn | +| type tracker without call steps | tst_conflict.js:6:3:6:34 | MyAppli ... onflict | | type tracker without call steps | tst_conflict.js:6:38:6:77 | api.cha ... ction() | | type tracker without call steps with property conflict | tst.js:63:3:63:25 | MyAppli ... mespace | | type tracker without call steps with property conflict | tst_conflict.js:6:3:6:25 | MyAppli ... mespace | diff --git a/javascript/ql/test/library-tests/frameworks/Express/tests.expected b/javascript/ql/test/library-tests/frameworks/Express/tests.expected index 93f9b4c578e..6b1291c52ac 100644 --- a/javascript/ql/test/library-tests/frameworks/Express/tests.expected +++ b/javascript/ql/test/library-tests/frameworks/Express/tests.expected @@ -3227,10 +3227,13 @@ getRouteHandlerContainerStep | src/route-collection.js:1:18:4:1 | {\\n a: ... (req)\\n} | src/route-collection.js:3:6:3:35 | (req, r ... og(req) | src/advanced-routehandler-registration.js:116:14:116:30 | importedRoutes[p] | | src/route-collection.js:1:18:4:1 | {\\n a: ... (req)\\n} | src/route-collection.js:3:6:3:35 | (req, r ... og(req) | src/advanced-routehandler-registration.js:119:14:119:29 | importedRoutes.b | dbUse +| src/middleware-flow.js:6:5:6:10 | req.db | | src/middleware-flow.js:6:5:6:21 | req.db = new DB() | | src/middleware-flow.js:6:14:6:21 | new DB() | +| src/middleware-flow.js:7:5:7:15 | req.deep.db | | src/middleware-flow.js:7:5:7:26 | req.dee ... ew DB() | | src/middleware-flow.js:7:19:7:26 | new DB() | +| src/middleware-flow.js:8:5:8:22 | req.deep.access.db | | src/middleware-flow.js:8:5:8:33 | req.dee ... ew DB() | | src/middleware-flow.js:8:26:8:33 | new DB() | | src/middleware-flow.js:18:9:18:14 | req.db | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected index 95fbc8f15c3..d40a652b962 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected @@ -431,6 +431,11 @@ nodes | jquery.js:34:5:34:25 | '' + ... '' | | jquery.js:34:5:34:25 | '' + ... '' | | jquery.js:34:13:34:16 | hash | +| jquery.js:36:25:36:31 | tainted | +| jquery.js:36:25:36:31 | tainted | +| jquery.js:37:25:37:37 | () => tainted | +| jquery.js:37:25:37:37 | () => tainted | +| jquery.js:37:31:37:37 | tainted | | json-stringify.jsx:5:9:5:36 | locale | | json-stringify.jsx:5:9:5:36 | locale | | json-stringify.jsx:5:18:5:36 | req.param("locale") | @@ -1512,6 +1517,9 @@ edges | express.js:7:15:7:33 | req.param("wobble") | express.js:7:15:7:33 | req.param("wobble") | | jquery.js:2:7:2:40 | tainted | jquery.js:7:20:7:26 | tainted | | jquery.js:2:7:2:40 | tainted | jquery.js:8:28:8:34 | tainted | +| jquery.js:2:7:2:40 | tainted | jquery.js:36:25:36:31 | tainted | +| jquery.js:2:7:2:40 | tainted | jquery.js:36:25:36:31 | tainted | +| jquery.js:2:7:2:40 | tainted | jquery.js:37:31:37:37 | tainted | | jquery.js:2:17:2:40 | documen ... .search | jquery.js:2:7:2:40 | tainted | | jquery.js:2:17:2:40 | documen ... .search | jquery.js:2:7:2:40 | tainted | | jquery.js:7:20:7:26 | tainted | jquery.js:7:5:7:34 | "
    " | @@ -1565,6 +1573,8 @@ edges | jquery.js:28:5:28:26 | window. ... .search | jquery.js:28:5:28:43 | window. ... ?', '') | | jquery.js:34:13:34:16 | hash | jquery.js:34:5:34:25 | '' + ... '' | | jquery.js:34:13:34:16 | hash | jquery.js:34:5:34:25 | '' + ... '' | +| jquery.js:37:31:37:37 | tainted | jquery.js:37:25:37:37 | () => tainted | +| jquery.js:37:31:37:37 | tainted | jquery.js:37:25:37:37 | () => tainted | | json-stringify.jsx:5:9:5:36 | locale | json-stringify.jsx:11:51:11:56 | locale | | json-stringify.jsx:5:9:5:36 | locale | json-stringify.jsx:19:56:19:61 | locale | | json-stringify.jsx:5:9:5:36 | locale | json-stringify.jsx:31:55:31:60 | locale | @@ -2355,6 +2365,8 @@ edges | jquery.js:27:5:27:25 | hash.re ... #', '') | jquery.js:18:14:18:33 | window.location.hash | jquery.js:27:5:27:25 | hash.re ... #', '') | Cross-site scripting vulnerability due to $@. | jquery.js:18:14:18:33 | window.location.hash | user-provided value | | jquery.js:28:5:28:43 | window. ... ?', '') | jquery.js:28:5:28:26 | window. ... .search | jquery.js:28:5:28:43 | window. ... ?', '') | Cross-site scripting vulnerability due to $@. | jquery.js:28:5:28:26 | window. ... .search | user-provided value | | jquery.js:34:5:34:25 | '' + ... '' | jquery.js:18:14:18:33 | window.location.hash | jquery.js:34:5:34:25 | '' + ... '' | Cross-site scripting vulnerability due to $@. | jquery.js:18:14:18:33 | window.location.hash | user-provided value | +| jquery.js:36:25:36:31 | tainted | jquery.js:2:17:2:40 | documen ... .search | jquery.js:36:25:36:31 | tainted | Cross-site scripting vulnerability due to $@. | jquery.js:2:17:2:40 | documen ... .search | user-provided value | +| jquery.js:37:25:37:37 | () => tainted | jquery.js:2:17:2:40 | documen ... .search | jquery.js:37:25:37:37 | () => tainted | Cross-site scripting vulnerability due to $@. | jquery.js:2:17:2:40 | documen ... .search | user-provided value | | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | Cross-site scripting vulnerability due to $@. | json-stringify.jsx:5:18:5:36 | req.param("locale") | user-provided value | | json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | Cross-site scripting vulnerability due to $@. | json-stringify.jsx:5:18:5:36 | req.param("locale") | user-provided value | | jwt-server.js:11:19:11:29 | decoded.foo | jwt-server.js:7:17:7:35 | req.param("wobble") | jwt-server.js:11:19:11:29 | decoded.foo | Cross-site scripting vulnerability due to $@. | jwt-server.js:7:17:7:35 | req.param("wobble") | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected index 03c3dd0d9ca..5e5010d126e 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected @@ -431,6 +431,11 @@ nodes | jquery.js:34:5:34:25 | '' + ... '' | | jquery.js:34:5:34:25 | '' + ... '' | | jquery.js:34:13:34:16 | hash | +| jquery.js:36:25:36:31 | tainted | +| jquery.js:36:25:36:31 | tainted | +| jquery.js:37:25:37:37 | () => tainted | +| jquery.js:37:25:37:37 | () => tainted | +| jquery.js:37:31:37:37 | tainted | | json-stringify.jsx:5:9:5:36 | locale | | json-stringify.jsx:5:9:5:36 | locale | | json-stringify.jsx:5:18:5:36 | req.param("locale") | @@ -1562,6 +1567,9 @@ edges | express.js:7:15:7:33 | req.param("wobble") | express.js:7:15:7:33 | req.param("wobble") | | jquery.js:2:7:2:40 | tainted | jquery.js:7:20:7:26 | tainted | | jquery.js:2:7:2:40 | tainted | jquery.js:8:28:8:34 | tainted | +| jquery.js:2:7:2:40 | tainted | jquery.js:36:25:36:31 | tainted | +| jquery.js:2:7:2:40 | tainted | jquery.js:36:25:36:31 | tainted | +| jquery.js:2:7:2:40 | tainted | jquery.js:37:31:37:37 | tainted | | jquery.js:2:17:2:40 | documen ... .search | jquery.js:2:7:2:40 | tainted | | jquery.js:2:17:2:40 | documen ... .search | jquery.js:2:7:2:40 | tainted | | jquery.js:7:20:7:26 | tainted | jquery.js:7:5:7:34 | "
    " | @@ -1615,6 +1623,8 @@ edges | jquery.js:28:5:28:26 | window. ... .search | jquery.js:28:5:28:43 | window. ... ?', '') | | jquery.js:34:13:34:16 | hash | jquery.js:34:5:34:25 | '' + ... '' | | jquery.js:34:13:34:16 | hash | jquery.js:34:5:34:25 | '' + ... '' | +| jquery.js:37:31:37:37 | tainted | jquery.js:37:25:37:37 | () => tainted | +| jquery.js:37:31:37:37 | tainted | jquery.js:37:25:37:37 | () => tainted | | json-stringify.jsx:5:9:5:36 | locale | json-stringify.jsx:11:51:11:56 | locale | | json-stringify.jsx:5:9:5:36 | locale | json-stringify.jsx:19:56:19:61 | locale | | json-stringify.jsx:5:9:5:36 | locale | json-stringify.jsx:31:55:31:60 | locale | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/jquery.js b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/jquery.js index 3bff577fbdf..3369df5dd87 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/jquery.js +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/jquery.js @@ -32,4 +32,7 @@ function test() { $(hash + 'blah'); // OK $('blah' + hash); // OK - does not start with '<' $('' + hash + ''); // NOT OK + + $('#foo').replaceWith(tainted); // NOT OK + $('#foo').replaceWith(() => tainted); // NOT OK } diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected index 8a5fb51a44e..83147705499 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/XssThroughDom.expected @@ -159,6 +159,11 @@ nodes | xss-through-dom.js:141:25:141:27 | src | | xss-through-dom.js:150:24:150:26 | src | | xss-through-dom.js:150:24:150:26 | src | +| xss-through-dom.js:154:25:154:27 | msg | +| xss-through-dom.js:155:27:155:29 | msg | +| xss-through-dom.js:155:27:155:29 | msg | +| xss-through-dom.js:159:34:159:52 | $("textarea").val() | +| xss-through-dom.js:159:34:159:52 | $("textarea").val() | edges | forms.js:8:23:8:28 | values | forms.js:9:31:9:36 | values | | forms.js:8:23:8:28 | values | forms.js:9:31:9:36 | values | @@ -263,6 +268,10 @@ edges | xss-through-dom.js:139:11:139:52 | src | xss-through-dom.js:150:24:150:26 | src | | xss-through-dom.js:139:17:139:52 | documen ... k").src | xss-through-dom.js:139:11:139:52 | src | | xss-through-dom.js:139:17:139:52 | documen ... k").src | xss-through-dom.js:139:11:139:52 | src | +| xss-through-dom.js:154:25:154:27 | msg | xss-through-dom.js:155:27:155:29 | msg | +| xss-through-dom.js:154:25:154:27 | msg | xss-through-dom.js:155:27:155:29 | msg | +| xss-through-dom.js:159:34:159:52 | $("textarea").val() | xss-through-dom.js:154:25:154:27 | msg | +| xss-through-dom.js:159:34:159:52 | $("textarea").val() | xss-through-dom.js:154:25:154:27 | msg | #select | forms.js:9:31:9:40 | values.foo | forms.js:8:23:8:28 | values | forms.js:9:31:9:40 | values.foo | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:8:23:8:28 | values | DOM text | | forms.js:12:31:12:40 | values.bar | forms.js:11:24:11:29 | values | forms.js:12:31:12:40 | values.bar | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:11:24:11:29 | values | DOM text | @@ -307,3 +316,4 @@ edges | xss-through-dom.js:140:19:140:21 | src | xss-through-dom.js:139:17:139:52 | documen ... k").src | xss-through-dom.js:140:19:140:21 | src | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:139:17:139:52 | documen ... k").src | DOM text | | xss-through-dom.js:141:25:141:27 | src | xss-through-dom.js:139:17:139:52 | documen ... k").src | xss-through-dom.js:141:25:141:27 | src | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:139:17:139:52 | documen ... k").src | DOM text | | xss-through-dom.js:150:24:150:26 | src | xss-through-dom.js:139:17:139:52 | documen ... k").src | xss-through-dom.js:150:24:150:26 | src | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:139:17:139:52 | documen ... k").src | DOM text | +| xss-through-dom.js:155:27:155:29 | msg | xss-through-dom.js:159:34:159:52 | $("textarea").val() | xss-through-dom.js:155:27:155:29 | msg | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:159:34:159:52 | $("textarea").val() | DOM text | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js index 4c488c0dfa3..354194a597d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js @@ -148,4 +148,15 @@ const cashDom = require("cash-dom"); cashDom("#id").html(DOMPurify ? DOMPurify.sanitize(src) : src); // OK $("", { html: src }).appendTo("#id"); // NOT OK + + function foo() { + window.VeryUniqueXssTestName = { + send: function (msg) { + $("#id").html(msg); // NOT OK + }, + }; + + VeryUniqueXssTestName.send($("textarea").val()); + } + foo() })(); \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/UnsafeCodeConstruction.expected b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/UnsafeCodeConstruction.expected index 14733b4274d..725c600ecaa 100644 --- a/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/UnsafeCodeConstruction.expected +++ b/javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/UnsafeCodeConstruction.expected @@ -42,8 +42,11 @@ nodes | lib/index.js:112:17:112:21 | taint | | lib/index.js:112:17:112:21 | taint | | lib/index.js:113:20:113:24 | taint | +| lib/index.js:115:38:115:42 | taint | | lib/index.js:121:34:121:38 | taint | | lib/index.js:129:32:129:36 | taint | +| lib/index.js:135:23:135:49 | this.op ... dOption | +| lib/index.js:135:23:135:49 | this.op ... dOption | | lib/index.js:136:23:136:49 | this.op ... dOption | | lib/index.js:136:23:136:49 | this.op ... dOption | | lib/index.js:137:23:137:49 | this.op ... dOption | @@ -94,12 +97,16 @@ edges | lib/index.js:98:30:98:34 | taint | lib/index.js:105:21:105:47 | this.op ... dOption | | lib/index.js:112:17:112:21 | taint | lib/index.js:113:20:113:24 | taint | | lib/index.js:112:17:112:21 | taint | lib/index.js:113:20:113:24 | taint | +| lib/index.js:112:17:112:21 | taint | lib/index.js:115:38:115:42 | taint | +| lib/index.js:112:17:112:21 | taint | lib/index.js:115:38:115:42 | taint | | lib/index.js:112:17:112:21 | taint | lib/index.js:121:34:121:38 | taint | | lib/index.js:112:17:112:21 | taint | lib/index.js:121:34:121:38 | taint | | lib/index.js:112:17:112:21 | taint | lib/index.js:129:32:129:36 | taint | | lib/index.js:112:17:112:21 | taint | lib/index.js:129:32:129:36 | taint | | lib/index.js:113:20:113:24 | taint | lib/index.js:138:23:138:32 | this.taint | | lib/index.js:113:20:113:24 | taint | lib/index.js:138:23:138:32 | this.taint | +| lib/index.js:115:38:115:42 | taint | lib/index.js:135:23:135:49 | this.op ... dOption | +| lib/index.js:115:38:115:42 | taint | lib/index.js:135:23:135:49 | this.op ... dOption | | lib/index.js:121:34:121:38 | taint | lib/index.js:136:23:136:49 | this.op ... dOption | | lib/index.js:121:34:121:38 | taint | lib/index.js:136:23:136:49 | this.op ... dOption | | lib/index.js:129:32:129:36 | taint | lib/index.js:137:23:137:49 | this.op ... dOption | @@ -114,6 +121,7 @@ edges | lib/index.js:104:21:104:47 | this.op ... dOption | lib/index.js:86:15:86:19 | taint | lib/index.js:104:21:104:47 | this.op ... dOption | This string concatenation which depends on $@ is later $@. | lib/index.js:86:15:86:19 | taint | library input | lib/index.js:104:10:104:67 | " var ... ing();" | interpreted as code | | lib/index.js:105:21:105:47 | this.op ... dOption | lib/index.js:86:15:86:19 | taint | lib/index.js:105:21:105:47 | this.op ... dOption | This string concatenation which depends on $@ is later $@. | lib/index.js:86:15:86:19 | taint | library input | lib/index.js:105:10:105:67 | " var ... ing();" | interpreted as code | | lib/index.js:106:21:106:30 | this.taint | lib/index.js:86:15:86:19 | taint | lib/index.js:106:21:106:30 | this.taint | This string concatenation which depends on $@ is later $@. | lib/index.js:86:15:86:19 | taint | library input | lib/index.js:106:10:106:50 | " var ... ing();" | interpreted as code | +| lib/index.js:135:23:135:49 | this.op ... dOption | lib/index.js:112:17:112:21 | taint | lib/index.js:135:23:135:49 | this.op ... dOption | This string concatenation which depends on $@ is later $@. | lib/index.js:112:17:112:21 | taint | library input | lib/index.js:135:12:135:69 | " var ... ing();" | interpreted as code | | lib/index.js:136:23:136:49 | this.op ... dOption | lib/index.js:112:17:112:21 | taint | lib/index.js:136:23:136:49 | this.op ... dOption | This string concatenation which depends on $@ is later $@. | lib/index.js:112:17:112:21 | taint | library input | lib/index.js:136:12:136:69 | " var ... ing();" | interpreted as code | | lib/index.js:137:23:137:49 | this.op ... dOption | lib/index.js:112:17:112:21 | taint | lib/index.js:137:23:137:49 | this.op ... dOption | This string concatenation which depends on $@ is later $@. | lib/index.js:112:17:112:21 | taint | library input | lib/index.js:137:12:137:69 | " var ... ing();" | interpreted as code | | lib/index.js:138:23:138:32 | this.taint | lib/index.js:112:17:112:21 | taint | lib/index.js:138:23:138:32 | this.taint | This string concatenation which depends on $@ is later $@. | lib/index.js:112:17:112:21 | taint | library input | lib/index.js:138:12:138:52 | " var ... ing();" | interpreted as code | diff --git a/javascript/ql/test/query-tests/Security/CWE-327/BrokenCryptoAlgorithm.expected b/javascript/ql/test/query-tests/Security/CWE-327/BrokenCryptoAlgorithm.expected index ce03e114f4e..1938b020355 100644 --- a/javascript/ql/test/query-tests/Security/CWE-327/BrokenCryptoAlgorithm.expected +++ b/javascript/ql/test/query-tests/Security/CWE-327/BrokenCryptoAlgorithm.expected @@ -26,8 +26,8 @@ edges | tst.js:19:17:19:24 | password | tst.js:19:17:19:24 | password | | tst.js:22:21:22:30 | secretText | tst.js:22:21:22:30 | secretText | #select -| tst.js:11:17:11:26 | secretText | tst.js:3:18:3:24 | trusted | tst.js:11:17:11:26 | secretText | A broken or weak cryptographic algorithm depends on $@. | tst.js:3:18:3:24 | trusted | sensitive data froman access to trusted | -| tst.js:11:17:11:26 | secretText | tst.js:11:17:11:26 | secretText | tst.js:11:17:11:26 | secretText | A broken or weak cryptographic algorithm depends on $@. | tst.js:11:17:11:26 | secretText | sensitive data froman access to secretText | -| tst.js:17:17:17:25 | o.trusted | tst.js:17:17:17:25 | o.trusted | tst.js:17:17:17:25 | o.trusted | A broken or weak cryptographic algorithm depends on $@. | tst.js:17:17:17:25 | o.trusted | sensitive data froman access to trusted | -| tst.js:22:21:22:30 | secretText | tst.js:3:18:3:24 | trusted | tst.js:22:21:22:30 | secretText | A broken or weak cryptographic algorithm depends on $@. | tst.js:3:18:3:24 | trusted | sensitive data froman access to trusted | -| tst.js:22:21:22:30 | secretText | tst.js:22:21:22:30 | secretText | tst.js:22:21:22:30 | secretText | A broken or weak cryptographic algorithm depends on $@. | tst.js:22:21:22:30 | secretText | sensitive data froman access to secretText | +| tst.js:11:17:11:26 | secretText | tst.js:3:18:3:24 | trusted | tst.js:11:17:11:26 | secretText | A broken or weak cryptographic algorithm depends on $@. | tst.js:3:18:3:24 | trusted | sensitive data from an access to trusted | +| tst.js:11:17:11:26 | secretText | tst.js:11:17:11:26 | secretText | tst.js:11:17:11:26 | secretText | A broken or weak cryptographic algorithm depends on $@. | tst.js:11:17:11:26 | secretText | sensitive data from an access to secretText | +| tst.js:17:17:17:25 | o.trusted | tst.js:17:17:17:25 | o.trusted | tst.js:17:17:17:25 | o.trusted | A broken or weak cryptographic algorithm depends on $@. | tst.js:17:17:17:25 | o.trusted | sensitive data from an access to trusted | +| tst.js:22:21:22:30 | secretText | tst.js:3:18:3:24 | trusted | tst.js:22:21:22:30 | secretText | A broken or weak cryptographic algorithm depends on $@. | tst.js:3:18:3:24 | trusted | sensitive data from an access to trusted | +| tst.js:22:21:22:30 | secretText | tst.js:22:21:22:30 | secretText | tst.js:22:21:22:30 | secretText | A broken or weak cryptographic algorithm depends on $@. | tst.js:22:21:22:30 | secretText | sensitive data from an access to secretText | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialBackTracking.expected b/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialBackTracking.expected index cfc43062161..db29a305639 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialBackTracking.expected +++ b/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialBackTracking.expected @@ -1,5 +1,5 @@ -| highlight.js:2:26:2:979 | ((traffic-flow\|traffic-generator\|firewall\|scheduler\|aaa\|accounting\|address-list\|address\|align\|area\|bandwidth-server\|bfd\|bgp\|bridge\|client\|clock\|community\|config\|connection\|console\|customer\|default\|dhcp-client\|dhcp-server\|discovery\|dns\|e-mail\|ethernet\|filter\|firewall\|firmware\|gps\|graphing\|group\|hardware\|health\|hotspot\|identity\|igmp-proxy\|incoming\|instance\|interface\|ip\|ipsec\|ipv6\|irq\|l2tp-server\|lcd\|ldp\|logging\|mac-server\|mac-winbox\|mangle\|manual\|mirror\|mme\|mpls\|nat\|nd\|neighbor\|network\|note\|ntp\|ospf\|ospf-v3\|ovpn-server\|page\|peer\|pim\|ping\|policy\|pool\|port\|ppp\|pppoe-client\|pptp-server\|prefix\|profile\|proposal\|proxy\|queue\|radius\|resource\|rip\|ripng\|route\|routing\|screen\|script\|security-profiles\|server\|service\|service-port\|settings\|shares\|smb\|sms\|sniffer\|snmp\|snooper\|socks\|sstp-server\|system\|tool\|tracking\|type\|upgrade\|upnp\|user-manager\|users\|user\|vlan\|secret\|vrrp\|watchdog\|web-access\|wireless\|pptp\|pppoe\|lan\|wan\|layer7-protocol\|lease\|simple\|raw);?\\s)+ | Strings starting with '/' and with many repetitions of 'aaa\\t' can start matching anywhere after the start of the preceeding (\\.\\.\\/\|\\/\|\\s)((traffic-flow\|traffic-generator\|firewall\|scheduler\|aaa\|accounting\|address-list\|address\|align\|area\|bandwidth-server\|bfd\|bgp\|bridge\|client\|clock\|community\|config\|connection\|console\|customer\|default\|dhcp-client\|dhcp-server\|discovery\|dns\|e-mail\|ethernet\|filter\|firewall\|firmware\|gps\|graphing\|group\|hardware\|health\|hotspot\|identity\|igmp-proxy\|incoming\|instance\|interface\|ip\|ipsec\|ipv6\|irq\|l2tp-server\|lcd\|ldp\|logging\|mac-server\|mac-winbox\|mangle\|manual\|mirror\|mme\|mpls\|nat\|nd\|neighbor\|network\|note\|ntp\|ospf\|ospf-v3\|ovpn-server\|page\|peer\|pim\|ping\|policy\|pool\|port\|ppp\|pppoe-client\|pptp-server\|prefix\|profile\|proposal\|proxy\|queue\|radius\|resource\|rip\|ripng\|route\|routing\|screen\|script\|security-profiles\|server\|service\|service-port\|settings\|shares\|smb\|sms\|sniffer\|snmp\|snooper\|socks\|sstp-server\|system\|tool\|tracking\|type\|upgrade\|upnp\|user-manager\|users\|user\|vlan\|secret\|vrrp\|watchdog\|web-access\|wireless\|pptp\|pppoe\|lan\|wan\|layer7-protocol\|lease\|simple\|raw);?\\s)+X | -| highlight.js:3:27:3:971 | ((traffic-flow\|traffic-generator\|firewall\|scheduler\|aaa\|accounting\|address-list\|address\|align\|area\|bandwidth-server\|bfd\|bgp\|bridge\|client\|clock\|community\|config\|connection\|console\|customer\|default\|dhcp-client\|dhcp-server\|discovery\|dns\|e-mail\|ethernet\|filter\|firmware\|gps\|graphing\|group\|hardware\|health\|hotspot\|identity\|igmp-proxy\|incoming\|instance\|interface\|ip\|ipsec\|ipv6\|irq\|l2tp-server\|lcd\|ldp\|logging\|mac-server\|mac-winbox\|mangle\|manual\|mirror\|mme\|mpls\|nat\|nd\|neighbor\|network\|note\|ntp\|ospf\|ospf-v3\|ovpn-server\|page\|peer\|pim\|ping\|policy\|pool\|port\|ppp\|pppoe-client\|pptp-server\|prefix\|profile\|proposal\|proxy\|queue\|radius\|resource\|rip\|ripng\|route\|routing\|screen\|script\|security-profiles\|server\|service\|service-port\|settings\|shares\|smb\|sms\|sniffer\|snmp\|snooper\|socks\|sstp-server\|system\|tool\|tracking\|type\|upgrade\|upnp\|user-manager\|users\|user\|vlan\|secret\|vrrp\|watchdog\|web-access\|wireless\|pptp\|pppoe\|lan\|wan\|layer7-protocol\|lease\|simple\|raw);?\\s)+ | Strings starting with '/' and with many repetitions of 'aaa\\t' can start matching anywhere after the start of the preceeding (\\.\\.\\/\|\\/\|\\s)((traffic-flow\|traffic-generator\|firewall\|scheduler\|aaa\|accounting\|address-list\|address\|align\|area\|bandwidth-server\|bfd\|bgp\|bridge\|client\|clock\|community\|config\|connection\|console\|customer\|default\|dhcp-client\|dhcp-server\|discovery\|dns\|e-mail\|ethernet\|filter\|firmware\|gps\|graphing\|group\|hardware\|health\|hotspot\|identity\|igmp-proxy\|incoming\|instance\|interface\|ip\|ipsec\|ipv6\|irq\|l2tp-server\|lcd\|ldp\|logging\|mac-server\|mac-winbox\|mangle\|manual\|mirror\|mme\|mpls\|nat\|nd\|neighbor\|network\|note\|ntp\|ospf\|ospf-v3\|ovpn-server\|page\|peer\|pim\|ping\|policy\|pool\|port\|ppp\|pppoe-client\|pptp-server\|prefix\|profile\|proposal\|proxy\|queue\|radius\|resource\|rip\|ripng\|route\|routing\|screen\|script\|security-profiles\|server\|service\|service-port\|settings\|shares\|smb\|sms\|sniffer\|snmp\|snooper\|socks\|sstp-server\|system\|tool\|tracking\|type\|upgrade\|upnp\|user-manager\|users\|user\|vlan\|secret\|vrrp\|watchdog\|web-access\|wireless\|pptp\|pppoe\|lan\|wan\|layer7-protocol\|lease\|simple\|raw);?\\s)+X | +| highlight.js:2:26:2:979 | ((traffic-flow\|traffic-generator\|firewall\|scheduler\|aaa\|accounting\|address-list\|address\|align\|area\|bandwidth-server\|bfd\|bgp\|bridge\|client\|clock\|community\|config\|connection\|console\|customer\|default\|dhcp-client\|dhcp-server\|discovery\|dns\|e-mail\|ethernet\|filter\|firewall\|firmware\|gps\|graphing\|group\|hardware\|health\|hotspot\|identity\|igmp-proxy\|incoming\|instance\|interface\|ip\|ipsec\|ipv6\|irq\|l2tp-server\|lcd\|ldp\|logging\|mac-server\|mac-winbox\|mangle\|manual\|mirror\|mme\|mpls\|nat\|nd\|neighbor\|network\|note\|ntp\|ospf\|ospf-v3\|ovpn-server\|page\|peer\|pim\|ping\|policy\|pool\|port\|ppp\|pppoe-client\|pptp-server\|prefix\|profile\|proposal\|proxy\|queue\|radius\|resource\|rip\|ripng\|route\|routing\|screen\|script\|security-profiles\|server\|service\|service-port\|settings\|shares\|smb\|sms\|sniffer\|snmp\|snooper\|socks\|sstp-server\|system\|tool\|tracking\|type\|upgrade\|upnp\|user-manager\|users\|user\|vlan\|secret\|vrrp\|watchdog\|web-access\|wireless\|pptp\|pppoe\|lan\|wan\|layer7-protocol\|lease\|simple\|raw);?\\s)+ | Strings starting with '/' and with many repetitions of 'ip\\t' can start matching anywhere after the start of the preceeding (\\.\\.\\/\|\\/\|\\s)((traffic-flow\|traffic-generator\|firewall\|scheduler\|aaa\|accounting\|address-list\|address\|align\|area\|bandwidth-server\|bfd\|bgp\|bridge\|client\|clock\|community\|config\|connection\|console\|customer\|default\|dhcp-client\|dhcp-server\|discovery\|dns\|e-mail\|ethernet\|filter\|firewall\|firmware\|gps\|graphing\|group\|hardware\|health\|hotspot\|identity\|igmp-proxy\|incoming\|instance\|interface\|ip\|ipsec\|ipv6\|irq\|l2tp-server\|lcd\|ldp\|logging\|mac-server\|mac-winbox\|mangle\|manual\|mirror\|mme\|mpls\|nat\|nd\|neighbor\|network\|note\|ntp\|ospf\|ospf-v3\|ovpn-server\|page\|peer\|pim\|ping\|policy\|pool\|port\|ppp\|pppoe-client\|pptp-server\|prefix\|profile\|proposal\|proxy\|queue\|radius\|resource\|rip\|ripng\|route\|routing\|screen\|script\|security-profiles\|server\|service\|service-port\|settings\|shares\|smb\|sms\|sniffer\|snmp\|snooper\|socks\|sstp-server\|system\|tool\|tracking\|type\|upgrade\|upnp\|user-manager\|users\|user\|vlan\|secret\|vrrp\|watchdog\|web-access\|wireless\|pptp\|pppoe\|lan\|wan\|layer7-protocol\|lease\|simple\|raw);?\\s)+X | +| highlight.js:3:27:3:971 | ((traffic-flow\|traffic-generator\|firewall\|scheduler\|aaa\|accounting\|address-list\|address\|align\|area\|bandwidth-server\|bfd\|bgp\|bridge\|client\|clock\|community\|config\|connection\|console\|customer\|default\|dhcp-client\|dhcp-server\|discovery\|dns\|e-mail\|ethernet\|filter\|firmware\|gps\|graphing\|group\|hardware\|health\|hotspot\|identity\|igmp-proxy\|incoming\|instance\|interface\|ip\|ipsec\|ipv6\|irq\|l2tp-server\|lcd\|ldp\|logging\|mac-server\|mac-winbox\|mangle\|manual\|mirror\|mme\|mpls\|nat\|nd\|neighbor\|network\|note\|ntp\|ospf\|ospf-v3\|ovpn-server\|page\|peer\|pim\|ping\|policy\|pool\|port\|ppp\|pppoe-client\|pptp-server\|prefix\|profile\|proposal\|proxy\|queue\|radius\|resource\|rip\|ripng\|route\|routing\|screen\|script\|security-profiles\|server\|service\|service-port\|settings\|shares\|smb\|sms\|sniffer\|snmp\|snooper\|socks\|sstp-server\|system\|tool\|tracking\|type\|upgrade\|upnp\|user-manager\|users\|user\|vlan\|secret\|vrrp\|watchdog\|web-access\|wireless\|pptp\|pppoe\|lan\|wan\|layer7-protocol\|lease\|simple\|raw);?\\s)+ | Strings starting with '/' and with many repetitions of 'ip\\t' can start matching anywhere after the start of the preceeding (\\.\\.\\/\|\\/\|\\s)((traffic-flow\|traffic-generator\|firewall\|scheduler\|aaa\|accounting\|address-list\|address\|align\|area\|bandwidth-server\|bfd\|bgp\|bridge\|client\|clock\|community\|config\|connection\|console\|customer\|default\|dhcp-client\|dhcp-server\|discovery\|dns\|e-mail\|ethernet\|filter\|firmware\|gps\|graphing\|group\|hardware\|health\|hotspot\|identity\|igmp-proxy\|incoming\|instance\|interface\|ip\|ipsec\|ipv6\|irq\|l2tp-server\|lcd\|ldp\|logging\|mac-server\|mac-winbox\|mangle\|manual\|mirror\|mme\|mpls\|nat\|nd\|neighbor\|network\|note\|ntp\|ospf\|ospf-v3\|ovpn-server\|page\|peer\|pim\|ping\|policy\|pool\|port\|ppp\|pppoe-client\|pptp-server\|prefix\|profile\|proposal\|proxy\|queue\|radius\|resource\|rip\|ripng\|route\|routing\|screen\|script\|security-profiles\|server\|service\|service-port\|settings\|shares\|smb\|sms\|sniffer\|snmp\|snooper\|socks\|sstp-server\|system\|tool\|tracking\|type\|upgrade\|upnp\|user-manager\|users\|user\|vlan\|secret\|vrrp\|watchdog\|web-access\|wireless\|pptp\|pppoe\|lan\|wan\|layer7-protocol\|lease\|simple\|raw);?\\s)+X | | highlight.js:6:12:6:695 | (Add\|Clear\|Close\|Copy\|Enter\|Exit\|Find\|Format\|Get\|Hide\|Join\|Lock\|Move\|New\|Open\|Optimize\|Pop\|Push\|Redo\|Remove\|Rename\|Reset\|Resize\|Search\|Select\|Set\|Show\|Skip\|Split\|Step\|Switch\|Undo\|Unlock\|Watch\|Backup\|Checkpoint\|Compare\|Compress\|Convert\|ConvertFrom\|ConvertTo\|Dismount\|Edit\|Expand\|Export\|Group\|Import\|Initialize\|Limit\|Merge\|New\|Out\|Publish\|Restore\|Save\|Sync\|Unpublish\|Update\|Approve\|Assert\|Complete\|Confirm\|Deny\|Disable\|Enable\|Install\|Invoke\|Register\|Request\|Restart\|Resume\|Start\|Stop\|Submit\|Suspend\|Uninstall\|Unregister\|Wait\|Debug\|Measure\|Ping\|Repair\|Resolve\|Test\|Trace\|Connect\|Disconnect\|Read\|Receive\|Send\|Write\|Block\|Grant\|Protect\|Revoke\|Unblock\|Unprotect\|Use\|ForEach\|Sort\|Tee\|Where)+ | Strings with many repetitions of 'Add' can start matching anywhere after the start of the preceeding (Add\|Clear\|Close\|Copy\|Enter\|Exit\|Find\|Format\|Get\|Hide\|Join\|Lock\|Move\|New\|Open\|Optimize\|Pop\|Push\|Redo\|Remove\|Rename\|Reset\|Resize\|Search\|Select\|Set\|Show\|Skip\|Split\|Step\|Switch\|Undo\|Unlock\|Watch\|Backup\|Checkpoint\|Compare\|Compress\|Convert\|ConvertFrom\|ConvertTo\|Dismount\|Edit\|Expand\|Export\|Group\|Import\|Initialize\|Limit\|Merge\|New\|Out\|Publish\|Restore\|Save\|Sync\|Unpublish\|Update\|Approve\|Assert\|Complete\|Confirm\|Deny\|Disable\|Enable\|Install\|Invoke\|Register\|Request\|Restart\|Resume\|Start\|Stop\|Submit\|Suspend\|Uninstall\|Unregister\|Wait\|Debug\|Measure\|Ping\|Repair\|Resolve\|Test\|Trace\|Connect\|Disconnect\|Read\|Receive\|Send\|Write\|Block\|Grant\|Protect\|Revoke\|Unblock\|Unprotect\|Use\|ForEach\|Sort\|Tee\|Where)+(-)[\\w\\d]+ | | highlight.js:7:13:7:692 | (Add\|Clear\|Close\|Copy\|Enter\|Exit\|Find\|Format\|Get\|Hide\|Join\|Lock\|Move\|New\|Open\|Optimize\|Pop\|Push\|Redo\|Remove\|Rename\|Reset\|Resize\|Search\|Select\|Set\|Show\|Skip\|Split\|Step\|Switch\|Undo\|Unlock\|Watch\|Backup\|Checkpoint\|Compare\|Compress\|Convert\|ConvertFrom\|ConvertTo\|Dismount\|Edit\|Expand\|Export\|Group\|Import\|Initialize\|Limit\|Merge\|Out\|Publish\|Restore\|Save\|Sync\|Unpublish\|Update\|Approve\|Assert\|Complete\|Confirm\|Deny\|Disable\|Enable\|Install\|Invoke\|Register\|Request\|Restart\|Resume\|Start\|Stop\|Submit\|Suspend\|Uninstall\|Unregister\|Wait\|Debug\|Measure\|Ping\|Repair\|Resolve\|Test\|Trace\|Connect\|Disconnect\|Read\|Receive\|Send\|Write\|Block\|Grant\|Protect\|Revoke\|Unblock\|Unprotect\|Use\|ForEach\|Sort\|Tee\|Where)+ | Strings with many repetitions of 'Add' can start matching anywhere after the start of the preceeding (Add\|Clear\|Close\|Copy\|Enter\|Exit\|Find\|Format\|Get\|Hide\|Join\|Lock\|Move\|New\|Open\|Optimize\|Pop\|Push\|Redo\|Remove\|Rename\|Reset\|Resize\|Search\|Select\|Set\|Show\|Skip\|Split\|Step\|Switch\|Undo\|Unlock\|Watch\|Backup\|Checkpoint\|Compare\|Compress\|Convert\|ConvertFrom\|ConvertTo\|Dismount\|Edit\|Expand\|Export\|Group\|Import\|Initialize\|Limit\|Merge\|Out\|Publish\|Restore\|Save\|Sync\|Unpublish\|Update\|Approve\|Assert\|Complete\|Confirm\|Deny\|Disable\|Enable\|Install\|Invoke\|Register\|Request\|Restart\|Resume\|Start\|Stop\|Submit\|Suspend\|Uninstall\|Unregister\|Wait\|Debug\|Measure\|Ping\|Repair\|Resolve\|Test\|Trace\|Connect\|Disconnect\|Read\|Receive\|Send\|Write\|Block\|Grant\|Protect\|Revoke\|Unblock\|Unprotect\|Use\|ForEach\|Sort\|Tee\|Where)+(-)[\\w\\d]+ | | highlight.js:14:17:14:52 | [a-z0-9&#*=?@\\\\><:,()$[\\]_.{}!+%^-]+ | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding ([ ]*[a-z0-9&#*=?@\\\\><:,()$[\\]_.{}!+%^-]+)+ | @@ -7,7 +7,8 @@ | highlight.js:18:20:18:22 | .*? | Strings starting with '"' and with many repetitions of '"' can start matching anywhere after the start of the preceeding .*? | | highlight.js:18:27:18:29 | .*? | Strings starting with '[' and with many repetitions of '[' can start matching anywhere after the start of the preceeding .*? | | highlight.js:18:33:18:69 | [^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+ | Strings with many repetitions of '$' can start matching anywhere after the start of the preceeding .*? | -| highlight.js:19:56:19:61 | [^\\]]+ | Strings starting with '[' and with many repetitions of '.[' can start matching anywhere after the start of the preceeding (\\.\|\\.\\/\|\\/)?(""\|"[^"]+"\|''\|'[^']+'\|\\[\\]\|\\[[^\\]]+\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+)((\\.\|\\/)(""\|"[^"]+"\|''\|'[^']+'\|\\[\\]\|\\[[^\\]]+\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+))* | +| highlight.js:19:56:19:61 | [^\\]]+ | Strings starting with '[' and with many repetitions of '[' can start matching anywhere after the start of the preceeding (\\.\|\\.\\/\|\\/)?(""\|"[^"]+"\|''\|'[^']+'\|\\[\\]\|\\[[^\\]]+\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+)((\\.\|\\/)(""\|"[^"]+"\|''\|'[^']+'\|\\[\\]\|\\[[^\\]]+\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+))* | +| highlight.js:19:141:19:146 | [^\\]]+ | Strings starting with '"".[' and with many repetitions of '$.[' can start matching anywhere after the start of the preceeding (\\.\|\\.\\/\|\\/)?(""\|"[^"]+"\|''\|'[^']+'\|\\[\\]\|\\[[^\\]]+\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+)((\\.\|\\/)(""\|"[^"]+"\|''\|'[^']+'\|\\[\\]\|\\[[^\\]]+\\]\|[^\\s!"#%&'()*+,.\\/;<=>@\\[\\\\\\]^`{\|}~]+))* | | highlight.js:22:12:22:82 | ((decltype\\(auto\\)\|(?:[a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(?:<.*?>)?)[\\*&\\s]+)+ | Strings with many repetitions of 'A\\t' can start matching anywhere after the start of the preceeding .*? | | highlight.js:22:43:22:45 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding .*? | | highlight.js:22:66:22:68 | .*? | Strings starting with 'A<' and with many repetitions of 'A<' can start matching anywhere after the start of the preceeding \\w* | @@ -16,8 +17,8 @@ | highlight.js:23:42:23:44 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|([a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(<[^<>]+>)?)[\\*&\\s]+)+([a-zA-Z_]\\w*::)?[a-zA-Z]\\w*\\s*\\( | | highlight.js:23:63:23:68 | [^<>]+ | Strings starting with 'A<' and with many repetitions of ';>\\tA<' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|([a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(<[^<>]+>)?)[\\*&\\s]+)+([a-zA-Z_]\\w*::)?[a-zA-Z]\\w*\\s*\\( | | highlight.js:23:73:23:80 | [\\*&\\s]+ | Strings starting with 'A' and with many repetitions of '\\tA\\t' can start matching anywhere after the start of the preceeding ((decltype\\(auto\\)\|([a-zA-Z_]\\w*::)?[a-zA-Z_]\\w*(<[^<>]+>)?)[\\*&\\s]+)+([a-zA-Z_]\\w*::)?[a-zA-Z]\\w*\\s*\\( | -| highlight.js:26:14:26:34 | (([\\/.])[\\w\\-.\\/=]+)+ | Strings with many repetitions of '.-' can start matching anywhere after the start of the preceeding [\\w\\-.\\/=]+ | -| highlight.js:26:22:26:32 | [\\w\\-.\\/=]+ | Strings with many repetitions of '.-' can start matching anywhere after the start of the preceeding (([\\/.])[\\w\\-.\\/=]+)+ | +| highlight.js:26:14:26:34 | (([\\/.])[\\w\\-.\\/=]+)+ | Strings with many repetitions of '..' can start matching anywhere after the start of the preceeding [\\w\\-.\\/=]+ | +| highlight.js:26:22:26:32 | [\\w\\-.\\/=]+ | Strings with many repetitions of '..' can start matching anywhere after the start of the preceeding (([\\/.])[\\w\\-.\\/=]+)+ | | highlight.js:31:14:31:28 | (?:\\\\.\|[^`\\\\])+ | Strings starting with '`' and with many repetitions of '\\\\`' can start matching anywhere after the start of the preceeding `(?:\\\\.\|[^`\\\\])+` | | highlight.js:38:21:38:23 | \\w* | Strings starting with 'A' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding [a-zA-Z_]\\w*\\([^()]*(\\([^()]*(\\([^()]*\\))*[^()]*\\))*[^()]*\\)\\s*\\{ | | highlight.js:38:54:38:59 | [^()]* | Strings starting with 'A((' and with many repetitions of ''' can start matching anywhere after the start of the preceeding [^()]* | @@ -93,7 +94,6 @@ | polynomial-redos.js:64:14:64:15 | Y* | Strings starting with 'fooY' and with many repetitions of 'Y' can start matching anywhere after the start of the preceeding (K\|Y)+ | | polynomial-redos.js:65:14:65:15 | .* | Strings starting with 'fooY' and with many repetitions of 'K' can start matching anywhere after the start of the preceeding (K\|Y)+ | | polynomial-redos.js:66:9:66:10 | .* | Strings starting with 'K' and with many repetitions of 'K' can start matching anywhere after the start of the preceeding (K\|Y).*X | -| polynomial-redos.js:67:8:67:9 | .* | Strings starting with 'X' and with many repetitions of 'Z' can start matching anywhere after the start of the preceeding [^Y].*X | | polynomial-redos.js:68:8:68:9 | .* | Strings starting with 'X' and with many repetitions of 'X' can start matching anywhere after the start of the preceeding [^Y].*$ | | polynomial-redos.js:69:8:69:9 | .* | Strings starting with 'X' and with many repetitions of 'X' can start matching anywhere after the start of the preceeding [^Y].*$ | | polynomial-redos.js:71:51:71:63 | [?\\x21-\\x7E]* | Strings starting with ',-+' and with many repetitions of '++' can start matching anywhere after the start of the preceeding [A-Za-z0-9+/]+ | @@ -123,33 +123,37 @@ | polynomial-redos.js:111:17:111:19 | \\s* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding \\s*$ | | polynomial-redos.js:112:17:112:19 | \\s+ | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding \\s+$ | | polynomial-redos.js:114:22:114:24 | \\w* | Strings starting with '5' and with many repetitions of '5' can start matching anywhere after the start of the preceeding \\d* | -| polynomial-redos.js:116:21:116:28 | [\\d\\D]*? | Strings starting with '/*' and with many repetitions of 'a/*' can start matching anywhere after the start of the preceeding \\/\\*[\\d\\D]*?\\*\\/ | | polynomial-redos.js:118:17:118:23 | (#\\d+)+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding \\d+ | | polynomial-redos.js:124:33:124:35 | \\s+ | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding \\s+$ | | polynomial-redos.js:130:21:130:22 | c+ | Strings starting with 'c' and with many repetitions of 'c' can start matching anywhere after the start of the preceeding cc+D | | polynomial-redos.js:133:22:133:23 | f+ | Strings starting with 'f' and with many repetitions of 'f' can start matching anywhere after the start of the preceeding ff+G | | polynomial-redos.js:136:25:136:26 | h+ | Strings starting with 'h' and with many repetitions of 'h' can start matching anywhere after the start of the preceeding hh+I | +| polynomial-redos.js:138:322:138:323 | .* | Strings starting with 'AAAAAAAAAAAAAAAAAAAAAABBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC' and with many repetitions of 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC' can start matching anywhere after the start of the preceeding (AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)C.*X | | regexplib/address.js:27:3:27:5 | \\s* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{4}\\)?(\\s*\|-)\\d{3}(\\s*\|-)\\d{3}\\s*) | | regexplib/address.js:27:48:27:50 | \\s* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{3}\\)?(\\s*\|-)\\d{3}(\\s*\|-)\\d{4}\\s*) | | regexplib/address.js:27:93:27:95 | \\s* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (\\s*(7\|8)(\\d{7}\|\\d{3}(\\-\|\\s{1})\\d{4})\\s*) | | regexplib/address.js:38:39:38:45 | [ 0-9]* | Strings starting with 'po' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding [ \|\\.]* | | regexplib/address.js:51:220:51:222 | \\w+ | Strings starting with 'C/O ' and with many repetitions of '0' can start matching anywhere after the start of the preceeding \\x20* | -| regexplib/address.js:51:331:51:344 | [a-zA-Z0-9\\-]+ | Strings starting with 'C/O 0#' and with many repetitions of '0APT0' can start matching anywhere after the start of the preceeding \\w+ | +| regexplib/address.js:51:331:51:344 | [a-zA-Z0-9\\-]+ | Strings starting with 'C/O 0#' and with many repetitions of 'FL0' can start matching anywhere after the start of the preceeding \\w+ | +| regexplib/address.js:51:399:51:401 | \\s+ | Strings starting with 'C/O 0' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\x20* | | regexplib/address.js:51:415:51:419 | \\x20+ | Strings starting with 'C/O 0\\t0' and with many repetitions of ' 0 ' can start matching anywhere after the start of the preceeding \\x20* | +| regexplib/address.js:51:420:51:422 | \\w+ | Strings starting with 'C/O 0\\t0 ' and with many repetitions of '0 0 ' can start matching anywhere after the start of the preceeding \\w+ | | regexplib/address.js:51:616:51:618 | \\w+ | Strings starting with 'C/O 0\\tC/O ' and with many repetitions of '0' can start matching anywhere after the start of the preceeding \\x20* | -| regexplib/address.js:51:727:51:740 | [a-zA-Z0-9\\-]+ | Strings starting with 'C/O 0\\t0 0#' and with many repetitions of '0APT0' can start matching anywhere after the start of the preceeding \\w+ | -| regexplib/address.js:51:796:51:798 | \\s+ | Strings starting with 'C/O 0\\t' and with many repetitions of '\\t\\t' can start matching anywhere after the start of the preceeding \\s+ | +| regexplib/address.js:51:727:51:740 | [a-zA-Z0-9\\-]+ | Strings starting with 'C/O 0\\t0 0#' and with many repetitions of 'FL0' can start matching anywhere after the start of the preceeding \\w+ | +| regexplib/address.js:51:796:51:798 | \\s+ | Strings starting with 'C/O 0\\t' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+ | | regexplib/address.js:51:803:51:811 | [A-Za-z]+ | Strings starting with 'C/O 0\\t\\t' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding \\w+ | | regexplib/address.js:67:379:67:755 | [a-zA-Z0-9ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïñòóôõöøùúûüýÿ\\.\\,\\-\\/\\' ]+ | Strings starting with '#' and with many repetitions of '#' can start matching anywhere after the start of the preceeding [a-zA-Z0-9ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïñòóôõöøùúûüýÿ\\.\\,\\-\\/\\']+ | | regexplib/address.js:69:3:69:5 | \\s* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{4}\\)?(\\s*\|-)\\d{3}(\\s*\|-)\\d{3}\\s*) | | regexplib/address.js:69:48:69:50 | \\s* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{3}\\)?(\\s*\|-)\\d{3}(\\s*\|-)\\d{4}\\s*) | | regexplib/address.js:69:93:69:95 | \\s* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (\\s*(7\|8)(\\d{7}\|\\d{3}(\\-\|\\s{1})\\d{4})\\s*) | | regexplib/address.js:75:220:75:222 | \\w+ | Strings starting with 'C/O ' and with many repetitions of '0' can start matching anywhere after the start of the preceeding \\x20* | -| regexplib/address.js:75:331:75:344 | [a-zA-Z0-9\\-]+ | Strings starting with 'C/O 0#' and with many repetitions of '0APT0' can start matching anywhere after the start of the preceeding \\w+ | +| regexplib/address.js:75:331:75:344 | [a-zA-Z0-9\\-]+ | Strings starting with 'C/O 0#' and with many repetitions of 'FL0' can start matching anywhere after the start of the preceeding \\w+ | +| regexplib/address.js:75:399:75:401 | \\s+ | Strings starting with 'C/O 0' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\x20* | | regexplib/address.js:75:415:75:419 | \\x20+ | Strings starting with 'C/O 0\\t0' and with many repetitions of ' 0 ' can start matching anywhere after the start of the preceeding \\x20* | +| regexplib/address.js:75:420:75:422 | \\w+ | Strings starting with 'C/O 0\\t0 ' and with many repetitions of '0 0 ' can start matching anywhere after the start of the preceeding \\w+ | | regexplib/address.js:75:616:75:618 | \\w+ | Strings starting with 'C/O 0\\tC/O ' and with many repetitions of '0' can start matching anywhere after the start of the preceeding \\x20* | -| regexplib/address.js:75:727:75:740 | [a-zA-Z0-9\\-]+ | Strings starting with 'C/O 0\\t0 0#' and with many repetitions of '0APT0' can start matching anywhere after the start of the preceeding \\w+ | -| regexplib/address.js:75:796:75:798 | \\s+ | Strings starting with 'C/O 0\\t' and with many repetitions of '\\t\\t' can start matching anywhere after the start of the preceeding \\s+ | +| regexplib/address.js:75:727:75:740 | [a-zA-Z0-9\\-]+ | Strings starting with 'C/O 0\\t0 0#' and with many repetitions of 'FL0' can start matching anywhere after the start of the preceeding \\w+ | +| regexplib/address.js:75:796:75:798 | \\s+ | Strings starting with 'C/O 0\\t' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+ | | regexplib/address.js:75:803:75:811 | [A-Za-z]+ | Strings starting with 'C/O 0\\t\\t' and with many repetitions of 'A' can start matching anywhere after the start of the preceeding \\w+ | | regexplib/address.js:85:15:85:49 | ([0-9]\|[ ]\|[-]\|[\\(]\|[\\)]\|ext.\|[,])+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding (?([0-9]\|[ ]\|[-]\|[\\(]\|[\\)]\|ext.\|[,])+)([ ]\|[:]\|\\t\|[-])*(?Home\|Office\|Work\|Away\|Fax\|FAX\|Phone) | | regexplib/address.js:85:51:85:67 | ([ ]\|[:]\|\\t\|[-])* | Strings starting with '0' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding ([0-9]\|[ ]\|[-]\|[\\(]\|[\\)]\|ext.\|[,])+ | @@ -163,8 +167,10 @@ | regexplib/email.js:5:24:5:35 | [a-zA-Z0-9]+ | Strings starting with '0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding ([_\\.\\-]?[a-zA-Z0-9]+)* | | regexplib/email.js:5:63:5:74 | [a-zA-Z0-9]+ | Strings starting with '0@0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [A-Za-z0-9]+ | | regexplib/email.js:8:16:8:49 | [^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+ | Strings with many repetitions of '!' can start matching anywhere after the start of the preceeding (?(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\"))(?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\")))*)@(?(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\[(?:(?:[^\\[\\]\\\\\\r\\n])\|(?:\\\\.))*\\]))(?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\[(?:(?:[^\\[\\]\\\\\\r\\n])\|(?:\\\\.))*\\])))*) | +| regexplib/email.js:8:57:8:84 | (?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))* | Strings starting with '"' and with many repetitions of '\\\\"' can start matching anywhere after the start of the preceeding (?(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\"))(?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\")))*)@(?(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\[(?:(?:[^\\[\\]\\\\\\r\\n])\|(?:\\\\.))*\\]))(?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\[(?:(?:[^\\[\\]\\\\\\r\\n])\|(?:\\\\.))*\\])))*) | | regexplib/email.js:8:89:8:174 | (?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\")))* | Strings starting with '!' and with many repetitions of '.!' can start matching anywhere after the start of the preceeding (?(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\"))(?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\")))*)@(?(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\[(?:(?:[^\\[\\]\\\\\\r\\n])\|(?:\\\\.))*\\]))(?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\[(?:(?:[^\\[\\]\\\\\\r\\n])\|(?:\\\\.))*\\])))*) | | regexplib/email.js:8:100:8:133 | [^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+ | Strings starting with '!.' and with many repetitions of '!.!' can start matching anywhere after the start of the preceeding (?(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\"))(?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\")))*)@(?(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\[(?:(?:[^\\[\\]\\\\\\r\\n])\|(?:\\\\.))*\\]))(?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\[(?:(?:[^\\[\\]\\\\\\r\\n])\|(?:\\\\.))*\\])))*) | +| regexplib/email.js:8:141:8:168 | (?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))* | Strings starting with '!."' and with many repetitions of '".!."' can start matching anywhere after the start of the preceeding (?(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\"))(?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\"(?:(?:[^\\"\\\\\\r\\n])\|(?:\\\\.))*\\")))*)@(?(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\[(?:(?:[^\\[\\]\\\\\\r\\n])\|(?:\\\\.))*\\]))(?:\\.(?:(?:[^ \\t\\(\\)\\<\\>@,;\\:\\\\\\"\\.\\[\\]\\r\\n]+)\|(?:\\[(?:(?:[^\\[\\]\\\\\\r\\n])\|(?:\\\\.))*\\])))*) | | regexplib/email.js:12:2:12:4 | \\w+ | Strings with many repetitions of '0' can start matching anywhere after the start of the preceeding \\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*([,;]\\s*\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*)* | | regexplib/email.js:12:5:12:15 | ([-+.]\\w+)* | Strings starting with '0' and with many repetitions of '+0' can start matching anywhere after the start of the preceeding \\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*([,;]\\s*\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*)* | | regexplib/email.js:12:11:12:13 | \\w+ | Strings starting with '0+' and with many repetitions of '0+' can start matching anywhere after the start of the preceeding \\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*([,;]\\s*\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*)* | @@ -195,12 +201,16 @@ | regexplib/markup.js:2:3:2:7 | [^>]* | Strings starting with '<' and with many repetitions of '<' can start matching anywhere after the start of the preceeding <[^>]*> | | regexplib/markup.js:3:440:3:456 | (\\s(?.+?))* | Strings starting with '.+?))* | +| regexplib/markup.js:5:1525:5:1527 | \\s* | Strings starting with '?'DateLiteral' ?# Per the VB Spec : DateLiteral ::= '#' DateOrTime '#' # ?'DateOrTime' DateValue ?# TimeValue ::= HourValue : MinuteValue 10 ?# Hour 01 - 24 : 60 ?# Minute 01 - 60 : ?# Optional Minute :01 - :60 ' and with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s* | +| regexplib/markup.js:6:11:6:25 | [\\w\\*\\)\\(\\,\\s]+ | Strings starting with 'SELECT\\t' and with many repetitions of 'SELECT\\t' can start matching anywhere after the start of the preceeding (SELECT\\s[\\w\\*\\)\\(\\,\\s]+\\sFROM\\s[\\w]+) | | regexplib/markup.js:6:99:6:113 | [\\s\\w\\d\\)\\(\\,]* | Strings starting with ' INSERT\\tINTO\\t0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [\\d\\w]+ | | regexplib/markup.js:7:8:7:23 | (?:\\\\.\|[^\\\\"]*)* | Strings starting with '"!' and with many repetitions of '\\\\"!\\\\a' can start matching anywhere after the start of the preceeding "([^"](?:\\\\.\|[^\\\\"]*)*)" | | regexplib/markup.js:9:6:9:13 | [\\s\\S]*? | Strings starting with ' | | regexplib/markup.js:12:40:12:42 | .*? | Strings starting with ') | | regexplib/markup.js:12:117:12:121 | [^>]* | Strings starting with ']*>) | +| regexplib/markup.js:12:149:12:153 | [^>]* | Strings starting with 'font-family:' and with many repetitions of 'font-family:' can start matching anywhere after the start of the preceeding (font-family:[^>]*[;']) | +| regexplib/markup.js:12:171:12:175 | [^>]* | Strings starting with 'font-size:' and with many repetitions of 'font-size:' can start matching anywhere after the start of the preceeding (font-size:[^>]*[;'])(?-s) | | regexplib/markup.js:13:6:13:12 | [^"']+? | Strings starting with '<' and with many repetitions of '!' can start matching anywhere after the start of the preceeding .*? | | regexplib/markup.js:13:14:13:16 | .+? | Strings starting with '<' and with many repetitions of '!' can start matching anywhere after the start of the preceeding .*? | | regexplib/markup.js:14:13:14:14 | .* | Strings starting with '<' and with many repetitions of 'a' can start matching anywhere after the start of the preceeding .* | @@ -216,7 +226,8 @@ | regexplib/markup.js:20:52:20:53 | .* | Strings with many repetitions of '=color' can start matching anywhere after the start of the preceeding [^>]+ | | regexplib/markup.js:20:155:20:156 | '+ | Strings with many repetitions of '''' can start matching anywhere after the start of the preceeding '+ | | regexplib/markup.js:20:197:20:198 | "+ | Strings with many repetitions of '""' can start matching anywhere after the start of the preceeding "+ | -| regexplib/markup.js:20:274:20:276 | .*? | Strings starting with ']+color.*>) #IF\\/THEN lookahead color in tag (.*?color\\s*?[=\|:]\\s*?) # IF found THEN move ahead ('+\\#*?[\\w\\s]*'+ # CAPTURE ColorName\\/Hex \|"+\\#*?[\\w\\s]*"+ # single or double \|\\#*\\w*\\b) # or no quotes\t.*?> # & move to end of tag \|.*?> # ELSE move to end of Tag ) # Close the If\\/Then lookahead # Use Multiline and IgnoreCase # Replace the matches from RE with MatchEvaluator below: # if m.Groups(1).Value<>"" then # Return "" # else # Return "" # end if | +| regexplib/markup.js:20:245:20:247 | .*? | Strings with many repetitions of 'color: # IF found THEN move ahead "" # single or double # or no quotes\\t' can start matching anywhere after the start of the preceeding .*? | +| regexplib/markup.js:20:274:20:276 | .*? | Strings starting with ']+color.*>) #IF\\/THEN lookahead color in tag (.*?color\\s*?[=\|:]\\s*?) # IF found THEN move ahead ('+\\#*?[\\w\\s]*'+ # CAPTURE ColorName\\/Hex \|"+\\#*?[\\w\\s]*"+ # single or double \|\\#*\\w*\\b) # or no quotes\t.*?> # & move to end of tag \|.*?> # ELSE move to end of Tag ) # Close the If\\/Then lookahead # Use Multiline and IgnoreCase # Replace the matches from RE with MatchEvaluator below: # if m.Groups(1).Value<>"" then # Return "" # else # Return "" # end if | | regexplib/markup.js:24:39:24:41 | \\s+ | Strings starting with '<A' and with many repetitions of '\\t-\\t!=\\t' can start matching anywhere after the start of the preceeding \\s* | | regexplib/markup.js:24:43:24:45 | \\S+ | Strings starting with '<A\\t' and with many repetitions of '-\\t!=' can start matching anywhere after the start of the preceeding \\s* | | regexplib/markup.js:24:48:24:50 | \\s* | Strings starting with '<A\\t!' and with many repetitions of '\\t=-\\t!\\t' can start matching anywhere after the start of the preceeding \\s+ | @@ -225,7 +236,6 @@ | regexplib/markup.js:25:45:25:49 | [^>]* | Strings starting with ']* | Strings starting with '<' and with many repetitions of '<' can start matching anywhere after the start of the preceeding <[^>]*name[\\s]*=[\\s]*"?[^\\w_]*"?[^>]*> | | regexplib/markup.js:27:34:27:38 | [^>]* | Strings starting with ']* | Strings starting with '<' and with many repetitions of ']*)(\\s[^<]*)> | | regexplib/markup.js:37:15:37:19 | [\\w]* | Strings starting with '[0' and with many repetitions of '0' can start matching anywhere after the start of the preceeding \\w+ | @@ -235,7 +245,6 @@ | regexplib/markup.js:43:45:43:49 | [^>]* | Strings starting with ']* | Strings starting with '<' and with many repetitions of '<' can start matching anywhere after the start of the preceeding <[^>]*name[\\s]*=[\\s]*"?[^\\w_]*"?[^>]*> | | regexplib/markup.js:44:34:44:38 | [^>]* | Strings starting with '' and with many repetitions of '' can start matching anywhere after the start of the preceeding [^']*? | | regexplib/markup.js:62:9:62:14 | [^>]*? | Strings starting with '' and with many repetitions of '>;' can start matching anywhere after the start of the preceeding .*? | | regexplib/markup.js:62:57:62:59 | .*? | Strings starting with '' and with many repetitions of '>a' can start matching anywhere after the start of the preceeding .*? | -| regexplib/markup.js:63:70:63:77 | [\\w\\W]*? | Strings with many repetitions of 'a/*' can start matching anywhere after the start of the preceeding (?((?m:^[\\t ]*\\/{2}[^\\n\\r\\v\\f]+[\\n\\r\\v\\f]*){2,})\|(\\/\\*[\\w\\W]*?\\*\\/)) | | regexplib/misc.js:4:36:4:44 | [a-zA-Z]* | Strings starting with 'A' and with many repetitions of 'AA' can start matching anywhere after the start of the preceeding [a-zA-Z]+ | | regexplib/misc.js:76:2:76:27 | (AUX\|PRN\|NUL\|COM\\d\|LPT\\d)+ | Strings with many repetitions of 'AUX' can start matching anywhere after the start of the preceeding (AUX\|PRN\|NUL\|COM\\d\|LPT\\d)+\\s*$ | | regexplib/misc.js:81:31:81:45 | [^a-z\\:\\,\\(\\)]* | Strings starting with '#' and with many repetitions of '#' can start matching anywhere after the start of the preceeding ([A-Zäöü0-9\\/][^a-z\\:\\,\\(\\)]*[A-Zäöü0-9])($\|[\\.\\:\\,\\;\\)\\-\\ \\+]\|s\\b) | @@ -270,7 +279,7 @@ | regexplib/misc.js:95:25:95:26 | .+ | Strings starting with 'at\\t' and with many repetitions of 'at\\ta' can start matching anywhere after the start of the preceeding (at\\s)(?.+)(\\.)(?[^\\.]*)(\\()(?[^\\)]*)(\\))((\\sin\\s)(?.+)(:line )(?[\\d]*))? | | regexplib/misc.js:95:71:95:76 | [^\\)]* | Strings starting with 'at\\ta.(' and with many repetitions of '((' can start matching anywhere after the start of the preceeding .+ | | regexplib/misc.js:95:103:95:104 | .+ | Strings starting with 'at\\ta.()\\tin\\t' and with many repetitions of '()\\tin\\t-' can start matching anywhere after the start of the preceeding .+ | -| regexplib/misc.js:101:52:101:70 | [a-z0-9\\/\\.\\?\\=\\&]* | Strings starting with '".htm' and with many repetitions of '.asp' can start matching anywhere after the start of the preceeding [a-z0-9\\/\\.\\?\\=\\&]* | +| regexplib/misc.js:101:52:101:70 | [a-z0-9\\/\\.\\?\\=\\&]* | Strings starting with '".htm' and with many repetitions of '.htm' can start matching anywhere after the start of the preceeding [a-z0-9\\/\\.\\?\\=\\&]* | | regexplib/misc.js:112:3:112:5 | \\s* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{4}\\)?\\s*\\d{6}\\s*) | | regexplib/misc.js:112:32:112:34 | \\s* | Strings with many repetitions of '\\t' can start matching anywhere after the start of the preceeding (\\s*\\(?0\\d{3}\\)?\\s*\\d{3}\\s*\\d{4}\\s*) | | regexplib/misc.js:114:6:114:8 | \\\|+ | Strings starting with 'a' and with many repetitions of '\|' can start matching anywhere after the start of the preceeding .+ | @@ -281,7 +290,7 @@ | regexplib/misc.js:123:36:123:38 | .*? | Strings starting with '?se[A' and with many repetitions of '?se[Aa' can start matching anywhere after the start of the preceeding (?s)(?:\\e\\[(?:(\\d+);?)*([A-Za-z])(.*?))(?=\\e\\[\|\\z) | | regexplib/misc.js:126:15:126:20 | [a-z]+ | Strings starting with 'a' and with many repetitions of 'aa' can start matching anywhere after the start of the preceeding [a-z]+ | | regexplib/misc.js:141:15:141:19 | [^;]+ | Strings starting with '{\\\\f\\\\' and with many repetitions of '{\\\\f\\\\:' can start matching anywhere after the start of the preceeding (\\{\\\\f\\d*)\\\\([^;]+;) | -| regexplib/misc.js:144:52:144:70 | [a-z0-9\\/\\.\\?\\=\\&]* | Strings starting with '".htm' and with many repetitions of '.asp' can start matching anywhere after the start of the preceeding [a-z0-9\\/\\.\\?\\=\\&]* | +| regexplib/misc.js:144:52:144:70 | [a-z0-9\\/\\.\\?\\=\\&]* | Strings starting with '".htm' and with many repetitions of '.htm' can start matching anywhere after the start of the preceeding [a-z0-9\\/\\.\\?\\=\\&]* | | regexplib/misc.js:148:12:148:18 | [^\\s>]+ | Strings starting with '<' and with many repetitions of ']+(\\s+[^"'=]+(=("[^"]*")\|('[^\\']*')\|([^\\s"'>]*))?)*\\s*\\/?> | | regexplib/misc.js:148:20:148:22 | \\s+ | Strings starting with '' and with many repetitions of 'href=! >;' can start matching anywhere after the start of the preceeding href\\s*=\\s*(?:(?:\\"(?[^\\"]*)\\")\|(?[^\\s*] ))>(?[^<]+)<\\/\\w> | +| regexplib/uri.js:29:2:29:45 | ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+ | Strings with many repetitions of 'wwwa' can start matching anywhere after the start of the preceeding ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+(([a-zA-Z0-9\\.-]+\\.[a-zA-Z]{2,4})\|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(\\/[a-zA-Z0-9%:/-_\\?\\.'~]*)? | +| regexplib/uri.js:29:48:29:62 | [a-zA-Z0-9\\.-]+ | Strings starting with 'wwwa' and with many repetitions of 'www--' can start matching anywhere after the start of the preceeding ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+ | +| regexplib/uri.js:31:65:31:69 | [^<]+ | Strings starting with 'href=! >' and with many repetitions of 'href="">;' can start matching anywhere after the start of the preceeding href\\s*=\\s*(?:(?:\\"(?<url>[^\\"]*)\\")\|(?<url>[^\\s*] ))>(?<title>[^<]+)<\\/\\w> | | regexplib/uri.js:34:3:34:9 | [^\\=&]+ | Strings with many repetitions of '%' can start matching anywhere after the start of the preceeding ([^\\=&]+)(?<!param1\|param2\|param3)\\=([^\\=&]+)(&)? | | regexplib/uri.js:36:40:36:42 | \\d* | Strings starting with '$1' and with many repetitions of '1' can start matching anywhere after the start of the preceeding [1-9]+ | | regexplib/uri.js:38:20:38:28 | [a-z0-9]+ | Strings starting with 'a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-z]+ | @@ -393,7 +406,8 @@ | regexplib/uri.js:55:20:55:28 | [a-z0-9]+ | Strings starting with 'a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-z]+ | | regexplib/uri.js:55:35:55:40 | [a-z]+ | Strings starting with 'a.' and with many repetitions of 'aa' can start matching anywhere after the start of the preceeding [a-z0-9]+ | | regexplib/uri.js:55:52:55:60 | [a-z0-9]+ | Strings starting with 'a.a' and with many repetitions of '0' can start matching anywhere after the start of the preceeding [a-z]+ | -| regexplib/uri.js:58:2:58:45 | ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+ | Strings with many repetitions of 'ftp://' can start matching anywhere after the start of the preceeding ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+(([a-zA-Z0-9\\.-]+\\.[a-zA-Z]{2,4})\|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(\\/[a-zA-Z0-9%:/-_\\?\\.'~]*)? | +| regexplib/uri.js:58:2:58:45 | ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+ | Strings with many repetitions of 'wwwa' can start matching anywhere after the start of the preceeding ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+(([a-zA-Z0-9\\.-]+\\.[a-zA-Z]{2,4})\|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(\\/[a-zA-Z0-9%:/-_\\?\\.'~]*)? | +| regexplib/uri.js:58:48:58:62 | [a-zA-Z0-9\\.-]+ | Strings starting with 'wwwa' and with many repetitions of 'www--' can start matching anywhere after the start of the preceeding ((http\\:\\/\\/\|https\\:\\/\\/\|ftp\\:\\/\\/)\|(www.))+ | | regexplib/uri.js:64:31:64:36 | [\\w-]+ | Strings with many repetitions of '-' can start matching anywhere after the start of the preceeding [\\w-\\s]* | | regexplib/uri.js:70:16:70:31 | [a-zA-Z0-9\\-\\.]+ | Strings starting with '0' and with many repetitions of '00' can start matching anywhere after the start of the preceeding [a-zA-Z0-9]+ | | regexplib/uri.js:71:75:71:89 | [^\\/\\\\:*?"<>\|]+ | Strings starting with 'A:\\\\!.' and with many repetitions of '!.' can start matching anywhere after the start of the preceeding [^\\/\\\\:*?"<>\|]+ | @@ -475,10 +489,10 @@ | tst.js:254:51:254:53 | \\w* | Strings starting with 'foobarbazfoobarbazfoobarbaz' and with many repetitions of 'foobarbaz' can start matching anywhere after the start of the preceeding \\d* | | tst.js:254:63:254:65 | \\s* | Strings starting with 'foobarbazfoobarbazfoobarbazfoobarbaz' and with many repetitions of 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz' can start matching anywhere after the start of the preceeding \\d* | | tst.js:254:75:254:77 | \\d* | Strings starting with 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbaz' and with many repetitions of 'foobarbazfoobarbazfoobarbazfoobarbazfoobarbazfoobarbaz' can start matching anywhere after the start of the preceeding \\s* | -| tst.js:257:14:257:116 | (.thisisagoddamnlongstringforstresstestingthequery\|\\sthisisagoddamnlongstringforstresstestingthequery)* | Strings with many repetitions of '\\tthisisagoddamnlongstringforstresstestingthequery' can start matching anywhere after the start of the preceeding (.thisisagoddamnlongstringforstresstestingthequery\|\\sthisisagoddamnlongstringforstresstestingthequery)*- | +| tst.js:257:14:257:116 | (.thisisagoddamnlongstringforstresstestingthequery\|\\sthisisagoddamnlongstringforstresstestingthequery)* | Strings with many repetitions of 'athisisagoddamnlongstringforstresstestingthequery' can start matching anywhere after the start of the preceeding (.thisisagoddamnlongstringforstresstestingthequery\|\\sthisisagoddamnlongstringforstresstestingthequery)*- | | tst.js:260:14:260:77 | (thisisagoddamnlongstringforstresstestingthequery\|this\\w+query)* | Strings with many repetitions of 'this0query' can start matching anywhere after the start of the preceeding \\w+ | | tst.js:260:68:260:70 | \\w+ | Strings starting with 'this' and with many repetitions of 'this' can start matching anywhere after the start of the preceeding (thisisagoddamnlongstringforstresstestingthequery\|this\\w+query)* | -| tst.js:263:15:263:117 | (thisisagoddamnlongstringforstresstestingthequery\|imanotherbutunrelatedstringcomparedtotheotherstring)* | Strings with many repetitions of 'imanotherbutunrelatedstringcomparedtotheotherstring' can start matching anywhere after the start of the preceeding (thisisagoddamnlongstringforstresstestingthequery\|imanotherbutunrelatedstringcomparedtotheotherstring)*- | +| tst.js:263:15:263:117 | (thisisagoddamnlongstringforstresstestingthequery\|imanotherbutunrelatedstringcomparedtotheotherstring)* | Strings with many repetitions of 'thisisagoddamnlongstringforstresstestingthequery' can start matching anywhere after the start of the preceeding (thisisagoddamnlongstringforstresstestingthequery\|imanotherbutunrelatedstringcomparedtotheotherstring)*- | | tst.js:272:21:272:22 | b+ | Strings with many repetitions of 'b' can start matching anywhere after the start of the preceeding (b+)+ | | tst.js:275:25:275:27 | \\s+ | Strings starting with '<0' and with many repetitions of '\\t0="\\t0="\\t' can start matching anywhere after the start of the preceeding [^"]* | | tst.js:275:28:275:30 | \\w+ | Strings starting with '<0\\t' and with many repetitions of '0="\\t0="\\t' can start matching anywhere after the start of the preceeding [^"]* | @@ -521,7 +535,7 @@ | tst.js:375:15:375:16 | x* | Strings with many repetitions of 'x' can start matching anywhere after the start of the preceeding (x*)+(?=$\|y) | | tst.js:378:16:378:22 | [\\s\\S]* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding ([\\s\\S]*)+(?=$) | | tst.js:379:16:379:22 | [\\s\\S]* | Strings with many repetitions of 'a' can start matching anywhere after the start of the preceeding ([\\s\\S]*)+(?=$\|y) | -| tst.js:381:15:381:24 | (foo\|FOO)* | Strings with many repetitions of 'FOO' can start matching anywhere after the start of the preceeding (foo\|FOO)*bar | +| tst.js:381:15:381:24 | (foo\|FOO)* | Strings with many repetitions of 'foo' can start matching anywhere after the start of the preceeding (foo\|FOO)*bar | | tst.js:382:14:382:23 | (foo\|FOO)* | Strings with many repetitions of 'foo' can start matching anywhere after the start of the preceeding (foo\|FOO)*bar | | tst.js:384:15:384:26 | ([AB]\|[ab])* | Strings with many repetitions of 'A' can start matching anywhere after the start of the preceeding ([AB]\|[ab])*C | | tst.js:385:14:385:25 | ([DE]\|[de])* | Strings with many repetitions of 'd' can start matching anywhere after the start of the preceeding ([DE]\|[de])*F | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialReDoS.expected b/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialReDoS.expected index 0892c7e0be5..0ec4c40fd2c 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialReDoS.expected +++ b/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/PolynomialReDoS.expected @@ -163,8 +163,6 @@ nodes | polynomial-redos.js:65:24:65:30 | tainted | | polynomial-redos.js:66:19:66:25 | tainted | | polynomial-redos.js:66:19:66:25 | tainted | -| polynomial-redos.js:67:18:67:24 | tainted | -| polynomial-redos.js:67:18:67:24 | tainted | | polynomial-redos.js:68:18:68:24 | req.url | | polynomial-redos.js:68:18:68:24 | req.url | | polynomial-redos.js:68:18:68:24 | req.url | @@ -221,8 +219,6 @@ nodes | polynomial-redos.js:112:2:112:8 | tainted | | polynomial-redos.js:114:2:114:8 | tainted | | polynomial-redos.js:114:2:114:8 | tainted | -| polynomial-redos.js:116:2:116:8 | tainted | -| polynomial-redos.js:116:2:116:8 | tainted | | polynomial-redos.js:118:2:118:8 | tainted | | polynomial-redos.js:118:2:118:8 | tainted | | polynomial-redos.js:121:7:121:55 | replaced | @@ -247,6 +243,8 @@ nodes | polynomial-redos.js:135:21:135:47 | tainted ... /g, "") | | polynomial-redos.js:136:5:136:13 | modified3 | | polynomial-redos.js:136:5:136:13 | modified3 | +| polynomial-redos.js:138:5:138:11 | tainted | +| polynomial-redos.js:138:5:138:11 | tainted | edges | lib/closure.js:3:21:3:21 | x | lib/closure.js:4:16:4:16 | x | | lib/closure.js:3:21:3:21 | x | lib/closure.js:4:16:4:16 | x | @@ -405,8 +403,6 @@ edges | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:65:24:65:30 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:66:19:66:25 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:66:19:66:25 | tainted | -| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:67:18:67:24 | tainted | -| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:67:18:67:24 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:71:2:71:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:71:2:71:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:73:2:73:8 | tainted | @@ -457,14 +453,14 @@ edges | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:112:2:112:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:114:2:114:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:114:2:114:8 | tainted | -| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:116:2:116:8 | tainted | -| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:116:2:116:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:118:2:118:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:118:2:118:8 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:121:18:121:24 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:129:17:129:23 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:132:18:132:24 | tainted | | polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:135:21:135:27 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:138:5:138:11 | tainted | +| polynomial-redos.js:5:6:5:32 | tainted | polynomial-redos.js:138:5:138:11 | tainted | | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:5:6:5:32 | tainted | | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:5:6:5:32 | tainted | | polynomial-redos.js:68:18:68:24 | req.url | polynomial-redos.js:68:18:68:24 | req.url | @@ -551,7 +547,6 @@ edges | polynomial-redos.js:64:3:64:31 | /^foo(K ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:64:24:64:30 | tainted | This $@ that depends on $@ may run slow on strings starting with 'fooY' and with many repetitions of 'Y'. | polynomial-redos.js:64:14:64:15 | Y* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:65:3:65:31 | /^foo(K ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:65:24:65:30 | tainted | This $@ that depends on $@ may run slow on strings starting with 'fooY' and with many repetitions of 'K'. | polynomial-redos.js:65:14:65:15 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:66:3:66:26 | /(K\|Y). ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:66:19:66:25 | tainted | This $@ that depends on $@ may run slow on strings starting with 'K' and with many repetitions of 'K'. | polynomial-redos.js:66:9:66:10 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:67:3:67:25 | /[^Y].* ... ainted) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:67:18:67:24 | tainted | This $@ that depends on $@ may run slow on strings starting with 'X' and with many repetitions of 'Z'. | polynomial-redos.js:67:8:67:9 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:69:3:69:26 | /[^Y].* ... q.body) | polynomial-redos.js:69:18:69:25 | req.body | polynomial-redos.js:69:18:69:25 | req.body | This $@ that depends on $@ may run slow on strings starting with 'X' and with many repetitions of 'X'. | polynomial-redos.js:69:8:69:9 | .* | regular expression | polynomial-redos.js:69:18:69:25 | req.body | a user-provided value | | polynomial-redos.js:71:2:71:67 | tainted ... E]*)$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:71:2:71:8 | tainted | This $@ that depends on $@ may run slow on strings starting with ',-+' and with many repetitions of '++'. | polynomial-redos.js:71:51:71:63 | [?\\x21-\\x7E]* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:73:2:73:60 | tainted ... LWP7")) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:73:2:73:8 | tainted | This $@ that depends on $@ may run slow on strings starting with 'MSIE 0.0' and with many repetitions of '0'. | polynomial-redos.js:73:50:73:51 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | @@ -579,9 +574,9 @@ edges | polynomial-redos.js:111:2:111:22 | tainted ... /\\s*$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:111:2:111:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of '\\t'. | polynomial-redos.js:111:17:111:19 | \\s* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:112:2:112:22 | tainted ... /\\s+$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:112:2:112:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of '\\t'. | polynomial-redos.js:112:17:112:19 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:114:2:114:27 | tainted ... 5\\w*$/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:114:2:114:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '5' and with many repetitions of '5'. | polynomial-redos.js:114:22:114:24 | \\w* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | -| polynomial-redos.js:116:2:116:35 | tainted ... \\*\\//g) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:116:2:116:8 | tainted | This $@ that depends on $@ may run slow on strings starting with '/*' and with many repetitions of 'a/*'. | polynomial-redos.js:116:21:116:28 | [\\d\\D]*? | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:118:2:118:25 | tainted ... \\d+)+/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:118:2:118:8 | tainted | This $@ that depends on $@ may run slow on strings with many repetitions of '0'. | polynomial-redos.js:118:17:118:23 | (#\\d+)+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:124:12:124:43 | result. ... /g, '') | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:124:12:124:17 | result | This $@ that depends on $@ may run slow on strings with many repetitions of '\\t'. | polynomial-redos.js:124:33:124:35 | \\s+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:130:2:130:31 | modifie ... g, "b") | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:130:2:130:9 | modified | This $@ that depends on $@ may run slow on strings starting with 'c' and with many repetitions of 'c'. | polynomial-redos.js:130:21:130:22 | c+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:133:2:133:32 | modifie ... g, "b") | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:133:2:133:10 | modified2 | This $@ that depends on $@ may run slow on strings starting with 'f' and with many repetitions of 'f'. | polynomial-redos.js:133:22:133:23 | f+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | | polynomial-redos.js:136:5:136:35 | modifie ... g, "b") | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:136:5:136:13 | modified3 | This $@ that depends on $@ may run slow on strings starting with 'h' and with many repetitions of 'h'. | polynomial-redos.js:136:25:136:26 | h+ | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | +| polynomial-redos.js:138:5:138:326 | tainted ... )C.*X/) | polynomial-redos.js:5:16:5:32 | req.query.tainted | polynomial-redos.js:138:5:138:11 | tainted | This $@ that depends on $@ may run slow on strings starting with 'AAAAAAAAAAAAAAAAAAAAAABBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC' and with many repetitions of 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC'. | polynomial-redos.js:138:322:138:323 | .* | regular expression | polynomial-redos.js:5:16:5:32 | req.query.tainted | a user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/polynomial-redos.js b/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/polynomial-redos.js index c4a7d38fc6b..fc0ddde66b2 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/polynomial-redos.js +++ b/javascript/ql/test/query-tests/Security/CWE-400/ReDoS/polynomial-redos.js @@ -134,4 +134,6 @@ app.use(function(req, res) { var modified3 = tainted.replace(/\s+/g, ""); modified3.replace(/hh+I/g, "b"); // NOT OK + + tainted.match(/(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)C.*X/); // NOT OK }); diff --git a/python/ql/lib/change-notes/2023-02-17-import-refined-variable.md b/python/ql/lib/change-notes/2023-02-17-import-refined-variable.md new file mode 100644 index 00000000000..e2dfcd8fd1a --- /dev/null +++ b/python/ql/lib/change-notes/2023-02-17-import-refined-variable.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Fixed module resolution so we allow imports of definitions that have had an attribute assigned to it, such as `class Foo; Foo.bar = 42`. diff --git a/python/ql/lib/change-notes/2023-03-22-database-modeling.md b/python/ql/lib/change-notes/2023-03-22-database-modeling.md new file mode 100644 index 00000000000..6cd23bed44f --- /dev/null +++ b/python/ql/lib/change-notes/2023-03-22-database-modeling.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added modeling of SQL execution in the packages `sqlite3.dbapi2`, `cassandra-driver`, `aiosqlite`, and the functions `sqlite3.Connection.executescript`/`sqlite3.Cursor.executescript` and `asyncpg.connection.connect()`. diff --git a/python/ql/lib/change-notes/2023-03-23-dataflow-renaming.md b/python/ql/lib/change-notes/2023-03-23-dataflow-renaming.md new file mode 100644 index 00000000000..54df71fae46 --- /dev/null +++ b/python/ql/lib/change-notes/2023-03-23-dataflow-renaming.md @@ -0,0 +1,6 @@ +--- +category: deprecated +--- +* The recently introduced new data flow and taint tracking APIs have had a + number of module and predicate renamings. The old APIs remain in place for + now. diff --git a/python/ql/lib/change-notes/2023-03-28-dataflow-rm-footgun.md b/python/ql/lib/change-notes/2023-03-28-dataflow-rm-footgun.md new file mode 100644 index 00000000000..82dc0a1d893 --- /dev/null +++ b/python/ql/lib/change-notes/2023-03-28-dataflow-rm-footgun.md @@ -0,0 +1,4 @@ +--- +category: fix +--- +* Fixed some accidental predicate visibility in the backwards-compatible wrapper for data flow configurations. In particular `DataFlow::hasFlowPath`, `DataFlow::hasFlow`, `DataFlow::hasFlowTo`, and `DataFlow::hasFlowToExpr` were accidentally exposed in a single version. diff --git a/python/ql/lib/qlpack.yml b/python/ql/lib/qlpack.yml index f40f7e10b4f..bc1863e7214 100644 --- a/python/ql/lib/qlpack.yml +++ b/python/ql/lib/qlpack.yml @@ -7,7 +7,7 @@ library: true upgrades: upgrades dependencies: codeql/regex: ${workspace} - codeql/util: ${workspace} codeql/tutorial: ${workspace} + codeql/util: ${workspace} dataExtensions: - semmle/python/frameworks/**/model.yml diff --git a/python/ql/lib/semmle/python/Frameworks.qll b/python/ql/lib/semmle/python/Frameworks.qll index d9592fcafb3..c0d3c5e0b23 100644 --- a/python/ql/lib/semmle/python/Frameworks.qll +++ b/python/ql/lib/semmle/python/Frameworks.qll @@ -3,12 +3,14 @@ */ // If you add modeling of a new framework/library, remember to add it to the docs in -// `docs/codeql/support/reusables/frameworks.rst` +// `docs/codeql/reusables/supported-frameworks.rst` private import semmle.python.frameworks.Aioch private import semmle.python.frameworks.Aiohttp private import semmle.python.frameworks.Aiomysql +private import semmle.python.frameworks.Aiosqlite private import semmle.python.frameworks.Aiopg private import semmle.python.frameworks.Asyncpg +private import semmle.python.frameworks.CassandraDriver private import semmle.python.frameworks.ClickhouseDriver private import semmle.python.frameworks.Cryptodome private import semmle.python.frameworks.Cryptography diff --git a/python/ql/lib/semmle/python/Unit.qll b/python/ql/lib/semmle/python/Unit.qll index e9611ed3df4..83a4a03321d 100644 --- a/python/ql/lib/semmle/python/Unit.qll +++ b/python/ql/lib/semmle/python/Unit.qll @@ -1,10 +1,3 @@ /** Provides the `Unit` class. */ -/** The unit type. */ -private newtype TUnit = TMkUnit() - -/** The trivial type with a single element. */ -class Unit extends TUnit { - /** Gets a textual representation of this element. */ - string toString() { result = "unit" } -} +import codeql.util.Unit diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlow.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlow.qll index 617362ab4f0..865d7b4d6ce 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlow.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlow.qll @@ -2,7 +2,7 @@ * Provides an implementation of global (interprocedural) data flow. This file * re-exports the local (intraprocedural) data flow analysis from * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Make` and `MakeWithState` modules. + * through the `Global` and `GlobalWithState` modules. */ private import DataFlowImplCommon @@ -73,10 +73,10 @@ signature module ConfigSig { */ default FlowFeature getAFeature() { none() } - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ default predicate sourceGrouping(Node source, string sourceGroup) { none() } - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ default predicate sinkGrouping(Node sink, string sinkGroup) { none() } /** @@ -166,10 +166,10 @@ signature module StateConfigSig { */ default FlowFeature getAFeature() { none() } - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ default predicate sourceGrouping(Node source, string sourceGroup) { none() } - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ default predicate sinkGrouping(Node sink, string sinkGroup) { none() } /** @@ -182,15 +182,15 @@ signature module StateConfigSig { } /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * Gets the exploration limit for `partialFlow` and `partialFlowRev` * measured in approximate number of interprocedural steps. */ signature int explorationLimitSig(); /** - * The output of a data flow computation. + * The output of a global data flow computation. */ -signature module DataFlowSig { +signature module GlobalFlowSig { /** * A `Node` augmented with a call context (except for sinks) and an access path. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. @@ -203,28 +203,28 @@ signature module DataFlowSig { * The corresponding paths are generated from the end-points and the graph * included in the module `PathGraph`. */ - predicate hasFlowPath(PathNode source, PathNode sink); + predicate flowPath(PathNode source, PathNode sink); /** * Holds if data can flow from `source` to `sink`. */ - predicate hasFlow(Node source, Node sink); + predicate flow(Node source, Node sink); /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowTo(Node sink); + predicate flowTo(Node sink); /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowToExpr(DataFlowExpr sink); + predicate flowToExpr(DataFlowExpr sink); } /** - * Constructs a standard data flow computation. + * Constructs a global data flow computation. */ -module Make<ConfigSig Config> implements DataFlowSig { +module Global<ConfigSig Config> implements GlobalFlowSig { private module C implements FullStateConfigSig { import DefaultState<Config> import Config @@ -233,10 +233,15 @@ module Make<ConfigSig Config> implements DataFlowSig { import Impl<C> } +/** DEPRECATED: Use `Global` instead. */ +deprecated module Make<ConfigSig Config> implements GlobalFlowSig { + import Global<Config> +} + /** - * Constructs a data flow computation using flow state. + * Constructs a global data flow computation using flow state. */ -module MakeWithState<StateConfigSig Config> implements DataFlowSig { +module GlobalWithState<StateConfigSig Config> implements GlobalFlowSig { private module C implements FullStateConfigSig { import Config } @@ -244,6 +249,11 @@ module MakeWithState<StateConfigSig Config> implements DataFlowSig { import Impl<C> } +/** DEPRECATED: Use `GlobalWithState` instead. */ +deprecated module MakeWithState<StateConfigSig Config> implements GlobalFlowSig { + import GlobalWithState<Config> +} + signature class PathNodeSig { /** Gets a textual representation of this element. */ string toString(); diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll index c47b0308855..6ea97954bdf 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -8,6 +8,7 @@ private import DataFlowImplCommon private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommonPublic +private import codeql.util.Unit import DataFlow /** @@ -91,10 +92,10 @@ signature module FullStateConfigSig { */ FlowFeature getAFeature(); - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ predicate sourceGrouping(Node source, string sourceGroup); - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ predicate sinkGrouping(Node sink, string sinkGroup); /** @@ -445,11 +446,7 @@ module Impl<FullStateConfigSig Config> { } private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } + class Ap = Unit; private class Cc = boolean; @@ -3633,7 +3630,7 @@ module Impl<FullStateConfigSig Config> { * The corresponding paths are generated from the end-points and the graph * included in the module `PathGraph`. */ - predicate hasFlowPath(PathNode source, PathNode sink) { + predicate flowPath(PathNode source, PathNode sink) { exists(PathNodeImpl flowsource, PathNodeImpl flowsink | source = flowsource and sink = flowsink | @@ -3643,6 +3640,9 @@ module Impl<FullStateConfigSig Config> { ) } + /** DEPRECATED: Use `flowPath` instead. */ + deprecated predicate hasFlowPath = flowPath/2; + private predicate flowsTo(PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink) { flowsource.isSource() and flowsource.getNodeEx().asNode() = source and @@ -3653,17 +3653,26 @@ module Impl<FullStateConfigSig Config> { /** * Holds if data can flow from `source` to `sink`. */ - predicate hasFlow(Node source, Node sink) { flowsTo(_, _, source, sink) } + predicate flow(Node source, Node sink) { flowsTo(_, _, source, sink) } + + /** DEPRECATED: Use `flow` instead. */ + deprecated predicate hasFlow = flow/2; /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + predicate flowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + + /** DEPRECATED: Use `flowTo` instead. */ + deprecated predicate hasFlowTo = flowTo/1; /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate flowToExpr(DataFlowExpr sink) { flowTo(exprNode(sink)) } + + /** DEPRECATED: Use `flowToExpr` instead. */ + deprecated predicate hasFlowToExpr = flowToExpr/1; private predicate finalStats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples @@ -4574,7 +4583,7 @@ module Impl<FullStateConfigSig Config> { * * To use this in a `path-problem` query, import the module `PartialPathGraph`. */ - predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { + predicate partialFlow(PartialPathNode source, PartialPathNode node, int dist) { partialFlow(source, node) and dist = node.getSourceDistance() } @@ -4594,7 +4603,7 @@ module Impl<FullStateConfigSig Config> { * Note that reverse flow has slightly lower precision than the corresponding * forward flow, as reverse flow disregards type pruning among other features. */ - predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { + predicate partialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { revPartialFlow(node, sink) and dist = node.getSinkDistance() } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll index e6bdc74cceb..be70086a93a 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl<Config> as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll index e6bdc74cceb..be70086a93a 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl<Config> as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll index e6bdc74cceb..be70086a93a 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl<Config> as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll index e6bdc74cceb..be70086a93a 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl<Config> as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll index d09fdcfca3e..e6fce328326 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll @@ -140,10 +140,8 @@ private module LambdaFlow { } pragma[nomagic] - private TReturnPositionSimple viableReturnPosLambda( - DataFlowCall call, DataFlowCallOption lastCall, ReturnKind kind - ) { - result = TReturnPositionSimple0(viableCallableLambda(call, lastCall), kind) + private TReturnPositionSimple viableReturnPosLambda(DataFlowCall call, ReturnKind kind) { + result = TReturnPositionSimple0(viableCallableLambda(call, _), kind) } private predicate viableReturnPosOutNonLambda( @@ -155,11 +153,12 @@ private module LambdaFlow { ) } + pragma[nomagic] private predicate viableReturnPosOutLambda( - DataFlowCall call, DataFlowCallOption lastCall, TReturnPositionSimple pos, OutNode out + DataFlowCall call, TReturnPositionSimple pos, OutNode out ) { exists(ReturnKind kind | - pos = viableReturnPosLambda(call, lastCall, kind) and + pos = viableReturnPosLambda(call, kind) and out = getAnOutNode(call, kind) ) } @@ -188,6 +187,7 @@ private module LambdaFlow { else any() } + pragma[assume_small_delta] pragma[nomagic] predicate revLambdaFlow0( DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn, @@ -274,6 +274,7 @@ private module LambdaFlow { ) } + pragma[assume_small_delta] pragma[nomagic] predicate revLambdaFlowOut( DataFlowCall lambdaCall, LambdaCallKind kind, TReturnPositionSimple pos, DataFlowType t, @@ -285,7 +286,7 @@ private module LambdaFlow { or // non-linear recursion revLambdaFlowOutLambdaCall(lambdaCall, kind, out, t, toJump, call, lastCall) and - viableReturnPosOutLambda(call, _, pos, out) + viableReturnPosOutLambda(call, pos, out) ) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplForRegExp.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplForRegExp.qll index e6bdc74cceb..be70086a93a 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplForRegExp.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplForRegExp.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl<Config> as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplSpecific.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplSpecific.qll index cdbd1eecb2c..8a7ecbcb565 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplSpecific.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplSpecific.qll @@ -7,9 +7,6 @@ private import python as Python module Private { import DataFlowPrivate - - // import DataFlowDispatch - class Unit = Python::Unit; } module Public { diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll index 478328d90bf..6665e0e7480 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll @@ -10,6 +10,7 @@ private import FlowSummaryImplSpecific private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommon +private import codeql.util.Unit /** Provides classes and predicates for defining flow summaries. */ module Public { @@ -109,6 +110,7 @@ module Public { } /** Gets the stack obtained by dropping the first `i` elements, if any. */ + pragma[assume_small_delta] SummaryComponentStack drop(int i) { i = 0 and result = this or diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll b/python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll index 7af9ca524aa..64ae4e50430 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/ImportResolution.qll @@ -65,31 +65,75 @@ private import semmle.python.dataflow.new.internal.DataFlowPrivate */ module ImportResolution { /** - * Holds if the module `m` defines a name `name` by assigning `defn` to it. This is an - * overapproximation, as `name` may not in fact be exported (e.g. by defining an `__all__` that does - * not include `name`). + * Holds if there is an ESSA step from `defFrom` to `defTo`, which should be allowed + * for import resolution. + */ + private predicate allowedEssaImportStep(EssaDefinition defFrom, EssaDefinition defTo) { + // to handle definitions guarded by if-then-else + defFrom = defTo.(PhiFunction).getAnInput() + or + // refined variable + // example: https://github.com/nvbn/thefuck/blob/ceeaeab94b5df5a4fe9d94d61e4f6b0bbea96378/thefuck/utils.py#L25-L45 + defFrom = defTo.(EssaNodeRefinement).getInput().getDefinition() + } + + /** + * Holds if the module `m` defines a name `name` with the value `val`. The value + * represents the value `name` will have at the end of the module (the last place we + * have def-use flow to). + * + * Note: The handling of re-exporting imports is a bit simplistic. We assume that if + * an import is made, it will be re-exported (which will not be the case if a new + * value is assigned to the name, or it is deleted). */ pragma[nomagic] - predicate module_export(Module m, string name, DataFlow::CfgNode defn) { - exists(EssaVariable v, EssaDefinition essaDef | - v.getName() = name and - v.getAUse() = ImportStar::getStarImported*(m).getANormalExit() and - ( - essaDef = v.getDefinition() - or - // to handle definitions guarded by if-then-else - essaDef = v.getDefinition().(PhiFunction).getAnInput() - ) + predicate module_export(Module m, string name, DataFlow::Node val) { + // Definitions made inside `m` itself + // + // for code such as `foo = ...; foo.bar = ...` there will be TWO + // EssaDefinition/EssaVariable. One for `foo = ...` (AssignmentDefinition) and one + // for `foo.bar = ...`. The one for `foo.bar = ...` (EssaNodeRefinement). The + // EssaNodeRefinement is the one that will reach the end of the module (normal + // exit). + // + // However, we cannot just use the EssaNodeRefinement as the `val`, because the + // normal data-flow depends on use-use flow, and use-use flow targets CFG nodes not + // EssaNodes. So we need to go back from the EssaDefinition/EssaVariable that + // reaches the end of the module, to the first definition of the variable, and then + // track forwards using use-use flow to find a suitable CFG node that has flow into + // it from use-use flow. + exists(EssaVariable lastUseVar, EssaVariable firstDef | + lastUseVar.getName() = name and + // we ignore special variable $ introduced by our analysis (not used for anything) + // we ignore special variable * introduced by `from <pkg> import *` -- TODO: understand why we even have this? + not name in ["$", "*"] and + lastUseVar.getAUse() = m.getANormalExit() and + allowedEssaImportStep*(firstDef, lastUseVar) and + not allowedEssaImportStep(_, firstDef) | - defn.getNode() = essaDef.(AssignmentDefinition).getValue() + not EssaFlow::defToFirstUse(firstDef, _) and + val.asVar() = firstDef or - defn.getNode() = essaDef.(ArgumentRefinement).getArgument() + exists(ControlFlowNode mid, ControlFlowNode end | + EssaFlow::defToFirstUse(firstDef, mid) and + EssaFlow::useToNextUse*(mid, end) and + not EssaFlow::useToNextUse(end, _) and + val.asCfgNode() = end + ) ) or + // re-exports from `from <pkg> import *` + exists(Module importedFrom | + importedFrom = ImportStar::getStarImported(m) and + module_export(importedFrom, name, val) and + potential_module_export(importedFrom, name) + ) + or + // re-exports from `import <pkg>` or `from <pkg> import <stuff>` exists(Alias a | - defn.asExpr() = [a.getValue(), a.getValue().(ImportMember).getModule()] and + val.asExpr() = a.getValue() and a.getAsname().(Name).getId() = name and - defn.getScope() = m + val.getScope() = m ) } @@ -263,9 +307,21 @@ module ImportResolution { module_reexport(reexporter, attr_name, m) ) or - // Submodules that are implicitly defined with relative imports of the form `from .foo import ...`. - // In practice, we create a definition for each module in a package, even if it is not imported. + // submodules of packages will be available as `<pkg>.<submodule>` after doing + // `import <pkg>.<submodule>` at least once in the program, or can be directly + // imported with `from <pkg> import <submodule>` (even with an empty + // `<pkg>.__init__` file). + // + // Until an import of `<pkg>.<submodule>` is executed, it is technically possible + // that `<pkg>.<submodule>` (or `from <pkg> import <submodule>`) can refer to an + // attribute set in `<pkg>.__init__`. + // + // Therefore, if there is an attribute defined in `<pkg>.__init__` with the same + // name as a submodule, we always consider that this attribute _could_ be a + // reference to the submodule, even if we don't know that the submodule has been + // imported yet. exists(string submodule, Module package | + submodule = result.asVar().getName() and SsaSource::init_module_submodule_defn(result.asVar().getSourceVariable(), package.getEntryNode()) and m = getModuleFromName(package.getPackageName() + "." + submodule) diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTracking.qll b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTracking.qll index 7f96fe5e6fb..872ac8d4cb8 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTracking.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTracking.qll @@ -33,9 +33,9 @@ private module AddTaintDefaults<DataFlowInternal::FullStateConfigSig Config> imp } /** - * Constructs a standard taint tracking computation. + * Constructs a global taint tracking computation. */ -module Make<DataFlow::ConfigSig Config> implements DataFlow::DataFlowSig { +module Global<DataFlow::ConfigSig Config> implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import DataFlowInternal::DefaultState<Config> import Config @@ -48,10 +48,15 @@ module Make<DataFlow::ConfigSig Config> implements DataFlow::DataFlowSig { import DataFlowInternal::Impl<C> } +/** DEPRECATED: Use `Global` instead. */ +deprecated module Make<DataFlow::ConfigSig Config> implements DataFlow::GlobalFlowSig { + import Global<Config> +} + /** - * Constructs a taint tracking computation using flow state. + * Constructs a global taint tracking computation using flow state. */ -module MakeWithState<DataFlow::StateConfigSig Config> implements DataFlow::DataFlowSig { +module GlobalWithState<DataFlow::StateConfigSig Config> implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import Config } @@ -62,3 +67,8 @@ module MakeWithState<DataFlow::StateConfigSig Config> implements DataFlow::DataF import DataFlowInternal::Impl<C> } + +/** DEPRECATED: Use `GlobalWithState` instead. */ +deprecated module MakeWithState<DataFlow::StateConfigSig Config> implements DataFlow::GlobalFlowSig { + import GlobalWithState<Config> +} diff --git a/python/ql/lib/semmle/python/frameworks/Aiomysql.qll b/python/ql/lib/semmle/python/frameworks/Aiomysql.qll index 3d43c13b91a..d5ac942506e 100644 --- a/python/ql/lib/semmle/python/frameworks/Aiomysql.qll +++ b/python/ql/lib/semmle/python/frameworks/Aiomysql.qll @@ -9,11 +9,10 @@ private import python private import semmle.python.dataflow.new.DataFlow private import semmle.python.Concepts private import semmle.python.ApiGraphs +private import semmle.python.frameworks.PEP249 /** Provides models for the `aiomysql` PyPI package. */ private module Aiomysql { - private import semmle.python.internal.Awaited - /** * Gets a `ConnectionPool` that is created when the result of `aiomysql.create_pool()` is awaited. * See https://aiomysql.readthedocs.io/en/stable/pool.html @@ -23,49 +22,29 @@ private module Aiomysql { } /** - * Gets a `Connection` that is created when + * A Connection that is created when * - the result of `aiomysql.connect()` is awaited. * - the result of calling `acquire` on a `ConnectionPool` is awaited. - * See https://aiomysql.readthedocs.io/en/stable/connection.html#connection + * See + * - https://aiomysql.readthedocs.io/en/stable/connection.html#connection + * - https://aiomysql.readthedocs.io/en/stable/pool.html#Pool.acquire */ - API::Node connection() { - result = API::moduleImport("aiomysql").getMember("connect").getReturn().getAwaited() - or - result = connectionPool().getMember("acquire").getReturn().getAwaited() + class AiomysqlConnection extends PEP249::AsyncDatabaseConnection { + AiomysqlConnection() { + this = API::moduleImport("aiomysql").getMember("connect").getReturn().getAwaited() + or + this = connectionPool().getMember("acquire").getReturn().getAwaited() + } } /** - * Gets a `Cursor` that is created when + * An additional cursor, that is created when * - the result of calling `cursor` on a `ConnectionPool` is awaited. - * - the result of calling `cursor` on a `Connection` is awaited. - * See https://aiomysql.readthedocs.io/en/stable/cursors.html + * See + * - https://aiomysql.readthedocs.io/en/stable/pool.html##Pool.cursor */ - API::Node cursor() { - result = connectionPool().getMember("cursor").getReturn().getAwaited() - or - result = connection().getMember("cursor").getReturn().getAwaited() - } - - /** - * A query. Calling `execute` on a `Cursor` constructs a query. - * See https://aiomysql.readthedocs.io/en/stable/cursors.html#Cursor.execute - */ - class CursorExecuteCall extends SqlConstruction::Range, API::CallNode { - CursorExecuteCall() { this = cursor().getMember("execute").getACall() } - - override DataFlow::Node getSql() { result = this.getParameter(0, "operation").asSink() } - } - - /** - * An awaited query. Awaiting the result of calling `execute` executes the query. - * See https://aiomysql.readthedocs.io/en/stable/cursors.html#Cursor.execute - */ - class AwaitedCursorExecuteCall extends SqlExecution::Range { - CursorExecuteCall executeCall; - - AwaitedCursorExecuteCall() { this = executeCall.getReturn().getAwaited().asSource() } - - override DataFlow::Node getSql() { result = executeCall.getSql() } + class AiomysqlCursor extends PEP249::AsyncDatabaseCursor { + AiomysqlCursor() { this = connectionPool().getMember("cursor").getReturn().getAwaited() } } /** diff --git a/python/ql/lib/semmle/python/frameworks/Aiopg.qll b/python/ql/lib/semmle/python/frameworks/Aiopg.qll index 979f7edb94f..e2fdfd1638d 100644 --- a/python/ql/lib/semmle/python/frameworks/Aiopg.qll +++ b/python/ql/lib/semmle/python/frameworks/Aiopg.qll @@ -9,11 +9,10 @@ private import python private import semmle.python.dataflow.new.DataFlow private import semmle.python.Concepts private import semmle.python.ApiGraphs +private import semmle.python.frameworks.PEP249 /** Provides models for the `aiopg` PyPI package. */ private module Aiopg { - private import semmle.python.internal.Awaited - /** * Gets a `ConnectionPool` that is created when the result of `aiopg.create_pool()` is awaited. * See https://aiopg.readthedocs.io/en/stable/core.html#pool @@ -23,49 +22,29 @@ private module Aiopg { } /** - * Gets a `Connection` that is created when + * A Connection that is created when * - the result of `aiopg.connect()` is awaited. * - the result of calling `acquire` on a `ConnectionPool` is awaited. - * See https://aiopg.readthedocs.io/en/stable/core.html#connection + * See + * - https://aiopg.readthedocs.io/en/stable/core.html#connection + * - https://aiopg.readthedocs.io/en/stable/core.html#aiopg.Pool.acquire */ - API::Node connection() { - result = API::moduleImport("aiopg").getMember("connect").getReturn().getAwaited() - or - result = connectionPool().getMember("acquire").getReturn().getAwaited() + class AiopgConnection extends PEP249::AsyncDatabaseConnection { + AiopgConnection() { + this = API::moduleImport("aiopg").getMember("connect").getReturn().getAwaited() + or + this = connectionPool().getMember("acquire").getReturn().getAwaited() + } } /** - * Gets a `Cursor` that is created when + * An additional cursor, that is created when * - the result of calling `cursor` on a `ConnectionPool` is awaited. - * - the result of calling `cursor` on a `Connection` is awaited. - * See https://aiopg.readthedocs.io/en/stable/core.html#cursor + * See + * - https://aiopg.readthedocs.io/en/stable/core.html#aiopg.Pool.cursor */ - API::Node cursor() { - result = connectionPool().getMember("cursor").getReturn().getAwaited() - or - result = connection().getMember("cursor").getReturn().getAwaited() - } - - /** - * A query. Calling `execute` on a `Cursor` constructs a query. - * See https://aiopg.readthedocs.io/en/stable/core.html#aiopg.Cursor.execute - */ - class CursorExecuteCall extends SqlConstruction::Range, API::CallNode { - CursorExecuteCall() { this = cursor().getMember("execute").getACall() } - - override DataFlow::Node getSql() { result = this.getParameter(0, "operation").asSink() } - } - - /** - * An awaited query. Awaiting the result of calling `execute` executes the query. - * See https://aiopg.readthedocs.io/en/stable/core.html#aiopg.Cursor.execute - */ - class AwaitedCursorExecuteCall extends SqlExecution::Range { - CursorExecuteCall execute; - - AwaitedCursorExecuteCall() { this = execute.getReturn().getAwaited().asSource() } - - override DataFlow::Node getSql() { result = execute.getSql() } + class AiopgCursor extends PEP249::AsyncDatabaseCursor { + AiopgCursor() { this = connectionPool().getMember("cursor").getReturn().getAwaited() } } /** diff --git a/python/ql/lib/semmle/python/frameworks/Aiosqlite.qll b/python/ql/lib/semmle/python/frameworks/Aiosqlite.qll new file mode 100644 index 00000000000..842459e1c36 --- /dev/null +++ b/python/ql/lib/semmle/python/frameworks/Aiosqlite.qll @@ -0,0 +1,39 @@ +/** + * Provides classes modeling security-relevant aspects of the `aiosqlite` PyPI package. + * See + * - https://pypi.org/project/aiosqlite/ + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.Concepts +private import semmle.python.ApiGraphs +private import semmle.python.frameworks.PEP249 + +/** Provides models for the `aiosqlite` PyPI package. */ +private module Aiosqlite { + /** + * A model of `aiosqlite` as a module that implements PEP 249 using asyncio, providing + * ways to execute SQL statements against a database. + */ + class AiosqlitePEP249 extends PEP249::AsyncPEP249ModuleApiNode { + AiosqlitePEP249() { this = API::moduleImport("aiosqlite") } + } + + /** + * An additional cursor, that is return from the coroutine Connection.execute, + * see https://aiosqlite.omnilib.dev/en/latest/api.html#aiosqlite.Connection.execute + */ + class AiosqliteCursor extends PEP249::AsyncDatabaseCursor { + AiosqliteCursor() { + this = + API::moduleImport("aiosqlite") + .getMember("connect") + .getReturn() + .getAwaited() + .getMember("execute") + .getReturn() + .getAwaited() + } + } +} diff --git a/python/ql/lib/semmle/python/frameworks/Asyncpg.qll b/python/ql/lib/semmle/python/frameworks/Asyncpg.qll index 259699eeb0e..8542d04ab14 100644 --- a/python/ql/lib/semmle/python/frameworks/Asyncpg.qll +++ b/python/ql/lib/semmle/python/frameworks/Asyncpg.qll @@ -22,6 +22,7 @@ private module Asyncpg { // * - the result of `asyncpg.connect()` is awaited. // * - the result of calling `acquire` on a `ConnectionPool` is awaited. "asyncpg.Connection;asyncpg;Member[connect].ReturnValue.Awaited", + "asyncpg.Connection;asyncpg;Member[connection].Member[connect].ReturnValue.Awaited", "asyncpg.Connection;asyncpg.ConnectionPool;Member[acquire].ReturnValue.Awaited", // Creating an internal `~Connection` type that contains both `Connection` and `ConnectionPool`. "asyncpg.~Connection;asyncpg.Connection;", // diff --git a/python/ql/lib/semmle/python/frameworks/CassandraDriver.qll b/python/ql/lib/semmle/python/frameworks/CassandraDriver.qll new file mode 100644 index 00000000000..93fc9723b2e --- /dev/null +++ b/python/ql/lib/semmle/python/frameworks/CassandraDriver.qll @@ -0,0 +1,61 @@ +/** + * Provides classes modeling security-relevant aspects of the `cassandra-driver` PyPI package. + * See https://pypi.org/project/cassandra-driver/ + */ + +private import python +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.Concepts +private import semmle.python.ApiGraphs +private import semmle.python.frameworks.PEP249 + +/** + * Provides models for the `cassandra-driver` PyPI package. + * See https://pypi.org/project/cassandra-driver/ + */ +private module CassandraDriver { + /** + * A cassandra cluster session. + * + * see + * - https://docs.datastax.com/en/developer/python-driver/3.25/api/cassandra/cluster/#cassandra.cluster.Cluster.connect + * - https://docs.datastax.com/en/developer/python-driver/3.25/api/cassandra/cluster/#cassandra.cluster.Session + */ + API::Node session() { + result = + API::moduleImport("cassandra") + .getMember("cluster") + .getMember("Cluster") + .getReturn() + .getMember("connect") + .getReturn() + } + + /** + * see https://docs.datastax.com/en/developer/python-driver/3.25/api/cassandra/cluster/#cassandra.cluster.Session.execute + */ + class CassandraSessionExecuteCall extends SqlExecution::Range, API::CallNode { + CassandraSessionExecuteCall() { this = session().getMember("execute").getACall() } + + override DataFlow::Node getSql() { result = this.getParameter(0, "query").asSink() } + } + + /** + * see https://docs.datastax.com/en/developer/python-driver/3.25/api/cassandra/cluster/#cassandra.cluster.Session.execute_async + */ + class CassandraSessionExecuteAsyncCall extends SqlConstruction::Range, API::CallNode { + CassandraSessionExecuteAsyncCall() { this = session().getMember("execute_async").getACall() } + + override DataFlow::Node getSql() { result = this.getParameter(0, "query").asSink() } + } + + /** + * see https://docs.datastax.com/en/developer/python-driver/3.25/api/cassandra/cluster/#cassandra.cluster.Session.prepare + */ + class CassandraSessionPrepareCall extends SqlConstruction::Range, API::CallNode { + CassandraSessionPrepareCall() { this = session().getMember("prepare").getACall() } + + override DataFlow::Node getSql() { result = this.getParameter(0, "query").asSink() } + } +} diff --git a/python/ql/lib/semmle/python/frameworks/Django.qll b/python/ql/lib/semmle/python/frameworks/Django.qll index f1300c34a6e..c656ee85fda 100644 --- a/python/ql/lib/semmle/python/frameworks/Django.qll +++ b/python/ql/lib/semmle/python/frameworks/Django.qll @@ -561,8 +561,8 @@ module PrivateDjango { API::Node connection() { result = db().getMember("connection") } /** A `django.db.connection` is a PEP249 compliant DB connection. */ - class DjangoDbConnection extends PEP249::Connection::InstanceSource { - DjangoDbConnection() { this = connection().asSource() } + class DjangoDbConnection extends PEP249::DatabaseConnection { + DjangoDbConnection() { this = connection() } } // ------------------------------------------------------------------------- diff --git a/python/ql/lib/semmle/python/frameworks/PEP249.qll b/python/ql/lib/semmle/python/frameworks/PEP249.qll index 594c3e938e2..2425f4514f8 100644 --- a/python/ql/lib/semmle/python/frameworks/PEP249.qll +++ b/python/ql/lib/semmle/python/frameworks/PEP249.qll @@ -22,6 +22,148 @@ module PEP249 { override string toString() { result = this.(API::Node).toString() } } + /** + * An API graph node representing a database connection. + */ + abstract class DatabaseConnection extends API::Node { + /** Gets a string representation of this element. */ + override string toString() { result = this.(API::Node).toString() } + } + + private class DefaultDatabaseConnection extends DatabaseConnection { + DefaultDatabaseConnection() { + this = any(PEP249ModuleApiNode mod).getMember("connect").getReturn() + } + } + + /** + * An API graph node representing a database cursor. + */ + abstract class DatabaseCursor extends API::Node { + /** Gets a string representation of this element. */ + override string toString() { result = this.(API::Node).toString() } + } + + private class DefaultDatabaseCursor extends DatabaseCursor { + DefaultDatabaseCursor() { this = any(DatabaseConnection conn).getMember("cursor").getReturn() } + } + + private string getSqlKwargName() { + result in ["sql", "statement", "operation", "query", "query_string", "sql_script"] + } + + private string getExecuteMethodName() { + result in ["execute", "executemany", "executescript", "execute_insert", "execute_fetchall"] + } + + /** + * A call to an execute method on a database cursor or a connection, such as `execute` + * or `executemany`. + * + * See + * - https://peps.python.org/pep-0249/#execute + * - https://peps.python.org/pep-0249/#executemany + * + * Note: While `execute` method on a connection is not part of PEP249, if it is used, we + * recognize it as an alias for constructing a cursor and calling `execute` on it. + */ + private class ExecuteMethodCall extends SqlExecution::Range, API::CallNode { + ExecuteMethodCall() { + exists(API::Node start | + start instanceof DatabaseCursor or start instanceof DatabaseConnection + | + this = start.getMember(getExecuteMethodName()).getACall() + ) + } + + override DataFlow::Node getSql() { + result in [this.getArg(0), this.getArgByName(getSqlKwargName()),] + } + } + + // --------------------------------------------------------------------------- + // asyncio implementations + // --------------------------------------------------------------------------- + // + // we differentiate between normal and asyncio implementations, since we model the + // `execute` call differently -- as a SqlExecution vs SqlConstruction, since the SQL + // is only executed in asyncio after being awaited (which might happen in something + // like `asyncio.gather`) + /** + * An API graph node representing a module that implements PEP 249 using asyncio. + */ + abstract class AsyncPEP249ModuleApiNode extends API::Node { + /** Gets a string representation of this element. */ + override string toString() { result = this.(API::Node).toString() } + } + + /** + * An API graph node representing a asyncio database connection (after being awaited). + */ + abstract class AsyncDatabaseConnection extends API::Node { + /** Gets a string representation of this element. */ + override string toString() { result = this.(API::Node).toString() } + } + + private class DefaultAsyncDatabaseConnection extends AsyncDatabaseConnection { + DefaultAsyncDatabaseConnection() { + this = any(AsyncPEP249ModuleApiNode mod).getMember("connect").getReturn().getAwaited() + } + } + + /** + * An API graph node representing a asyncio database cursor (after being awaited). + */ + abstract class AsyncDatabaseCursor extends API::Node { + /** Gets a string representation of this element. */ + override string toString() { result = this.(API::Node).toString() } + } + + private class DefaultAsyncDatabaseCursor extends AsyncDatabaseCursor { + DefaultAsyncDatabaseCursor() { + this = any(AsyncDatabaseConnection conn).getMember("cursor").getReturn().getAwaited() + } + } + + /** + * A call to an execute method on an asyncio database cursor or an asyncio connection, + * such as `execute` or `executemany`. + * + * (This is not an SqlExecution, since that only happens when the coroutine is + * awaited) + * + * See ExecuteMethodCall for more details. + */ + private class AsyncExecuteMethodCall extends SqlConstruction::Range, API::CallNode { + AsyncExecuteMethodCall() { + exists(API::Node start | + start instanceof AsyncDatabaseCursor or start instanceof AsyncDatabaseConnection + | + this = start.getMember(getExecuteMethodName()).getACall() + ) + } + + override DataFlow::Node getSql() { + result in [this.getArg(0), this.getArgByName(getSqlKwargName()),] + } + } + + /** Actual execution of the AsyncExecuteMethodCall coroutine. */ + private class AwaitedAsyncExecuteMethodCall extends SqlExecution::Range { + AsyncExecuteMethodCall execute; + + AwaitedAsyncExecuteMethodCall() { this = execute.getReturn().getAwaited().asSource() } + + override DataFlow::Node getSql() { result = execute.getSql() } + } + + // --------------------------------------------------------------------------- + // old impl + // --------------------------------------------------------------------------- + // the goal is to deprecate it in favour of the API graph version, but currently this + // requires a rewrite of the Peewee modeling, which depends on rewriting the + // instance/instance-source stuff to use API graphs instead. + // so is postponed for now. /** Gets a reference to the `connect` function of a module that implements PEP 249. */ DataFlow::Node connect() { result = any(PEP249ModuleApiNode a).getMember("connect").getAValueReachableFromSource() @@ -147,7 +289,10 @@ module PEP249 { * recognize it as an alias for constructing a cursor and calling `execute` on it. */ private class ExecuteCall extends SqlExecution::Range, DataFlow::CallCfgNode { - ExecuteCall() { this.getFunction() = execute() } + ExecuteCall() { + this.getFunction() = execute() and + not this instanceof ExecuteMethodCall + } override DataFlow::Node getSql() { result in [this.getArg(0), this.getArgByName("sql")] } } @@ -170,8 +315,13 @@ module PEP249 { * recognize it as an alias for constructing a cursor and calling `executemany` on it. */ private class ExecutemanyCall extends SqlExecution::Range, DataFlow::CallCfgNode { - ExecutemanyCall() { this.getFunction() = executemany() } + ExecutemanyCall() { + this.getFunction() = executemany() and + not this instanceof ExecuteMethodCall + } - override DataFlow::Node getSql() { result in [this.getArg(0), this.getArgByName("sql")] } + override DataFlow::Node getSql() { + result in [this.getArg(0), this.getArgByName(getSqlKwargName())] + } } } diff --git a/python/ql/lib/semmle/python/frameworks/Peewee.qll b/python/ql/lib/semmle/python/frameworks/Peewee.qll index 1179371be76..f923b463b3e 100644 --- a/python/ql/lib/semmle/python/frameworks/Peewee.qll +++ b/python/ql/lib/semmle/python/frameworks/Peewee.qll @@ -163,11 +163,9 @@ private module Peewee { * A call to the `connection` method on a `peewee.Database` instance. * https://docs.peewee-orm.com/en/latest/peewee/api.html#Database.connection. */ - class PeeweeDatabaseConnectionCall extends PEP249::Connection::InstanceSource, - DataFlow::CallCfgNode - { + class PeeweeDatabaseConnectionCall extends PEP249::DatabaseConnection { PeeweeDatabaseConnectionCall() { - this = Database::instance().getMember("connection").getACall() + this = Database::instance().getMember("connection").getReturn() } } @@ -175,8 +173,8 @@ private module Peewee { * A call to the `cursor` method on a `peewee.Database` instance. * https://docs.peewee-orm.com/en/latest/peewee/api.html#Database.cursor. */ - class PeeweeDatabaseCursorCall extends PEP249::Cursor::InstanceSource, DataFlow::CallCfgNode { - PeeweeDatabaseCursorCall() { this = Database::instance().getMember("cursor").getACall() } + class PeeweeDatabaseCursorCall extends PEP249::DatabaseCursor { + PeeweeDatabaseCursorCall() { this = Database::instance().getMember("cursor").getReturn() } } /** diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index e559d669248..e79aa270945 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -2435,9 +2435,14 @@ private module StdlibPrivate { * against a database. * * See https://devdocs.io/python~3.9/library/sqlite3 + * https://github.com/python/cpython/blob/3.11/Lib/sqlite3/dbapi2.py */ class Sqlite3 extends PEP249::PEP249ModuleApiNode { - Sqlite3() { this = API::moduleImport("sqlite3") } + Sqlite3() { + this = API::moduleImport("sqlite3") + or + this = API::moduleImport("sqlite3").getMember("dbapi2") + } } // --------------------------------------------------------------------------- diff --git a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll index 1b7e8cb326a..227f4ea22fb 100644 --- a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll +++ b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll @@ -63,10 +63,9 @@ * the type is not intended to match a static type. */ +private import codeql.util.Unit private import ApiGraphModelsSpecific as Specific -private class Unit = Specific::Unit; - private module API = Specific::API; private module DataFlow = Specific::DataFlow; diff --git a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsSpecific.qll b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsSpecific.qll index eb23efe4aff..38a1198193e 100644 --- a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsSpecific.qll +++ b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsSpecific.qll @@ -22,9 +22,6 @@ private import python as PY private import ApiGraphModels import semmle.python.ApiGraphs::API as API - -class Unit = PY::Unit; - // Re-export libraries needed by ApiGraphModels.qll import semmle.python.dataflow.new.internal.AccessPathSyntax as AccessPathSyntax import semmle.python.dataflow.new.DataFlow::DataFlow as DataFlow diff --git a/python/ql/src/Expressions/IncorrectComparisonUsingIs.ql b/python/ql/src/Expressions/IncorrectComparisonUsingIs.ql index 5352dc9c9fa..aab2ba6bfa1 100644 --- a/python/ql/src/Expressions/IncorrectComparisonUsingIs.ql +++ b/python/ql/src/Expressions/IncorrectComparisonUsingIs.ql @@ -11,16 +11,57 @@ */ import python -import IsComparisons -from Compare comp, Cmpop op, ClassValue c, string alt -where - invalid_portable_is_comparison(comp, op, c) and - not cpython_interned_constant(comp.getASubExpression()) and - ( - op instanceof Is and alt = "==" +/** Holds if the comparison `comp` uses `is` or `is not` (represented as `op`) to compare its `left` and `right` arguments. */ +predicate comparison_using_is(Compare comp, ControlFlowNode left, Cmpop op, ControlFlowNode right) { + exists(CompareNode fcomp | fcomp = comp.getAFlowNode() | + fcomp.operands(left, op, right) and + (op instanceof Is or op instanceof IsNot) + ) +} + +private predicate cpython_interned_value(Expr e) { + exists(string text | text = e.(StrConst).getText() | + text.length() = 0 or - op instanceof IsNot and alt = "!=" + text.length() = 1 and text.regexpMatch("[U+0000-U+00ff]") + ) + or + exists(int i | i = e.(IntegerLiteral).getN().toInt() | -5 <= i and i <= 256) + or + exists(Tuple t | t = e and not exists(t.getAnElt())) +} + +predicate uninterned_literal(Expr e) { + ( + e instanceof StrConst + or + e instanceof IntegerLiteral + or + e instanceof FloatLiteral + or + e instanceof Dict + or + e instanceof List + or + e instanceof Tuple + ) and + not cpython_interned_value(e) +} + +from Compare comp, Cmpop op, string alt +where + exists(ControlFlowNode left, ControlFlowNode right | + comparison_using_is(comp, left, op, right) and + ( + op instanceof Is and alt = "==" + or + op instanceof IsNot and alt = "!=" + ) + | + uninterned_literal(left.getNode()) + or + uninterned_literal(right.getNode()) ) select comp, "Values compared using '" + op.getSymbol() + diff --git a/python/ql/src/Security/CWE-327/FluentApiModel.qll b/python/ql/src/Security/CWE-327/FluentApiModel.qll index 3f479bc1627..ce62a1a590c 100644 --- a/python/ql/src/Security/CWE-327/FluentApiModel.qll +++ b/python/ql/src/Security/CWE-327/FluentApiModel.qll @@ -4,23 +4,18 @@ import TlsLibraryModel /** * Configuration to determine the state of a context being used to create - * a connection. There is one configuration for each pair of `TlsLibrary` and `ProtocolVersion`, - * such that a single configuration only tracks contexts where a specific `ProtocolVersion` is allowed. + * a connection. The configuration uses a flow state to track the `TlsLibrary` + * and the insecure `ProtocolVersion`s that are allowed. * * The state is in terms of whether a specific protocol is allowed. This is * either true or false when the context is created and can then be modified - * later by either restricting or unrestricting the protocol (see the predicates - * `isRestriction` and `isUnrestriction`). + * later by either restricting or unrestricting the protocol (see the predicate + * `isAdditionalFlowStep`). * - * Since we are interested in the final state, we want the flow to start from - * the last unrestriction, so we disallow flow into unrestrictions. We also - * model the creation as an unrestriction of everything it allows, to account - * for the common case where the creation plays the role of "last unrestriction". - * - * Since we really want "the last unrestriction, not nullified by a restriction", - * we also disallow flow into restrictions. + * The state is represented as a bit vector, where each bit corresponds to a + * protocol version. The bit is set if the protocol is allowed. */ -module InsecureContextConfiguration2 implements DataFlow::StateConfigSig { +module InsecureContextConfiguration implements DataFlow::StateConfigSig { private newtype TFlowState = TMkFlowState(TlsLibrary library, int bits) { bits in [0 .. max(any(ProtocolVersion v).getBit()) * 2 - 1] @@ -61,9 +56,14 @@ module InsecureContextConfiguration2 implements DataFlow::StateConfigSig { } predicate isSource(DataFlow::Node source, FlowState state) { - exists(ProtocolFamily family | - source = state.getLibrary().unspecific_context_creation(family) and - state.getBits() = family.getBits() + exists(ContextCreation creation | source = creation | + creation = state.getLibrary().unspecific_context_creation() and + state.getBits() = + sum(ProtocolVersion version | + version = creation.getProtocol() and version.isInsecure() + | + version.getBit() + ) ) } @@ -112,7 +112,7 @@ module InsecureContextConfiguration2 implements DataFlow::StateConfigSig { } } -private module InsecureContextFlow = DataFlow::MakeWithState<InsecureContextConfiguration2>; +private module InsecureContextFlow = DataFlow::GlobalWithState<InsecureContextConfiguration>; /** * Holds if `conectionCreation` marks the creation of a connection based on the contex @@ -127,7 +127,7 @@ predicate unsafe_connection_creation_with_context( ) { // Connection created from a context allowing `insecure_version`. exists(InsecureContextFlow::PathNode src, InsecureContextFlow::PathNode sink | - InsecureContextFlow::hasFlowPath(src, sink) and + InsecureContextFlow::flowPath(src, sink) and src.getNode() = contextOrigin and sink.getNode() = connectionCreation and sink.getState().allowsInsecureVersion(insecure_version) and diff --git a/python/ql/src/Security/CWE-327/PyOpenSSL.qll b/python/ql/src/Security/CWE-327/PyOpenSSL.qll index b2052ff5d05..e2571195bfa 100644 --- a/python/ql/src/Security/CWE-327/PyOpenSSL.qll +++ b/python/ql/src/Security/CWE-327/PyOpenSSL.qll @@ -12,14 +12,14 @@ class PyOpenSslContextCreation extends ContextCreation, DataFlow::CallCfgNode { this = API::moduleImport("OpenSSL").getMember("SSL").getMember("Context").getACall() } - override string getProtocol() { + override ProtocolVersion getProtocol() { exists(DataFlow::Node protocolArg, PyOpenSsl pyo | protocolArg in [this.getArg(0), this.getArgByName("method")] | - protocolArg in [ - pyo.specific_version(result).getAValueReachableFromSource(), - pyo.unspecific_version(result).getAValueReachableFromSource() - ] + protocolArg = pyo.specific_version(result).getAValueReachableFromSource() + or + protocolArg = pyo.unspecific_version().getAValueReachableFromSource() and + result = any(ProtocolVersion pv) ) } } @@ -51,19 +51,23 @@ class SetOptionsCall extends ProtocolRestriction, DataFlow::CallCfgNode { } } -class UnspecificPyOpenSslContextCreation extends PyOpenSslContextCreation, UnspecificContextCreation -{ - // UnspecificPyOpenSslContextCreation() { library instanceof PyOpenSsl } -} - class PyOpenSsl extends TlsLibrary { PyOpenSsl() { this = "pyOpenSSL" } override string specific_version_name(ProtocolVersion version) { result = version + "_METHOD" } - override string unspecific_version_name(ProtocolFamily family) { - // `"TLS_METHOD"` is not actually available in pyOpenSSL yet, but should be coming soon.. - result = family + "_METHOD" + override string unspecific_version_name() { + // See + // - https://www.pyopenssl.org/en/23.0.0/api/ssl.html#module-OpenSSL.SSL + // - https://www.openssl.org/docs/manmaster/man3/DTLS_server_method.html#NOTES + // + // PyOpenSSL also allows DTLS + // see https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.Context + // although they are not mentioned here: + // https://www.pyopenssl.org/en/stable/api/ssl.html#OpenSSL.SSL.TLS_METHOD + result = ["TLS", "SSLv23"] + "_METHOD" + or + result = "TLS_" + ["CLIENT", "SERVER"] + "_METHOD" } override API::Node version_constants() { result = API::moduleImport("OpenSSL").getMember("SSL") } @@ -80,7 +84,5 @@ class PyOpenSsl extends TlsLibrary { override ProtocolRestriction protocol_restriction() { result instanceof SetOptionsCall } - override ProtocolUnrestriction protocol_unrestriction() { - result instanceof UnspecificPyOpenSslContextCreation - } + override ProtocolUnrestriction protocol_unrestriction() { none() } } diff --git a/python/ql/src/Security/CWE-327/Ssl.qll b/python/ql/src/Security/CWE-327/Ssl.qll index 0f2ce77acc7..c3fd0366436 100644 --- a/python/ql/src/Security/CWE-327/Ssl.qll +++ b/python/ql/src/Security/CWE-327/Ssl.qll @@ -10,20 +10,21 @@ import TlsLibraryModel class SslContextCreation extends ContextCreation, DataFlow::CallCfgNode { SslContextCreation() { this = API::moduleImport("ssl").getMember("SSLContext").getACall() } - override string getProtocol() { + override ProtocolVersion getProtocol() { exists(DataFlow::Node protocolArg, Ssl ssl | protocolArg in [this.getArg(0), this.getArgByName("protocol")] | - protocolArg = - [ - ssl.specific_version(result).getAValueReachableFromSource(), - ssl.unspecific_version(result).getAValueReachableFromSource() - ] + protocolArg = ssl.specific_version(result).getAValueReachableFromSource() + or + protocolArg = ssl.unspecific_version().getAValueReachableFromSource() and + // see https://docs.python.org/3/library/ssl.html#id7 + result in ["TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"] ) or not exists(this.getArg(_)) and not exists(this.getArgByName(_)) and - result = "TLS" + // see https://docs.python.org/3/library/ssl.html#id7 + result in ["TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"] } } @@ -34,7 +35,7 @@ class SslDefaultContextCreation extends ContextCreation { // Allowed insecure versions are "TLSv1" and "TLSv1_1" // see https://docs.python.org/3/library/ssl.html#context-creation - override string getProtocol() { result = "TLS" } + override ProtocolVersion getProtocol() { result in ["TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"] } } /** Gets a reference to an `ssl.Context` instance. */ @@ -161,33 +162,29 @@ class ContextSetVersion extends ProtocolRestriction, ProtocolUnrestriction, Data } } -class UnspecificSslContextCreation extends SslContextCreation, UnspecificContextCreation { - // UnspecificSslContextCreation() { library instanceof Ssl } - // override ProtocolVersion getUnrestriction() { - // result = UnspecificContextCreation.super.getUnrestriction() and - // // These are turned off by default since Python 3.6 - // // see https://docs.python.org/3.6/library/ssl.html#ssl.SSLContext - // not result in ["SSLv2", "SSLv3"] - // } -} - -class UnspecificSslDefaultContextCreation extends SslDefaultContextCreation { - // override DataFlow::Node getContext() { result = this } - // // see https://docs.python.org/3/library/ssl.html#ssl.create_default_context - // override ProtocolVersion getUnrestriction() { - // result in ["TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"] - // } -} - +// class UnspecificSslContextCreation extends SslContextCreation, UnspecificContextCreation { +// // UnspecificSslContextCreation() { library instanceof Ssl } +// override ProtocolVersion getProtocol() { +// result = UnspecificContextCreation.super.getProtocol() and +// // These are turned off by default since Python 3.6 +// // see https://docs.python.org/3.6/library/ssl.html#ssl.SSLContext +// not result in ["SSLv2", "SSLv3"] +// } +// } +// class UnspecificSslDefaultContextCreation extends SslDefaultContextCreation { +// // override DataFlow::Node getContext() { result = this } +// // see https://docs.python.org/3/library/ssl.html#ssl.create_default_context +// override ProtocolVersion getProtocol() { result in ["TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"] } +// } class Ssl extends TlsLibrary { Ssl() { this = "ssl" } override string specific_version_name(ProtocolVersion version) { result = "PROTOCOL_" + version } - override string unspecific_version_name(ProtocolFamily family) { - family = "SSLv23" and result = "PROTOCOL_" + family + override string unspecific_version_name() { + result = "PROTOCOL_SSLv23" or - family = "TLS" and result = "PROTOCOL_" + family + ["", "_CLIENT", "_SERVER"] + result = "PROTOCOL_TLS" + ["", "_CLIENT", "_SERVER"] } override API::Node version_constants() { result = API::moduleImport("ssl") } @@ -217,9 +214,5 @@ class Ssl extends TlsLibrary { result instanceof OptionsAugAndNot or result instanceof ContextSetVersion - or - result instanceof UnspecificSslContextCreation - or - result instanceof UnspecificSslDefaultContextCreation } } diff --git a/python/ql/src/Security/CWE-327/TlsLibraryModel.qll b/python/ql/src/Security/CWE-327/TlsLibraryModel.qll index b45fa24a870..1e99755c1a9 100644 --- a/python/ql/src/Security/CWE-327/TlsLibraryModel.qll +++ b/python/ql/src/Security/CWE-327/TlsLibraryModel.qll @@ -37,29 +37,23 @@ class ProtocolVersion extends string { or this = "TLSv1_3" and result = 32 } - - /** Gets the protocol family for this protocol version. */ - ProtocolFamily getFamily() { - result = "SSLv23" and this in ["SSLv2", "SSLv3"] - or - result = "TLS" and this in ["TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"] - } -} - -/** An unspecific protocol version */ -class ProtocolFamily extends string { - ProtocolFamily() { this in ["SSLv23", "TLS"] } - - /** Gets the bit mask for this protocol family. */ - int getBits() { - result = sum(ProtocolVersion version | version.getFamily() = this | version.getBit()) - } } /** The creation of a context. */ abstract class ContextCreation extends DataFlow::Node { - /** Gets the protocol version or family for this context. */ - abstract string getProtocol(); + /** + * Gets the protocol version for this context. + * There can be multiple values if the context was created + * using a non-specific version such as `TLS`. + */ + abstract ProtocolVersion getProtocol(); + + /** + * Holds if the context was created with a specific version + * rather than with a version flexible method, see: + * https://www.openssl.org/docs/manmaster/man3/DTLS_server_method.html#NOTES + */ + predicate specificVersion() { count(this.getProtocol()) = 1 } } /** The creation of a connection from a context. */ @@ -91,13 +85,12 @@ abstract class ProtocolUnrestriction extends DataFlow::Node { * This also serves as unrestricting these protocols. */ abstract class UnspecificContextCreation extends ContextCreation { - // override ProtocolVersion getUnrestriction() { - // // There is only one family, the two names are aliases in OpenSSL. - // // see https://github.com/openssl/openssl/blob/13888e797c5a3193e91d71e5f5a196a2d68d266f/include/openssl/ssl.h.in#L1953-L1955 - // family in ["SSLv23", "TLS"] and - // // see https://docs.python.org/3/library/ssl.html#ssl-contexts - // result in ["SSLv2", "SSLv3", "TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"] - // } + override ProtocolVersion getProtocol() { + // There is only one family, the two names are aliases in OpenSSL. + // see https://github.com/openssl/openssl/blob/13888e797c5a3193e91d71e5f5a196a2d68d266f/include/openssl/ssl.h.in#L1953-L1955 + // see https://docs.python.org/3/library/ssl.html#ssl-contexts + result in ["SSLv2", "SSLv3", "TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"] + } } /** A model of a SSL/TLS library. */ @@ -108,8 +101,8 @@ abstract class TlsLibrary extends string { /** Gets the name of a specific protocol version. */ abstract string specific_version_name(ProtocolVersion version); - /** Gets a name, which is a member of `version_constants`, that can be used to specify the protocol family `family`. */ - abstract string unspecific_version_name(ProtocolFamily family); + /** Gets a name, which is a member of `version_constants`, that can be used to specify the entire protocol family. */ + abstract string unspecific_version_name(); /** Gets an API node representing the module or class holding the version constants. */ abstract API::Node version_constants(); @@ -119,9 +112,9 @@ abstract class TlsLibrary extends string { result = this.version_constants().getMember(this.specific_version_name(version)) } - /** Gets an API node representing the protocol family `family`. */ - API::Node unspecific_version(ProtocolFamily family) { - result = this.version_constants().getMember(this.unspecific_version_name(family)) + /** Gets an API node representing the protocol entire family. */ + API::Node unspecific_version() { + result = this.version_constants().getMember(this.unspecific_version_name()) } /** Gets a creation of a context with a default protocol. */ @@ -133,14 +126,15 @@ abstract class TlsLibrary extends string { /** Gets a creation of a context with a specific protocol version, known to be insecure. */ ContextCreation insecure_context_creation(ProtocolVersion version) { result in [this.specific_context_creation(), this.default_context_creation()] and + result.specificVersion() and result.getProtocol() = version and version.isInsecure() } /** Gets a context that was created using `family`, known to have insecure instances. */ - ContextCreation unspecific_context_creation(ProtocolFamily family) { + ContextCreation unspecific_context_creation() { result in [this.specific_context_creation(), this.default_context_creation()] and - result.getProtocol() = family + not result.specificVersion() } /** Gets a dataflow node representing a connection being created in an insecure manner, not from a context. */ diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.qhelp b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.qhelp new file mode 100644 index 00000000000..37b803553d8 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.qhelp @@ -0,0 +1,4 @@ +<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd"> +<qhelp> +<include src="TimingAttackAgainstHash.qhelp" /> +</qhelp> diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql new file mode 100644 index 00000000000..f46b93fb266 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql @@ -0,0 +1,37 @@ +/** + * @name Timing attack against Hash + * @description When checking a Hash over a message, a constant-time algorithm should be used. + * Otherwise, an attacker may be able to forge a valid Hash for an arbitrary message + * by running a timing attack if they can send to the validation procedure. + * A successful attack can result in authentication bypass. + * @kind path-problem + * @problem.severity error + * @precision low + * @id py/possible-timing-attack-against-hash + * @tags security + * external/cwe/cwe-208 + * experimental + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import experimental.semmle.python.security.TimingAttack +import DataFlow::PathGraph + +/** + * A configuration that tracks data flow from cryptographic operations + * to equality test + */ +class PossibleTimingAttackAgainstHash extends TaintTracking::Configuration { + PossibleTimingAttackAgainstHash() { this = "PossibleTimingAttackAgainstHash" } + + override predicate isSource(DataFlow::Node source) { source instanceof ProduceCryptoCall } + + override predicate isSink(DataFlow::Node sink) { sink instanceof NonConstantTimeComparisonSink } +} + +from PossibleTimingAttackAgainstHash config, DataFlow::PathNode source, DataFlow::PathNode sink +where config.hasFlowPath(source, sink) +select sink.getNode(), source, sink, "Possible Timing attack against $@ validation.", + source.getNode().(ProduceCryptoCall).getResultType(), "message" diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/SafeComparisonOfHash.py b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/SafeComparisonOfHash.py new file mode 100644 index 00000000000..3aadc9b577c --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/SafeComparisonOfHash.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +""" +@Desc :preventing timing attack Against Hash +""" +import hmac +import hashlib + +key = "e179017a-62b0-4996-8a38-e91aa9f1" +msg = "Test" + +def sign(pre_key, imsg, alg): + return hmac.new(pre_key, imsg, alg).digest() + +def verify(msg, sig): + return hmac.compare_digest(sig, sign(key, msg, hashlib.sha256)) #good diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.qhelp b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.qhelp new file mode 100644 index 00000000000..2dfe5296167 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.qhelp @@ -0,0 +1,55 @@ +<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd"> +<qhelp> + +<overview> +<p> + Timing Attack is based on the leakage of information by studying how long it takes the system to respond to different inputs. + it can be circumvented by using a constant-time algorithm for checking the value of Hash, +more precisely, the comparison time should not depend on the content of the input. Otherwise the attacker gains +information that is indirectly leaked by the application. This information may then be used for malicious purposes. +</p> +</overview> + + +<recommendation> +<p> + Two types of countermeasures can be applied against timing attacks. The first one consists +in eliminating timing variations whereas the second renders these variations useless for an attacker. +The only absolute way to prevent timing attacks is to make the computation strictly constant time, +independent of the input. + + Use <code>hmac.compare_digest()</code> method to securely check the value of Hash. +If this method is used, then the calculation time depends only on the length of input byte arrays, +and does not depend on the contents of the arrays. + Unlike <code>==</code> is a fail fast check, If the first byte is not equal, it will return immediately. +</p> +</recommendation> +<example> +<p> + The following example uses <code>==</code> which is a fail fast check for validating a Hash. +</p> +<sample src="UnSafeComparisonOfHash.py" /> + +<p> + The next example use a safe constant-time algorithm for validating a Hash: +</p> +<sample src="SafeComparisonOfHash.py" /> +</example> + +<references> +<li> + Wikipedia: + <a href="https://en.wikipedia.org/wiki/Timing_attack">Timing attack</a>. +</li> + +<li> + <a href="https://docs.python.org/3/library/hmac.html#hmac.compare_digest">hmac.compare_digest() method</a> +</li> + +<li> + HMAC: + <a href="https://datatracker.ietf.org/doc/html/rfc2104.html">RFC 2104</a> +</li> +</references> + +</qhelp> diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.ql b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.ql new file mode 100644 index 00000000000..392356b7c42 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.ql @@ -0,0 +1,38 @@ +/** + * @name Timing attack against Hash + * @description When checking a Hash over a message, a constant-time algorithm should be used. + * Otherwise, an attacker may be able to forge a valid Hash for an arbitrary message + * by running a timing attack if they can send to the validation procedure. + * A successful attack can result in authentication bypass. + * @kind path-problem + * @problem.severity error + * @precision low + * @id py/timing-attack-against-hash + * @tags security + * external/cwe/cwe-208 + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import experimental.semmle.python.security.TimingAttack +import DataFlow::PathGraph + +/** + * A configuration that tracks data flow from cryptographic operations + * to Equality test. + */ +class TimingAttackAgainsthash extends TaintTracking::Configuration { + TimingAttackAgainsthash() { this = "TimingAttackAgainsthash" } + + override predicate isSource(DataFlow::Node source) { source instanceof ProduceCryptoCall } + + override predicate isSink(DataFlow::Node sink) { sink instanceof NonConstantTimeComparisonSink } +} + +from TimingAttackAgainsthash config, DataFlow::PathNode source, DataFlow::PathNode sink +where + config.hasFlowPath(source, sink) and + sink.getNode().(NonConstantTimeComparisonSink).includesUserInput() +select sink.getNode(), source, sink, "Timing attack against $@ validation.", + source.getNode().(ProduceCryptoCall).getResultType(), "message" diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/UnSafeComparisonOfHash.py b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/UnSafeComparisonOfHash.py new file mode 100644 index 00000000000..e518ee05379 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHash/UnSafeComparisonOfHash.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +""" +@Desc :timing attack Against Hash +""" +import hmac +import hashlib + +key = "e179017a-62b0-4996-8a38-e91aa9f1" +msg = "Test" + +def sign(pre_key, imsg, alg): + return hmac.new(pre_key, imsg, alg).digest() + +def verify(msg, sig): + return sig == sign(key, msg, hashlib.sha256) #bad diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/SafeComparisonOfHeaderValue.py b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/SafeComparisonOfHeaderValue.py new file mode 100644 index 00000000000..d5eca98ca3e --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/SafeComparisonOfHeaderValue.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +""" +@Desc :preventing timing attack against header value +""" + +from flask import Flask +from flask import request +import hmac + +@app.route('/good') +def good(): + secret = request.headers.get('X-Auth-Token') + if not hmac.compare_digest(secret, "token"): + raise Exception('bad token') + return 'good' + +if __name__ == '__main__': + app.debug = True + app.run() diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.qhelp b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.qhelp new file mode 100644 index 00000000000..547610b9bc2 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.qhelp @@ -0,0 +1,50 @@ +<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd"> +<qhelp> + +<overview> +<p> + A constant-time algorithm should be used for checking the value of sensitive headers. +In other words, the comparison time should not depend on the content of the input. +Otherwise timing information could be used to infer the header's expected, secret value. +</p> +</overview> + + +<recommendation> +<p> + Two types of countermeasures can be applied against timing attacks. The first one consists +in eliminating timing variations whereas the second renders these variations useless for an attacker. +The only absolute way to prevent timing attacks is to make the computation strictly constant time, +independent of the input. + + Use <code>hmac.compare_digest()</code> method to securely check the secret value. +If this method is used, then the calculation time depends only on the length of input byte arrays, +and does not depend on the contents of the arrays. + Unlike <code>==</code> is a fail fast check, If the first byte is not equal, it will return immediately. +</p> +</recommendation> +<example> +<p> + The following example uses <code>==</code> which is a fail fast check for validating the value of sensitive headers. +</p> +<sample src="UnsafeComparisonOfHeaderValue.py" /> + +<p> + The next example use a safe constant-time algorithm for validating the value of sensitive headers: +</p> +<sample src="SafeComparisonOfHeaderValue.py" /> +</example> + +<references> +<li> + Wikipedia: + <a href="https://en.wikipedia.org/wiki/Timing_attack">Timing attack</a>. +</li> + +<li> + <a href="https://docs.python.org/3/library/hmac.html#hmac.compare_digest">hmac.compare_digest() method</a> +</li> + +</references> + +</qhelp> diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.ql b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.ql new file mode 100644 index 00000000000..1f2ff8f50fb --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.ql @@ -0,0 +1,34 @@ +/** + * @name Timing attack against header value + * @description Use of a non-constant-time verification routine to check the value of an HTTP header, + * possibly allowing a timing attack to infer the header's expected value. + * @kind path-problem + * @problem.severity error + * @precision high + * @id py/timing-attack-against-header-value + * @tags security + * external/cwe/cwe-208 + * experimental + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import experimental.semmle.python.security.TimingAttack +import DataFlow::PathGraph + +/** + * A configuration tracing flow from a client Secret obtained by an HTTP header to a unsafe Comparison. + */ +class ClientSuppliedSecretConfig extends TaintTracking::Configuration { + ClientSuppliedSecretConfig() { this = "ClientSuppliedSecretConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof ClientSuppliedSecret } + + override predicate isSink(DataFlow::Node sink) { sink instanceof CompareSink } +} + +from ClientSuppliedSecretConfig config, DataFlow::PathNode source, DataFlow::PathNode sink +where config.hasFlowPath(source, sink) and not sink.getNode().(CompareSink).flowtolen() +select sink.getNode(), source, sink, "Timing attack against $@ validation.", source.getNode(), + "client-supplied token" diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/UnsafeComparisonOfHeaderValue.py b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/UnsafeComparisonOfHeaderValue.py new file mode 100644 index 00000000000..91bfadac9e5 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/UnsafeComparisonOfHeaderValue.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +""" +@Desc :preventing timing attack against header value +""" + +from flask import Flask +from flask import request + +@app.route('/bad') +def bad(): + secret = request.headers.get('X-Auth-Token') + if secret == "token": + raise Exception('bad token') + return 'bad' + +if __name__ == '__main__': + app.debug = True + app.run() diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.qhelp b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.qhelp new file mode 100644 index 00000000000..959bdc97a16 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.qhelp @@ -0,0 +1,4 @@ +<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd"> +<qhelp> +<include src="TimingAttackAgainstSensitiveInfo.qhelp" /> +</qhelp> diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.ql b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.ql new file mode 100644 index 00000000000..d43c3aa8995 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.ql @@ -0,0 +1,34 @@ +/** + * @name Timing attack against secret + * @description Use of a non-constant-time verification routine to check the value of an secret, + * possibly allowing a timing attack to retrieve sensitive information. + * @kind path-problem + * @problem.severity error + * @precision low + * @id py/possible-timing-attack-sensitive-info + * @tags security + * external/cwe/cwe-208 + * experimental + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import experimental.semmle.python.security.TimingAttack +import DataFlow::PathGraph + +/** + * A configuration tracing flow from obtaining a client Secret to a unsafe Comparison. + */ +class ClientSuppliedSecretConfig extends TaintTracking::Configuration { + ClientSuppliedSecretConfig() { this = "ClientSuppliedSecretConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof SecretSource } + + override predicate isSink(DataFlow::Node sink) { sink instanceof NonConstantTimeComparisonSink } +} + +from ClientSuppliedSecretConfig config, DataFlow::PathNode source, DataFlow::PathNode sink +where config.hasFlowPath(source, sink) +select sink.getNode(), source, sink, "Timing attack against $@ validation.", source.getNode(), + "client-supplied token" diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/SafeComparisonOfSensitiveInfo.py b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/SafeComparisonOfSensitiveInfo.py new file mode 100644 index 00000000000..d6be8c0c478 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/SafeComparisonOfSensitiveInfo.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +""" +@Desc :preventing timing attack sensitive info +""" +from flask import Flask +from flask import request +import hmac + +app = Flask(__name__) + +@app.route('/bad', methods = ['POST', 'GET']) +def bad(): + if request.method == 'POST': + password = request.form['pwd'] + return hmac.compare_digest(password, "1234") + +if __name__ == '__main__': + app.debug = True + app.run() diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.qhelp b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.qhelp new file mode 100644 index 00000000000..dd6d2de2573 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.qhelp @@ -0,0 +1,52 @@ +<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd"> +<qhelp> + +<overview> +<p> + Timing Attack is based on the leakage of information of secret parameters by studying +how long it takes the system to respond to different inputs. + it can be circumvented by using a constant-time algorithm for checking the value of sensitive info, +more precisely, the comparison time should not depend on the content of the input. Otherwise the attacker gains +information that is indirectly leaked by the application. This information is then used for malicious purposes. +</p> +</overview> + + +<recommendation> +<p> + Two types of countermeasures can be applied against timing attacks. The first one consists +in eliminating timing variations whereas the second renders these variations useless for an attacker. +The only absolute way to prevent timing attacks is to make the computation strictly constant time, +independent of the input. + + Use <code>hmac.compare_digest()</code> method to securely check the value of sensitive info. +If this method is used, then the calculation time depends only on the length of input byte arrays, +and does not depend on the contents of the arrays. + Unlike <code>==</code> is a fail fast check, If the first byte is not equal, it will return immediately. +</p> +</recommendation> +<example> +<p> + The following example uses <code>==</code> which is a fail fast check for validating a secret. +</p> +<sample src="UnSafeComparisonOfSensitiveInfo.py" /> + +<p> + The next example use a safe constant-time algorithm for validating a secret: +</p> +<sample src="SafeComparisonOfSensitiveInfo.py" /> +</example> + +<references> +<li> + Wikipedia: + <a href="https://en.wikipedia.org/wiki/Timing_attack">Timing attack</a>. +</li> + +<li> + <a href="https://docs.python.org/3/library/hmac.html#hmac.compare_digest">hmac.compare_digest() method</a> +</li> + +</references> + +</qhelp> diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.ql b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.ql new file mode 100644 index 00000000000..63587d4afcc --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.ql @@ -0,0 +1,39 @@ +/** + * @name Timing attack against secret + * @description Use of a non-constant-time verification routine to check the value of an secret, + * possibly allowing a timing attack to retrieve sensitive information. + * @kind path-problem + * @problem.severity error + * @precision low + * @id py/timing-attack-sensitive-info + * @tags security + * external/cwe/cwe-208 + * experimental + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import experimental.semmle.python.security.TimingAttack +import DataFlow::PathGraph + +/** + * A configuration tracing flow from obtaining a client Secret to a unsafe Comparison. + */ +class ClientSuppliedSecretConfig extends TaintTracking::Configuration { + ClientSuppliedSecretConfig() { this = "ClientSuppliedSecretConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof SecretSource } + + override predicate isSink(DataFlow::Node sink) { sink instanceof NonConstantTimeComparisonSink } +} + +from ClientSuppliedSecretConfig config, DataFlow::PathNode source, DataFlow::PathNode sink +where + config.hasFlowPath(source, sink) and + ( + source.getNode().(SecretSource).includesUserInput() or + sink.getNode().(NonConstantTimeComparisonSink).includesUserInput() + ) +select sink.getNode(), source, sink, "Timing attack against $@ validation.", source.getNode(), + "client-supplied token" diff --git a/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/UnSafeComparisonOfSensitiveInfo.py b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/UnSafeComparisonOfSensitiveInfo.py new file mode 100644 index 00000000000..3438c45b6c0 --- /dev/null +++ b/python/ql/src/experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/UnSafeComparisonOfSensitiveInfo.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +""" +@Desc :timing attack against sensitive info +""" + +from flask import Flask +from flask import request + +@app.route('/bad', methods = ['POST', 'GET']) +def bad(): + if request.method == 'POST': + password = request.form['pwd'] + return password == "test" + +if __name__ == '__main__': + app.debug = True + app.run() diff --git a/python/ql/src/experimental/Security/CWE-327/Azure/UnsafeUsageOfClientSideEncryptionVersion.ql b/python/ql/src/experimental/Security/CWE-327/Azure/UnsafeUsageOfClientSideEncryptionVersion.ql index 5799e0193ce..9b73cdcec87 100644 --- a/python/ql/src/experimental/Security/CWE-327/Azure/UnsafeUsageOfClientSideEncryptionVersion.ql +++ b/python/ql/src/experimental/Security/CWE-327/Azure/UnsafeUsageOfClientSideEncryptionVersion.ql @@ -1,7 +1,7 @@ /** * @name Unsafe usage of v1 version of Azure Storage client-side encryption. * @description Using version v1 of Azure Storage client-side encryption is insecure, and may enable an attacker to decrypt encrypted data - * @kind problem + * @kind path-problem * @tags security * experimental * cryptography @@ -12,80 +12,145 @@ */ import python +import semmle.python.dataflow.new.DataFlow import semmle.python.ApiGraphs -predicate isUnsafeClientSideAzureStorageEncryptionViaAttributes(Call call, AttrNode node) { - exists( - API::Node n, API::Node n2, Attribute a, AssignStmt astmt, API::Node uploadBlob, - ControlFlowNode ctrlFlowNode, string s - | - s in ["key_encryption_key", "key_resolver_function"] and - n = - API::moduleImport("azure") - .getMember("storage") - .getMember("blob") - .getMember("BlobClient") - .getReturn() - .getMember(s) and - n2 = - API::moduleImport("azure") - .getMember("storage") - .getMember("blob") - .getMember("BlobClient") - .getReturn() - .getMember("upload_blob") and - n.getAValueReachableFromSource().asExpr() = a and - astmt.getATarget() = a and - a.getAFlowNode() = node and - uploadBlob = - API::moduleImport("azure") - .getMember("storage") - .getMember("blob") - .getMember("BlobClient") - .getReturn() - .getMember("upload_blob") and - uploadBlob.getACall().asExpr() = call and - ctrlFlowNode = call.getAFlowNode() and - node.strictlyReaches(ctrlFlowNode) and - node != ctrlFlowNode and - not exists( - AssignStmt astmt2, Attribute a2, AttrNode encryptionVersionSet, StrConst uc, - API::Node encryptionVersion - | - uc = astmt2.getValue() and - uc.getText() in ["'2.0'", "2.0"] and - encryptionVersion = - API::moduleImport("azure") - .getMember("storage") - .getMember("blob") - .getMember("BlobClient") - .getReturn() - .getMember("encryption_version") and - encryptionVersion.getAValueReachableFromSource().asExpr() = a2 and - astmt2.getATarget() = a2 and - a2.getAFlowNode() = encryptionVersionSet and - encryptionVersionSet.strictlyReaches(ctrlFlowNode) - ) - ) +API::Node getBlobServiceClient(boolean isSource) { + isSource = true and + result = + API::moduleImport("azure") + .getMember("storage") + .getMember("blob") + .getMember("BlobServiceClient") + .getReturn() + or + isSource = true and + result = + API::moduleImport("azure") + .getMember("storage") + .getMember("blob") + .getMember("BlobServiceClient") + .getMember("from_connection_string") + .getReturn() } -predicate isUnsafeClientSideAzureStorageEncryptionViaObjectCreation(Call call, ControlFlowNode node) { - exists(API::Node c, string s, Keyword k | k.getAFlowNode() = node | - c.getACall().asExpr() = call and - c = API::moduleImport("azure").getMember("storage").getMember("blob").getMember(s) and - s in ["ContainerClient", "BlobClient", "BlobServiceClient"] and - k.getArg() = "key_encryption_key" and - k = call.getANamedArg() and - not k.getValue() instanceof None and - not exists(Keyword k2 | k2 = call.getANamedArg() | - k2.getArg() = "encryption_version" and - k2.getValue().(StrConst).getText() in ["'2.0'", "2.0"] - ) - ) +API::CallNode getTransitionToContainerClient() { + result = getBlobServiceClient(_).getMember("get_container_client").getACall() + or + result = getBlobClient(_).getMember("_get_container_client").getACall() } -from Call call, ControlFlowNode node -where - isUnsafeClientSideAzureStorageEncryptionViaAttributes(call, node) or - isUnsafeClientSideAzureStorageEncryptionViaObjectCreation(call, node) -select node, "Unsafe usage of v1 version of Azure Storage client-side encryption." +API::Node getContainerClient(boolean isSource) { + isSource = false and + result = getTransitionToContainerClient().getReturn() + or + isSource = true and + result = + API::moduleImport("azure") + .getMember("storage") + .getMember("blob") + .getMember("ContainerClient") + .getReturn() + or + isSource = true and + result = + API::moduleImport("azure") + .getMember("storage") + .getMember("blob") + .getMember("ContainerClient") + .getMember(["from_connection_string", "from_container_url"]) + .getReturn() +} + +API::CallNode getTransitionToBlobClient() { + result = [getBlobServiceClient(_), getContainerClient(_)].getMember("get_blob_client").getACall() +} + +API::Node getBlobClient(boolean isSource) { + isSource = false and + result = getTransitionToBlobClient().getReturn() + or + isSource = true and + result = + API::moduleImport("azure") + .getMember("storage") + .getMember("blob") + .getMember("BlobClient") + .getReturn() + or + isSource = true and + result = + API::moduleImport("azure") + .getMember("storage") + .getMember("blob") + .getMember("BlobClient") + .getMember(["from_connection_string", "from_blob_url"]) + .getReturn() +} + +API::Node anyClient(boolean isSource) { + result in [getBlobServiceClient(isSource), getContainerClient(isSource), getBlobClient(isSource)] +} + +newtype TAzureFlowState = + MkUsesV1Encryption() or + MkUsesNoEncryption() + +module AzureBlobClientConfig implements DataFlow::StateConfigSig { + class FlowState = TAzureFlowState; + + predicate isSource(DataFlow::Node node, FlowState state) { + state = MkUsesNoEncryption() and + node = anyClient(true).asSource() + } + + predicate isBarrier(DataFlow::Node node, FlowState state) { + exists(state) and + exists(DataFlow::AttrWrite attr | + node = anyClient(_).getAValueReachableFromSource() and + attr.accesses(node, "encryption_version") and + attr.getValue().asExpr().(StrConst).getText() in ["'2.0'", "2.0"] + ) + or + // small optimization to block flow with no encryption out of the post-update node + // for the attribute assignment. + isAdditionalFlowStep(_, MkUsesNoEncryption(), node, MkUsesV1Encryption()) and + state = MkUsesNoEncryption() + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + exists(DataFlow::MethodCallNode call | + call in [getTransitionToContainerClient(), getTransitionToBlobClient()] and + node1 = call.getObject() and + node2 = call + ) + } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 + ) { + node1 = node2.(DataFlow::PostUpdateNode).getPreUpdateNode() and + state1 = MkUsesNoEncryption() and + state2 = MkUsesV1Encryption() and + exists(DataFlow::AttrWrite attr | + node1 = anyClient(_).getAValueReachableFromSource() and + attr.accesses(node1, ["key_encryption_key", "key_resolver_function"]) + ) + } + + predicate isSink(DataFlow::Node node, FlowState state) { + state = MkUsesV1Encryption() and + exists(DataFlow::MethodCallNode call | + call = getBlobClient(_).getMember("upload_blob").getACall() and + node = call.getObject() + ) + } +} + +module AzureBlobClient = DataFlow::GlobalWithState<AzureBlobClientConfig>; + +import AzureBlobClient::PathGraph + +from AzureBlobClient::PathNode source, AzureBlobClient::PathNode sink +where AzureBlobClient::flowPath(source, sink) +select sink, source, sink, "Unsafe usage of v1 version of Azure Storage client-side encryption" diff --git a/python/ql/src/experimental/semmle/python/security/TimingAttack.qll b/python/ql/src/experimental/semmle/python/security/TimingAttack.qll new file mode 100644 index 00000000000..4df7752e64d --- /dev/null +++ b/python/ql/src/experimental/semmle/python/security/TimingAttack.qll @@ -0,0 +1,350 @@ +private import python +private import semmle.python.dataflow.new.TaintTracking2 +private import semmle.python.dataflow.new.TaintTracking +private import semmle.python.dataflow.new.DataFlow +private import semmle.python.dataflow.new.DataFlow2 +private import semmle.python.ApiGraphs +private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.frameworks.Flask +private import semmle.python.frameworks.Django + +/** A method call that produces cryptographic result. */ +abstract class ProduceCryptoCall extends API::CallNode { + /** Gets a type of cryptographic operation such as MAC, signature, Hash or ciphertext. */ + abstract string getResultType(); +} + +/** Gets a reference to the `cryptography.hazmat.primitives` module. */ +API::Node cryptographylib() { + result = API::moduleImport("cryptography").getMember("hazmat").getMember("primitives") +} + +/** Gets a reference to the `Crypto` module. */ +API::Node cryptodome() { result = API::moduleImport(["Crypto", "Cryptodome"]) } + +/** A method call that produces a MAC. */ +class ProduceMacCall extends ProduceCryptoCall { + ProduceMacCall() { + this = API::moduleImport("hmac").getMember("digest").getACall() or + this = + API::moduleImport("hmac") + .getMember("new") + .getReturn() + .getMember(["digest", "hexdigest"]) + .getACall() or + this = + cryptodome() + .getMember("Hash") + .getMember("HMAC") + .getMember(["new", "HMAC"]) + .getMember(["digest", "hexdigest"]) + .getACall() or + this = + cryptographylib() + .getMember("hmac") + .getMember("HMAC") + .getReturn() + .getMember("finalize") + .getACall() or + this = + cryptographylib() + .getMember("cmac") + .getMember("CMAC") + .getReturn() + .getMember("finalize") + .getACall() or + this = + cryptodome() + .getMember("Hash") + .getMember("CMAC") + .getMember(["new", "CMAC"]) + .getMember(["digest", "hexdigest"]) + .getACall() + } + + override string getResultType() { result = "MAC" } +} + +/** A method call that produces a signature. */ +private class ProduceSignatureCall extends ProduceCryptoCall { + ProduceSignatureCall() { + this = + cryptodome() + .getMember("Signature") + .getMember(["DSS", "pkcs1_15", "pss", "eddsa"]) + .getMember("new") + .getReturn() + .getMember("sign") + .getACall() + } + + override string getResultType() { result = "signature" } +} + +private string hashalgo() { + result = ["sha1", "sha224", "sha256", "sha384", "sha512", "blake2b", "blake2s", "md5"] +} + +/** A method call that produces a Hash. */ +private class ProduceHashCall extends ProduceCryptoCall { + ProduceHashCall() { + this = + cryptographylib() + .getMember("hashes") + .getMember("Hash") + .getReturn() + .getMember("finalize") + .getACall() or + this = + API::moduleImport("hashlib") + .getMember(["new", hashalgo()]) + .getReturn() + .getMember(["digest", "hexdigest"]) + .getACall() or + this = + cryptodome() + .getMember(hashalgo()) + .getMember("new") + .getReturn() + .getMember(["digest", "hexdigest"]) + .getACall() + } + + override string getResultType() { result = "Hash" } +} + +/** A method call that produces a ciphertext. */ +private class ProduceCiphertextCall extends ProduceCryptoCall { + ProduceCiphertextCall() { + this = + cryptodome() + .getMember("Cipher") + .getMember(["DES", "DES3", "ARC2", "ARC4", "Blowfish", "PKCS1_v1_5"]) + .getMember(["ARC4Cipher", "new", "PKCS115_Cipher"]) + .getMember("encrypt") + .getACall() or + this = + cryptographylib() + .getMember("ciphers") + .getMember("Cipher") + .getReturn() + .getMember("finalize") + .getACall() + } + + override string getResultType() { result = "ciphertext" } +} + +/** A data flow sink for comparison. */ +private predicate existsFailFastCheck(Expr firstInput, Expr secondInput) { + exists(Compare compare | + ( + compare.getOp(0) instanceof Eq or + compare.getOp(0) instanceof NotEq or + compare.getOp(0) instanceof In or + compare.getOp(0) instanceof NotIn + ) and + ( + compare.getLeft() = firstInput and + compare.getComparator(0) = secondInput and + not compare.getAComparator() instanceof None + or + compare.getLeft() = secondInput and + compare.getComparator(0) = firstInput and + not compare.getAComparator() instanceof None + ) + ) +} + +/** A sink that compares input using fail fast check. */ +class NonConstantTimeComparisonSink extends DataFlow::Node { + Expr anotherParameter; + + NonConstantTimeComparisonSink() { existsFailFastCheck(this.asExpr(), anotherParameter) } + + /** Holds if remote user input was used in the comparison. */ + predicate includesUserInput() { + exists(UserInputInComparisonConfig config | + config.hasFlowTo(DataFlow2::exprNode(anotherParameter)) + ) + } +} + +/** A data flow source of the secret obtained. */ +class SecretSource extends DataFlow::Node { + CredentialExpr secret; + + SecretSource() { secret = this.asExpr() } + + /** Holds if the secret was deliverd by remote user. */ + predicate includesUserInput() { + exists(UserInputSecretConfig config | config.hasFlowTo(DataFlow2::exprNode(secret))) + } +} + +/** A string for `match` that identifies strings that look like they represent secret data. */ +private string suspicious() { + result = + [ + "%password%", "%passwd%", "%pwd%", "%refresh%token%", "%secret%token", "%secret%key", + "%passcode%", "%passphrase%", "%token%", "%secret%", "%credential%", "%userpass%", "%digest%", + "%signature%", "%mac%" + ] +} + +/** A variable that may hold sensitive information, judging by its name. * */ +class CredentialExpr extends Expr { + CredentialExpr() { + exists(Variable v | this = v.getAnAccess() | v.getId().toLowerCase().matches(suspicious())) + } +} + +/** + * A data flow source of the client Secret obtained according to the remote endpoint identifier specified + * (`X-auth-token`, `proxy-authorization`, `X-Csrf-Header`, etc.) in the header. + * + * For example: `request.headers.get("X-Auth-Token")`. + */ +abstract class ClientSuppliedSecret extends DataFlow::CallCfgNode { } + +private class FlaskClientSuppliedSecret extends ClientSuppliedSecret { + FlaskClientSuppliedSecret() { + this = Flask::request().getMember("headers").getMember(["get", "get_all", "getlist"]).getACall() and + [this.getArg(0), this.getArgByName(["key", "name"])].asExpr().(StrConst).getText().toLowerCase() = + sensitiveheaders() + } +} + +private class DjangoClientSuppliedSecret extends ClientSuppliedSecret { + DjangoClientSuppliedSecret() { + this = + PrivateDjango::DjangoImpl::DjangoHttp::Request::HttpRequest::classRef() + .getMember(["headers", "META"]) + .getMember("get") + .getACall() and + [this.getArg(0), this.getArgByName("key")].asExpr().(StrConst).getText().toLowerCase() = + sensitiveheaders() + } +} + +/** Gets a reference to the `tornado.web.RequestHandler` module. */ +API::Node requesthandler() { + result = API::moduleImport("tornado").getMember("web").getMember("RequestHandler") +} + +private class TornadoClientSuppliedSecret extends ClientSuppliedSecret { + TornadoClientSuppliedSecret() { + this = requesthandler().getMember(["headers", "META"]).getMember("get").getACall() and + [this.getArg(0), this.getArgByName("key")].asExpr().(StrConst).getText().toLowerCase() = + sensitiveheaders() + } +} + +/** Gets a reference to the `werkzeug.datastructures.Headers` module. */ +API::Node headers() { + result = API::moduleImport("werkzeug").getMember("datastructures").getMember("Headers") +} + +private class WerkzeugClientSuppliedSecret extends ClientSuppliedSecret { + WerkzeugClientSuppliedSecret() { + this = + headers().getMember(["headers", "META"]).getMember(["get", "get_all", "getlist"]).getACall() and + [this.getArg(0), this.getArgByName(["key", "name"])].asExpr().(StrConst).getText().toLowerCase() = + sensitiveheaders() + } +} + +/** A string for `match` that identifies strings that look like they represent Sensitive Headers. */ +private string sensitiveheaders() { + result = + [ + "x-auth-token", "x-csrf-token", "http_x_csrf_token", "x-csrf-param", "x-csrf-header", + "http_x_csrf_token", "x-api-key", "authorization", "proxy-authorization", "x-gitlab-token", + "www-authenticate" + ] +} + +/** + * A config that tracks data flow from remote user input to Variable that hold sensitive info + */ +class UserInputSecretConfig extends TaintTracking::Configuration { + UserInputSecretConfig() { this = "UserInputSecretConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof CredentialExpr } +} + +/** + * A config that tracks data flow from remote user input to Equality test + */ +class UserInputInComparisonConfig extends TaintTracking2::Configuration { + UserInputInComparisonConfig() { this = "UserInputInComparisonConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { + exists(Compare cmp, Expr left, Expr right, Cmpop cmpop | + cmpop.getSymbol() = ["==", "in", "is not", "!="] and + cmp.compares(left, cmpop, right) and + sink.asExpr() = [left, right] + ) + } +} + +/** + * A configuration tracing flow from a client Secret obtained by an HTTP header to a len() function. + */ +private class ExcludeLenFunc extends TaintTracking2::Configuration { + ExcludeLenFunc() { this = "ExcludeLenFunc" } + + override predicate isSource(DataFlow::Node source) { source instanceof ClientSuppliedSecret } + + override predicate isSink(DataFlow::Node sink) { + exists(Call call | + call.getFunc().(Name).getId() = "len" and + sink.asExpr() = call.getArg(0) + ) + } +} + +/** + * Holds if there is a fast-fail check. + */ +class CompareSink extends DataFlow::Node { + CompareSink() { + exists(Compare compare | + ( + compare.getOp(0) instanceof Eq or + compare.getOp(0) instanceof NotEq + ) and + ( + compare.getLeft() = this.asExpr() and + not compare.getComparator(0).(StrConst).getText() = "bearer" + or + compare.getComparator(0) = this.asExpr() and + not compare.getLeft().(StrConst).getText() = "bearer" + ) + ) + or + exists(Compare compare | + compare.getOp(0) instanceof IsNot and + ( + compare.getLeft() = this.asExpr() and + not compare.getComparator(0) instanceof None + or + compare.getComparator(0) = this.asExpr() and + not compare.getLeft() instanceof None + ) + ) + } + + /** + * Holds if there is a flow to len(). + */ + predicate flowtolen() { + exists(ExcludeLenFunc config, DataFlow2::PathNode source, DataFlow2::PathNode sink | + config.hasFlowPath(source, sink) + ) + } +} diff --git a/python/ql/test/experimental/dataflow/coverage-py2/argumentRoutingTest.expected b/python/ql/test/experimental/dataflow/coverage-py2/argumentRoutingTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/experimental/dataflow/coverage-py2/argumentRoutingTest.qlref b/python/ql/test/experimental/dataflow/coverage-py2/argumentRoutingTest.qlref new file mode 100644 index 00000000000..58bedc4c88c --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage-py2/argumentRoutingTest.qlref @@ -0,0 +1 @@ +../coverage/argumentRoutingTest.ql diff --git a/python/ql/test/experimental/dataflow/coverage-py2/classes.py b/python/ql/test/experimental/dataflow/coverage-py2/classes.py new file mode 100644 index 00000000000..48dbaea8e93 --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage-py2/classes.py @@ -0,0 +1,54 @@ +# Python 2 specific tests, like the one in coverage/classes.py +# +# User-defined methods, both instance methods and class methods, can be called in many non-standard ways +# i.e. differently from simply `c.f()` or `C.f()`. For example, a user-defined `__await__` method on a +# class `C` will be called by the syntactic construct `await c` when `c` is an instance of `C`. +# +# These tests should cover all the class calls that we hope to support. +# It is based on https://docs.python.org/3/reference/datamodel.html, and headings refer there. +# +# All functions starting with "test_" should run and execute `print("OK")` exactly once. +# This can be checked by running validTest.py. + +import sys +import os + +sys.path.append(os.path.dirname(os.path.dirname((__file__)))) +from testlib import expects + + +def SINK1(x): + pass + + +def SINK2(x): + pass + + +def SINK3(x): + pass + + +def SINK4(x): + pass + + +def OK(): + print("OK") + + +# 3.3.8. Emulating numeric types + +# object.__index__(self) +class With_index: + def __index__(self): + SINK1(self) + OK() # Call not found + return 0 + + +def test_index(): + import operator + + with_index = With_index() #$ MISSING: arg1="SSA variable with_index" func=With_index.__index__ + operator.index(with_index) diff --git a/python/ql/test/experimental/dataflow/coverage-py2/options b/python/ql/test/experimental/dataflow/coverage-py2/options new file mode 100644 index 00000000000..8dd8d25c998 --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage-py2/options @@ -0,0 +1 @@ +semmle-extractor-options: --max-import-depth=1 --lang=2 diff --git a/python/ql/test/experimental/dataflow/coverage-py3/argumentRoutingTest.expected b/python/ql/test/experimental/dataflow/coverage-py3/argumentRoutingTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/experimental/dataflow/coverage-py3/argumentRoutingTest.qlref b/python/ql/test/experimental/dataflow/coverage-py3/argumentRoutingTest.qlref new file mode 100644 index 00000000000..58bedc4c88c --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage-py3/argumentRoutingTest.qlref @@ -0,0 +1 @@ +../coverage/argumentRoutingTest.ql diff --git a/python/ql/test/experimental/dataflow/coverage-py3/classes.py b/python/ql/test/experimental/dataflow/coverage-py3/classes.py new file mode 100644 index 00000000000..308c79acbb4 --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage-py3/classes.py @@ -0,0 +1,72 @@ +# Python 3 specific tests, like the one in coverage/classes.py +# +# User-defined methods, both instance methods and class methods, can be called in many non-standard ways +# i.e. differently from simply `c.f()` or `C.f()`. For example, a user-defined `__await__` method on a +# class `C` will be called by the syntactic construct `await c` when `c` is an instance of `C`. +# +# These tests should cover all the class calls that we hope to support. +# It is based on https://docs.python.org/3/reference/datamodel.html, and headings refer there. +# +# All functions starting with "test_" should run and execute `print("OK")` exactly once. +# This can be checked by running validTest.py. + +import sys +import os + +sys.path.append(os.path.dirname(os.path.dirname((__file__)))) +from testlib import expects + + +def SINK1(x): + pass + + +def SINK2(x): + pass + + +def SINK3(x): + pass + + +def SINK4(x): + pass + + +def OK(): + print("OK") + + + +# 3.3.7. Emulating container types + +# object.__length_hint__(self) +class With_length_hint: + def __length_hint__(self): + SINK1(self) + OK() + return 0 + + +def test_length_hint(): + import operator + + with_length_hint = With_length_hint() #$ arg1="SSA variable with_length_hint" func=With_length_hint.__length_hint__ + operator.length_hint(with_length_hint) + + +# 3.3.8. Emulating numeric types + +# object.__index__(self) +class With_index: + def __index__(self): + SINK1(self) + OK() # Call not found + return 0 + + +def test_index(): + import operator + + with_index = With_index() #$ arg1="SSA variable with_index" func=With_index.__index__ + operator.index(with_index) diff --git a/python/ql/test/experimental/dataflow/coverage-py3/options b/python/ql/test/experimental/dataflow/coverage-py3/options new file mode 100644 index 00000000000..cfef58cf2b2 --- /dev/null +++ b/python/ql/test/experimental/dataflow/coverage-py3/options @@ -0,0 +1 @@ +semmle-extractor-options: --max-import-depth=1 --lang=3 diff --git a/python/ql/test/experimental/dataflow/coverage/classes.py b/python/ql/test/experimental/dataflow/coverage/classes.py index d74a632b7c3..2569921d6c9 100644 --- a/python/ql/test/experimental/dataflow/coverage/classes.py +++ b/python/ql/test/experimental/dataflow/coverage/classes.py @@ -535,21 +535,6 @@ def test_len_if(): pass -# object.__length_hint__(self) -class With_length_hint: - def __length_hint__(self): - SINK1(self) - OK() # Call not found - return 0 - - -def test_length_hint(): - import operator - - with_length_hint = With_length_hint() #$ MISSING: arg1="SSA variable with_length_hint" func=With_length_hint.__length_hint__ - operator.length_hint(with_length_hint) - - # object.__getitem__(self, key) class With_getitem: def __getitem__(self, key): @@ -1378,13 +1363,6 @@ class With_index: return 0 -def test_index(): - import operator - - with_index = With_index() #$ MISSING: arg1="SSA variable with_index" func=With_index.__index__ - operator.index(with_index) - - def test_index_slicing(): with_index = With_index() #$ MISSING: arg1="SSA variable with_index" func=With_index.__index__ [0][with_index:1] diff --git a/python/ql/test/experimental/dataflow/validTest.py b/python/ql/test/experimental/dataflow/validTest.py index c2280521113..eeb6604ce7a 100644 --- a/python/ql/test/experimental/dataflow/validTest.py +++ b/python/ql/test/experimental/dataflow/validTest.py @@ -64,9 +64,12 @@ if __name__ == "__main__": check_tests_valid("coverage.test") check_tests_valid("coverage.argumentPassing") check_tests_valid("coverage.datamodel") + check_tests_valid("coverage-py2.classes") + check_tests_valid("coverage-py3.classes") check_tests_valid("variable-capture.in") check_tests_valid("variable-capture.nonlocal") check_tests_valid("variable-capture.dict") + check_tests_valid("variable-capture.collections") check_tests_valid("module-initialization.multiphase") check_tests_valid("fieldflow.test") check_tests_valid_after_version("match.test", (3, 10)) diff --git a/python/ql/test/experimental/dataflow/variable-capture/collections.py b/python/ql/test/experimental/dataflow/variable-capture/collections.py index 11504695ceb..0920c8d595a 100644 --- a/python/ql/test/experimental/dataflow/variable-capture/collections.py +++ b/python/ql/test/experimental/dataflow/variable-capture/collections.py @@ -31,7 +31,7 @@ def SINK_F(x): print("OK") l = [NONSOURCE] -SINK_F(l_mod[0]) +SINK_F(l[0]) l_mod = [SOURCE for x in l] SINK(l_mod[0]) #$ captured diff --git a/python/ql/test/experimental/import-resolution/ModuleExport.expected b/python/ql/test/experimental/import-resolution/ModuleExport.expected new file mode 100644 index 00000000000..b1f63a02a78 --- /dev/null +++ b/python/ql/test/experimental/import-resolution/ModuleExport.expected @@ -0,0 +1,160 @@ +| attr_clash.__init__ | __file__ | attr_clash/__init__.py:6:6:6:13 | ControlFlowNode for __file__ | +| attr_clash.__init__ | __name__ | attr_clash/__init__.py:0:0:0:0 | GSSA Variable __name__ | +| attr_clash.__init__ | __package__ | attr_clash/__init__.py:0:0:0:0 | GSSA Variable __package__ | +| attr_clash.__init__ | clashing_attr | attr_clash/__init__.py:4:1:4:13 | GSSA Variable clashing_attr | +| attr_clash.__init__ | enter | attr_clash/__init__.py:2:1:2:5 | ControlFlowNode for enter | +| attr_clash.__init__ | exit | attr_clash/__init__.py:6:1:6:4 | ControlFlowNode for exit | +| attr_clash.clashing_attr | __file__ | attr_clash/clashing_attr.py:4:6:4:13 | ControlFlowNode for __file__ | +| attr_clash.clashing_attr | __name__ | attr_clash/clashing_attr.py:0:0:0:0 | GSSA Variable __name__ | +| attr_clash.clashing_attr | __package__ | attr_clash/clashing_attr.py:0:0:0:0 | GSSA Variable __package__ | +| attr_clash.clashing_attr | enter | attr_clash/clashing_attr.py:2:1:2:5 | ControlFlowNode for enter | +| attr_clash.clashing_attr | exit | attr_clash/clashing_attr.py:4:1:4:4 | ControlFlowNode for exit | +| attr_clash.non_clashing_submodule | __file__ | attr_clash/non_clashing_submodule.py:4:6:4:13 | ControlFlowNode for __file__ | +| attr_clash.non_clashing_submodule | __name__ | attr_clash/non_clashing_submodule.py:0:0:0:0 | GSSA Variable __name__ | +| attr_clash.non_clashing_submodule | __package__ | attr_clash/non_clashing_submodule.py:0:0:0:0 | GSSA Variable __package__ | +| attr_clash.non_clashing_submodule | enter | attr_clash/non_clashing_submodule.py:2:1:2:5 | ControlFlowNode for enter | +| attr_clash.non_clashing_submodule | exit | attr_clash/non_clashing_submodule.py:4:1:4:4 | ControlFlowNode for exit | +| bar | __file__ | bar.py:6:6:6:13 | ControlFlowNode for __file__ | +| bar | __name__ | bar.py:0:0:0:0 | GSSA Variable __name__ | +| bar | __package__ | bar.py:0:0:0:0 | GSSA Variable __package__ | +| bar | bar_attr | bar.py:4:1:4:8 | GSSA Variable bar_attr | +| bar | enter | bar.py:2:1:2:5 | ControlFlowNode for enter | +| bar | exit | bar.py:6:1:6:4 | ControlFlowNode for exit | +| baz | __file__ | baz.py:6:6:6:13 | ControlFlowNode for __file__ | +| baz | __name__ | baz.py:0:0:0:0 | GSSA Variable __name__ | +| baz | __package__ | baz.py:0:0:0:0 | GSSA Variable __package__ | +| baz | baz_attr | baz.py:4:1:4:8 | GSSA Variable baz_attr | +| baz | enter | baz.py:2:1:2:5 | ControlFlowNode for enter | +| baz | exit | baz.py:6:1:6:4 | ControlFlowNode for exit | +| block_flow_check | SOURCE | block_flow_check.py:12:25:12:30 | ControlFlowNode for SOURCE | +| block_flow_check | __file__ | block_flow_check.py:14:6:14:13 | ControlFlowNode for __file__ | +| block_flow_check | __name__ | block_flow_check.py:0:0:0:0 | GSSA Variable __name__ | +| block_flow_check | __package__ | block_flow_check.py:0:0:0:0 | GSSA Variable __package__ | +| block_flow_check | check | block_flow_check.py:12:1:12:5 | ControlFlowNode for check | +| block_flow_check | enter | block_flow_check.py:2:1:2:5 | ControlFlowNode for enter | +| block_flow_check | exit | block_flow_check.py:14:1:14:4 | ControlFlowNode for exit | +| block_flow_check | globals | block_flow_check.py:12:33:12:39 | ControlFlowNode for globals | +| block_flow_check | object | block_flow_check.py:4:14:4:19 | ControlFlowNode for object | +| block_flow_check | staticmethod | block_flow_check.py:0:0:0:0 | GSSA Variable staticmethod | +| foo | __file__ | foo.py:14:6:14:13 | ControlFlowNode for __file__ | +| foo | __name__ | foo.py:0:0:0:0 | GSSA Variable __name__ | +| foo | __package__ | foo.py:0:0:0:0 | GSSA Variable __package__ | +| foo | __private_foo_attr | foo.py:8:1:8:18 | GSSA Variable __private_foo_attr | +| foo | bar_reexported | foo.py:11:8:11:10 | ControlFlowNode for ImportExpr | +| foo | bar_reexported | foo.py:12:34:12:47 | ControlFlowNode for bar_reexported | +| foo | check | foo.py:12:1:12:5 | ControlFlowNode for check | +| foo | enter | foo.py:2:1:2:5 | ControlFlowNode for enter | +| foo | exit | foo.py:14:1:14:4 | ControlFlowNode for exit | +| foo | foo_attr | foo.py:5:1:5:8 | GSSA Variable foo_attr | +| foo | globals | foo.py:12:71:12:77 | ControlFlowNode for globals | +| generous_export | Exception | generous_export.py:16:11:16:19 | ControlFlowNode for Exception | +| generous_export | SOURCE | generous_export.py:15:11:15:16 | ControlFlowNode for SOURCE | +| generous_export | SOURCE | generous_export.py:20:25:20:30 | ControlFlowNode for SOURCE | +| generous_export | __file__ | generous_export.py:22:6:22:13 | ControlFlowNode for __file__ | +| generous_export | __name__ | generous_export.py:0:0:0:0 | GSSA Variable __name__ | +| generous_export | __package__ | generous_export.py:0:0:0:0 | GSSA Variable __package__ | +| generous_export | check | generous_export.py:20:1:20:5 | ControlFlowNode for check | +| generous_export | enter | generous_export.py:2:1:2:5 | ControlFlowNode for enter | +| generous_export | eval | generous_export.py:10:4:10:7 | ControlFlowNode for eval | +| generous_export | exit | generous_export.py:22:1:22:4 | ControlFlowNode for exit | +| generous_export | globals | generous_export.py:20:33:20:39 | ControlFlowNode for globals | +| generous_export | object | generous_export.py:4:14:4:19 | ControlFlowNode for object | +| generous_export | print | generous_export.py:15:5:15:9 | ControlFlowNode for print | +| generous_export | staticmethod | generous_export.py:0:0:0:0 | GSSA Variable staticmethod | +| has_defined_all | __all__ | has_defined_all.py:7:1:7:7 | GSSA Variable __all__ | +| has_defined_all | __file__ | has_defined_all.py:9:6:9:13 | ControlFlowNode for __file__ | +| has_defined_all | __name__ | has_defined_all.py:0:0:0:0 | GSSA Variable __name__ | +| has_defined_all | __package__ | has_defined_all.py:0:0:0:0 | GSSA Variable __package__ | +| has_defined_all | all_defined_bar | has_defined_all.py:5:1:5:15 | GSSA Variable all_defined_bar | +| has_defined_all | all_defined_foo | has_defined_all.py:4:1:4:15 | GSSA Variable all_defined_foo | +| has_defined_all | enter | has_defined_all.py:2:1:2:5 | ControlFlowNode for enter | +| has_defined_all | exit | has_defined_all.py:9:1:9:4 | ControlFlowNode for exit | +| has_defined_all_copy | __all__ | has_defined_all_copy.py:9:1:9:7 | GSSA Variable __all__ | +| has_defined_all_copy | __file__ | has_defined_all_copy.py:11:6:11:13 | ControlFlowNode for __file__ | +| has_defined_all_copy | __name__ | has_defined_all_copy.py:0:0:0:0 | GSSA Variable __name__ | +| has_defined_all_copy | __package__ | has_defined_all_copy.py:0:0:0:0 | GSSA Variable __package__ | +| has_defined_all_copy | all_defined_bar_copy | has_defined_all_copy.py:7:1:7:20 | GSSA Variable all_defined_bar_copy | +| has_defined_all_copy | all_defined_foo_copy | has_defined_all_copy.py:6:1:6:20 | GSSA Variable all_defined_foo_copy | +| has_defined_all_copy | enter | has_defined_all_copy.py:4:1:4:5 | ControlFlowNode for enter | +| has_defined_all_copy | exit | has_defined_all_copy.py:11:1:11:4 | ControlFlowNode for exit | +| has_defined_all_indirection | __file__ | has_defined_all_indirection.py:6:6:6:13 | ControlFlowNode for __file__ | +| has_defined_all_indirection | __name__ | has_defined_all_indirection.py:0:0:0:0 | GSSA Variable __name__ | +| has_defined_all_indirection | __package__ | has_defined_all_indirection.py:0:0:0:0 | GSSA Variable __package__ | +| has_defined_all_indirection | all_defined_foo_copy | has_defined_all_copy.py:6:1:6:20 | GSSA Variable all_defined_foo_copy | +| has_defined_all_indirection | enter | has_defined_all_indirection.py:2:1:2:5 | ControlFlowNode for enter | +| has_defined_all_indirection | exit | has_defined_all_indirection.py:6:1:6:4 | ControlFlowNode for exit | +| if_then_else | __file__ | if_then_else.py:16:6:16:13 | ControlFlowNode for __file__ | +| if_then_else | __name__ | if_then_else.py:0:0:0:0 | GSSA Variable __name__ | +| if_then_else | __package__ | if_then_else.py:0:0:0:0 | GSSA Variable __package__ | +| if_then_else | enter | if_then_else.py:2:1:2:5 | ControlFlowNode for enter | +| if_then_else | eval | if_then_else.py:11:8:11:11 | ControlFlowNode for eval | +| if_then_else | exit | if_then_else.py:16:1:16:4 | ControlFlowNode for exit | +| if_then_else | if_then_else_defined | if_then_else.py:7:5:7:24 | GSSA Variable if_then_else_defined | +| if_then_else | if_then_else_defined | if_then_else.py:12:9:12:28 | GSSA Variable if_then_else_defined | +| if_then_else | if_then_else_defined | if_then_else.py:14:9:14:28 | GSSA Variable if_then_else_defined | +| if_then_else_refined | SOURCE | if_then_else_refined.py:11:11:11:16 | ControlFlowNode for SOURCE | +| if_then_else_refined | SOURCE | if_then_else_refined.py:13:11:13:16 | ControlFlowNode for SOURCE | +| if_then_else_refined | __file__ | if_then_else_refined.py:19:6:19:13 | ControlFlowNode for __file__ | +| if_then_else_refined | __name__ | if_then_else_refined.py:0:0:0:0 | GSSA Variable __name__ | +| if_then_else_refined | __package__ | if_then_else_refined.py:0:0:0:0 | GSSA Variable __package__ | +| if_then_else_refined | check | if_then_else_refined.py:17:1:17:5 | ControlFlowNode for check | +| if_then_else_refined | enter | if_then_else_refined.py:4:1:4:5 | ControlFlowNode for enter | +| if_then_else_refined | eval | if_then_else_refined.py:10:4:10:7 | ControlFlowNode for eval | +| if_then_else_refined | exit | if_then_else_refined.py:19:1:19:4 | ControlFlowNode for exit | +| if_then_else_refined | globals | if_then_else_refined.py:17:24:17:30 | ControlFlowNode for globals | +| if_then_else_refined | src | if_then_else_refined.py:17:19:17:21 | ControlFlowNode for src | +| package.__init__ | __file__ | package/__init__.py:7:6:7:13 | ControlFlowNode for __file__ | +| package.__init__ | __name__ | package/__init__.py:0:0:0:0 | GSSA Variable __name__ | +| package.__init__ | __package__ | package/__init__.py:0:0:0:0 | GSSA Variable __package__ | +| package.__init__ | attr_used_in_subpackage | package/__init__.py:4:1:4:23 | GSSA Variable attr_used_in_subpackage | +| package.__init__ | enter | package/__init__.py:2:1:2:5 | ControlFlowNode for enter | +| package.__init__ | exit | package/__init__.py:7:1:7:4 | ControlFlowNode for exit | +| package.__init__ | package_attr | package/__init__.py:5:1:5:12 | GSSA Variable package_attr | +| package.subpackage2.__init__ | __file__ | package/subpackage2/__init__.py:6:6:6:13 | ControlFlowNode for __file__ | +| package.subpackage2.__init__ | __name__ | package/subpackage2/__init__.py:0:0:0:0 | GSSA Variable __name__ | +| package.subpackage2.__init__ | __package__ | package/subpackage2/__init__.py:0:0:0:0 | GSSA Variable __package__ | +| package.subpackage2.__init__ | enter | package/subpackage2/__init__.py:2:1:2:5 | ControlFlowNode for enter | +| package.subpackage2.__init__ | exit | package/subpackage2/__init__.py:6:1:6:4 | ControlFlowNode for exit | +| package.subpackage2.__init__ | subpackage2_attr | package/subpackage2/__init__.py:4:1:4:16 | GSSA Variable subpackage2_attr | +| package.subpackage.__init__ | __file__ | package/subpackage/__init__.py:14:6:14:13 | ControlFlowNode for __file__ | +| package.subpackage.__init__ | __name__ | package/subpackage/__init__.py:0:0:0:0 | GSSA Variable __name__ | +| package.subpackage.__init__ | __package__ | package/subpackage/__init__.py:0:0:0:0 | GSSA Variable __package__ | +| package.subpackage.__init__ | check | package/subpackage/__init__.py:12:1:12:5 | ControlFlowNode for check | +| package.subpackage.__init__ | enter | package/subpackage/__init__.py:2:1:2:5 | ControlFlowNode for enter | +| package.subpackage.__init__ | exit | package/subpackage/__init__.py:14:1:14:4 | ControlFlowNode for exit | +| package.subpackage.__init__ | globals | package/subpackage/__init__.py:12:79:12:85 | ControlFlowNode for globals | +| package.subpackage.__init__ | imported_attr | package/subpackage/__init__.py:7:16:7:55 | ControlFlowNode for ImportMember | +| package.subpackage.__init__ | imported_attr | package/subpackage/__init__.py:8:24:8:36 | ControlFlowNode for imported_attr | +| package.subpackage.__init__ | irrelevant_attr | package/subpackage/__init__.py:11:24:11:38 | ControlFlowNode for ImportMember | +| package.subpackage.__init__ | irrelevant_attr | package/subpackage/__init__.py:11:24:11:38 | GSSA Variable irrelevant_attr | +| package.subpackage.__init__ | submodule | package/subpackage/__init__.py:12:35:12:43 | ControlFlowNode for submodule | +| package.subpackage.__init__ | subpackage_attr | package/subpackage/__init__.py:4:1:4:15 | GSSA Variable subpackage_attr | +| package.subpackage.submodule | __file__ | package/subpackage/submodule.py:7:6:7:13 | ControlFlowNode for __file__ | +| package.subpackage.submodule | __name__ | package/subpackage/submodule.py:0:0:0:0 | GSSA Variable __name__ | +| package.subpackage.submodule | __package__ | package/subpackage/submodule.py:0:0:0:0 | GSSA Variable __package__ | +| package.subpackage.submodule | enter | package/subpackage/submodule.py:2:1:2:5 | ControlFlowNode for enter | +| package.subpackage.submodule | exit | package/subpackage/submodule.py:7:1:7:4 | ControlFlowNode for exit | +| package.subpackage.submodule | irrelevant_attr | package/subpackage/submodule.py:5:1:5:15 | GSSA Variable irrelevant_attr | +| package.subpackage.submodule | submodule_attr | package/subpackage/submodule.py:4:1:4:14 | GSSA Variable submodule_attr | +| refined | SOURCE | refined.py:12:25:12:30 | ControlFlowNode for SOURCE | +| refined | __file__ | refined.py:14:6:14:13 | ControlFlowNode for __file__ | +| refined | __name__ | refined.py:0:0:0:0 | GSSA Variable __name__ | +| refined | __package__ | refined.py:0:0:0:0 | GSSA Variable __package__ | +| refined | check | refined.py:12:1:12:5 | ControlFlowNode for check | +| refined | enter | refined.py:2:1:2:5 | ControlFlowNode for enter | +| refined | exit | refined.py:14:1:14:4 | ControlFlowNode for exit | +| refined | globals | refined.py:12:33:12:39 | ControlFlowNode for globals | +| refined | object | refined.py:4:14:4:19 | ControlFlowNode for object | +| simplistic_reexport | __file__ | simplistic_reexport.py:19:6:19:13 | ControlFlowNode for __file__ | +| simplistic_reexport | __name__ | simplistic_reexport.py:0:0:0:0 | GSSA Variable __name__ | +| simplistic_reexport | __package__ | simplistic_reexport.py:0:0:0:0 | GSSA Variable __package__ | +| simplistic_reexport | bar_attr | simplistic_reexport.py:6:17:6:24 | ControlFlowNode for ImportMember | +| simplistic_reexport | bar_attr | simplistic_reexport.py:10:19:10:26 | ControlFlowNode for bar_attr | +| simplistic_reexport | baz_attr | baz.py:4:1:4:8 | GSSA Variable baz_attr | +| simplistic_reexport | baz_attr | simplistic_reexport.py:17:19:17:26 | ControlFlowNode for baz_attr | +| simplistic_reexport | check | simplistic_reexport.py:17:1:17:5 | ControlFlowNode for check | +| simplistic_reexport | enter | baz.py:2:1:2:5 | ControlFlowNode for enter | +| simplistic_reexport | enter | simplistic_reexport.py:4:1:4:5 | ControlFlowNode for enter | +| simplistic_reexport | exit | baz.py:6:1:6:4 | ControlFlowNode for exit | +| simplistic_reexport | exit | simplistic_reexport.py:19:1:19:4 | ControlFlowNode for exit | +| simplistic_reexport | globals | simplistic_reexport.py:17:44:17:50 | ControlFlowNode for globals | diff --git a/python/ql/test/experimental/import-resolution/ModuleExport.ql b/python/ql/test/experimental/import-resolution/ModuleExport.ql new file mode 100644 index 00000000000..56db660b103 --- /dev/null +++ b/python/ql/test/experimental/import-resolution/ModuleExport.ql @@ -0,0 +1,17 @@ +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.internal.ImportResolution + +from Module m, string name, DataFlow::Node defn +where + ImportResolution::module_export(m, name, defn) and + exists(m.getLocation().getFile().getRelativePath()) and + not defn.getScope() = any(Module trace | trace.getName() = "trace") and + not m.getName() = "main" and + // Since we test on both Python 2 and Python 3, but `namespace_package` is not allowed + // on Python 2 because of the missing `__init__.py` files, we remove those results + // from Python 3 tests as well. One alternative is to only run these tests under + // Python 3, but that does not seems like a good solution -- we could easily miss a + // Python 2 only regression then :O + not m.getName() = "namespace_package.namespace_module" +select m.getName(), name, defn diff --git a/python/ql/test/experimental/import-resolution/baz.py b/python/ql/test/experimental/import-resolution/baz.py new file mode 100644 index 00000000000..66838a315be --- /dev/null +++ b/python/ql/test/experimental/import-resolution/baz.py @@ -0,0 +1,6 @@ +from trace import * +enter(__file__) + +baz_attr = "baz_attr" + +exit(__file__) diff --git a/python/ql/test/experimental/import-resolution/block_flow_check.py b/python/ql/test/experimental/import-resolution/block_flow_check.py new file mode 100644 index 00000000000..cd939b037e6 --- /dev/null +++ b/python/ql/test/experimental/import-resolution/block_flow_check.py @@ -0,0 +1,14 @@ +from trace import * +enter(__file__) + +class SOURCE(object): + @staticmethod + def block_flow(): pass + +check("SOURCE", SOURCE, SOURCE, globals()) #$ prints=SOURCE + +SOURCE.block_flow() + +check("SOURCE", SOURCE, SOURCE, globals()) + +exit(__file__) diff --git a/python/ql/test/experimental/import-resolution/generous_export.py b/python/ql/test/experimental/import-resolution/generous_export.py new file mode 100644 index 00000000000..cbea96e19ce --- /dev/null +++ b/python/ql/test/experimental/import-resolution/generous_export.py @@ -0,0 +1,22 @@ +from trace import * +enter(__file__) + +class SOURCE(object): + @staticmethod + def block_flow(): pass + +check("SOURCE", SOURCE, SOURCE, globals()) #$ prints=SOURCE + +if eval("False"): + # With our current import resolution, this value for SOURCE will be considered to be + # a valid value at the end of this module, because it's the end of a use-use flow. + # This is clearly wrong, so our import resolution is a bit too generous on what is + # exported + print(SOURCE) + raise Exception() + +SOURCE.block_flow() + +check("SOURCE", SOURCE, SOURCE, globals()) + +exit(__file__) diff --git a/python/ql/test/experimental/import-resolution/has_defined_all.py b/python/ql/test/experimental/import-resolution/has_defined_all.py new file mode 100644 index 00000000000..9716a9a2ee1 --- /dev/null +++ b/python/ql/test/experimental/import-resolution/has_defined_all.py @@ -0,0 +1,9 @@ +from trace import * +enter(__file__) + +all_defined_foo = "all_defined_foo" +all_defined_bar = "all_defined_bar" + +__all__ = ["all_defined_foo"] + +exit(__file__) diff --git a/python/ql/test/experimental/import-resolution/has_defined_all_copy.py b/python/ql/test/experimental/import-resolution/has_defined_all_copy.py new file mode 100644 index 00000000000..bfcb1eb5054 --- /dev/null +++ b/python/ql/test/experimental/import-resolution/has_defined_all_copy.py @@ -0,0 +1,11 @@ +# a copy of `has_defined_all.py` that is imported by `has_defined_all_indirection.py` +# with its' own names such that we can check both `import *` without any cross-talk +from trace import * +enter(__file__) + +all_defined_foo_copy = "all_defined_foo_copy" +all_defined_bar_copy = "all_defined_bar_copy" + +__all__ = ["all_defined_foo_copy"] + +exit(__file__) diff --git a/python/ql/test/experimental/import-resolution/has_defined_all_indirection.py b/python/ql/test/experimental/import-resolution/has_defined_all_indirection.py new file mode 100644 index 00000000000..c928205fdcb --- /dev/null +++ b/python/ql/test/experimental/import-resolution/has_defined_all_indirection.py @@ -0,0 +1,6 @@ +from trace import * +enter(__file__) + +from has_defined_all_copy import * + +exit(__file__) diff --git a/python/ql/test/experimental/import-resolution/if_then_else_refined.py b/python/ql/test/experimental/import-resolution/if_then_else_refined.py new file mode 100644 index 00000000000..670c7f178e9 --- /dev/null +++ b/python/ql/test/experimental/import-resolution/if_then_else_refined.py @@ -0,0 +1,19 @@ +# combination of refined and if_then_else + +from trace import * +enter(__file__) + +class SOURCE(): pass + +# definition based on "random" choice in this case it will always go the the if-branch, +# but our analysis is not able to figure this out +if eval("True"): + src = SOURCE +else: + src = SOURCE + +src.foo = 42 + +check("src", src, src, globals()) #$ prints=SOURCE + +exit(__file__) diff --git a/python/ql/test/experimental/import-resolution/importflow.ql b/python/ql/test/experimental/import-resolution/importflow.ql index e6e51afa963..afb2278d1c5 100644 --- a/python/ql/test/experimental/import-resolution/importflow.ql +++ b/python/ql/test/experimental/import-resolution/importflow.ql @@ -11,6 +11,9 @@ private class SourceString extends DataFlow::Node { SourceString() { this.asExpr().(StrConst).getText() = contents and this.asExpr().getParent() instanceof Assign + or + this.asExpr().(ClassExpr).getInnerScope().getName() = "SOURCE" and + contents = "SOURCE" } string getContents() { result = contents } @@ -63,6 +66,10 @@ private class ImportConfiguration extends DataFlow::Configuration { override predicate isSink(DataFlow::Node sink) { sink = API::moduleImport("trace").getMember("check").getACall().getArg(1) } + + override predicate isBarrier(DataFlow::Node node) { + exists(DataFlow::MethodCallNode call | call.calls(node, "block_flow")) + } } class ResolutionTest extends InlineExpectationsTest { diff --git a/python/ql/test/experimental/import-resolution/main.py b/python/ql/test/experimental/import-resolution/main.py index 840da95a03c..ce1bee040f4 100644 --- a/python/ql/test/experimental/import-resolution/main.py +++ b/python/ql/test/experimental/import-resolution/main.py @@ -84,6 +84,52 @@ from attr_clash import clashing_attr, non_clashing_submodule #$ imports=attr_cla check("clashing_attr", clashing_attr, "clashing_attr", globals()) #$ prints=clashing_attr SPURIOUS: prints="<module attr_clash.clashing_attr>" check("non_clashing_submodule", non_clashing_submodule, "<module attr_clash.non_clashing_submodule>", globals()) #$ prints="<module attr_clash.non_clashing_submodule>" +import attr_clash.clashing_attr as _doesnt_matter #$ imports=attr_clash.clashing_attr as=_doesnt_matter +from attr_clash import clashing_attr, non_clashing_submodule #$ imports=attr_clash.clashing_attr as=clashing_attr imports=attr_clash.non_clashing_submodule as=non_clashing_submodule +check("clashing_attr", clashing_attr, "<module attr_clash.clashing_attr>", globals()) #$ prints="<module attr_clash.clashing_attr>" SPURIOUS: prints=clashing_attr + +# check that import * only imports the __all__ attributes +from has_defined_all import * +check("all_defined_foo", all_defined_foo, "all_defined_foo", globals()) #$ prints=all_defined_foo + +try: + check("all_defined_bar", all_defined_bar, "all_defined_bar", globals()) #$ SPURIOUS: prints=all_defined_bar + raise Exception("Did not get expected NameError") +except NameError as e: + if "all_defined_bar" in str(e): + print("Got expected NameError:", e) + else: + raise + +import has_defined_all # $ imports=has_defined_all as=has_defined_all +check("has_defined_all.all_defined_foo", has_defined_all.all_defined_foo, "all_defined_foo", globals()) #$ prints=all_defined_foo +check("has_defined_all.all_defined_bar", has_defined_all.all_defined_bar, "all_defined_bar", globals()) #$ prints=all_defined_bar + +# same check as above, but going through one level of indirection (which can make a difference) +from has_defined_all_indirection import * +check("all_defined_foo_copy", all_defined_foo_copy, "all_defined_foo_copy", globals()) #$ prints=all_defined_foo_copy + +try: + check("all_defined_bar_copy", all_defined_bar_copy, "all_defined_bar_copy", globals()) #$ SPURIOUS: prints=all_defined_bar_copy + raise Exception("Did not get expected NameError") +except NameError as e: + if "all_defined_bar_copy" in str(e): + print("Got expected NameError:", e) + else: + raise + +# same check as above, but going through one level of indirection (which can make a difference) +import has_defined_all_indirection # $ imports=has_defined_all_indirection as=has_defined_all_indirection +check("has_defined_all_indirection.all_defined_foo_copy", has_defined_all_indirection.all_defined_foo_copy, "all_defined_foo_copy", globals()) #$ prints=all_defined_foo_copy + +try: + check("has_defined_all_indirection.all_defined_bar_copy", has_defined_all_indirection.all_defined_bar_copy, "all_defined_bar_copy", globals()) + raise Exception("Did not get expected AttributeError") +except AttributeError as e: + if "all_defined_bar_copy" in str(e): + print("Got expected AttributeError:", e) + else: + raise # check that import * from an __init__ file works from package.subpackage2 import * @@ -93,6 +139,25 @@ check("subpackage2_attr", subpackage2_attr, "subpackage2_attr", globals()) #$ pr from if_then_else import if_then_else_defined check("if_then_else_defined", if_then_else_defined, "if_defined", globals()) #$ prints=if_defined prints=else_defined_1 prints=else_defined_2 +# check that refined definitions are handled correctly +import refined # $ imports=refined as=refined +check("refined.SOURCE", refined.SOURCE, refined.SOURCE, globals()) #$ prints=SOURCE + +import if_then_else_refined # $ imports=if_then_else_refined as=if_then_else_refined +check("if_then_else_refined.src", if_then_else_refined.src, if_then_else_refined.src, globals()) #$ prints=SOURCE + +import simplistic_reexport # $ imports=simplistic_reexport as=simplistic_reexport +check("simplistic_reexport.bar_attr", simplistic_reexport.bar_attr, "overwritten", globals()) #$ prints=overwritten SPURIOUS: prints=bar_attr +check("simplistic_reexport.baz_attr", simplistic_reexport.baz_attr, "overwritten", globals()) #$ prints=overwritten SPURIOUS: prints=baz_attr + +# check that we don't treat all assignments as being exports +import block_flow_check #$ imports=block_flow_check as=block_flow_check +check("block_flow_check.SOURCE", block_flow_check.SOURCE, block_flow_check.SOURCE, globals()) + +# show that import resolution is a bit too generous with definitions +import generous_export #$ imports=generous_export as=generous_export +check("generous_export.SOURCE", generous_export.SOURCE, generous_export.SOURCE, globals()) #$ SPURIOUS: prints=SOURCE + exit(__file__) print() diff --git a/python/ql/test/experimental/import-resolution/refined.py b/python/ql/test/experimental/import-resolution/refined.py new file mode 100644 index 00000000000..3694168c5df --- /dev/null +++ b/python/ql/test/experimental/import-resolution/refined.py @@ -0,0 +1,14 @@ +from trace import * +enter(__file__) + +class SOURCE(object): pass + +check("SOURCE", SOURCE, SOURCE, globals()) #$ prints=SOURCE + +SOURCE.foo = 42 +SOURCE.bar = 43 +SOURCE.baz = 44 + +check("SOURCE", SOURCE, SOURCE, globals()) #$ prints=SOURCE + +exit(__file__) diff --git a/python/ql/test/experimental/import-resolution/simplistic_reexport.py b/python/ql/test/experimental/import-resolution/simplistic_reexport.py new file mode 100644 index 00000000000..2847a8a66e0 --- /dev/null +++ b/python/ql/test/experimental/import-resolution/simplistic_reexport.py @@ -0,0 +1,19 @@ +# we might consider anything imported to also be exported, but this is not the case + +from trace import * +enter(__file__) + +from bar import bar_attr +check("bar_attr", bar_attr, "bar_attr", globals()) #$ prints=bar_attr + +bar_attr = "overwritten" +check("bar_attr", bar_attr, "overwritten", globals()) #$ prints=overwritten + + +from baz import * +check("baz_attr", baz_attr, "baz_attr", globals()) #$ MISSING: prints=baz_attr + +baz_attr = "overwritten" +check("baz_attr", baz_attr, "overwritten", globals()) #$ prints=overwritten + +exit(__file__) diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.expected b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.expected new file mode 100644 index 00000000000..ece6b8d6897 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.expected @@ -0,0 +1,12 @@ +edges +| TimingAttackAgainstHash.py:26:17:26:41 | ControlFlowNode for Attribute() | TimingAttackAgainstHash.py:27:24:27:32 | ControlFlowNode for signature | +| TimingAttackAgainstHash.py:30:12:30:47 | ControlFlowNode for Attribute() | TimingAttackAgainstHash.py:37:19:37:48 | ControlFlowNode for sign() | +nodes +| TimingAttackAgainstHash.py:26:17:26:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| TimingAttackAgainstHash.py:27:24:27:32 | ControlFlowNode for signature | semmle.label | ControlFlowNode for signature | +| TimingAttackAgainstHash.py:30:12:30:47 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| TimingAttackAgainstHash.py:37:19:37:48 | ControlFlowNode for sign() | semmle.label | ControlFlowNode for sign() | +subpaths +#select +| TimingAttackAgainstHash.py:27:24:27:32 | ControlFlowNode for signature | TimingAttackAgainstHash.py:26:17:26:41 | ControlFlowNode for Attribute() | TimingAttackAgainstHash.py:27:24:27:32 | ControlFlowNode for signature | Possible Timing attack against $@ validation. | signature | message | +| TimingAttackAgainstHash.py:37:19:37:48 | ControlFlowNode for sign() | TimingAttackAgainstHash.py:30:12:30:47 | ControlFlowNode for Attribute() | TimingAttackAgainstHash.py:37:19:37:48 | ControlFlowNode for sign() | Possible Timing attack against $@ validation. | MAC | message | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.qlref b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.qlref new file mode 100644 index 00000000000..73a8e6960ef --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.qlref @@ -0,0 +1 @@ +experimental/Security/CWE-208/TimingAttackAgainstHash/PossibleTimingAttackAgainstHash.ql diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.py b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.py new file mode 100644 index 00000000000..1d312f028eb --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHash/TimingAttackAgainstHash.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +""" +@Desc :Timing Attack Against Hash +""" +import hashlib +import hmac +from cryptography.hazmat.primitives import cmac +from cryptography.hazmat.primitives.ciphers import algorithms +from Crypto.Signature import pkcs1_15 +from Crypto.Hash import SHA256 +from Crypto.PublicKey import RSA + + +def UnsafeCmacCheck(actualCmac): + expected = cmac.CMAC(algorithms.AES(key)) + expected.update(b"message to authenticate") + expected.finalize() + return actualCmac == expected + + +def UnsafeCheckSignature(expected): + message = b'To be signed' + key = RSA.import_key(open('private_key.der').read()) + h = SHA256.new(message) + signature = pkcs1_15.new(key).sign(h) + return expected == signature + +def sign(pre_key, msg, alg): + return hmac.new(pre_key, msg, alg).digest() + +def verifyGood(msg, sig): + return constant_time_string_compare(sig, sign(key, msg, hashlib.sha256)) #good + +def verifyBad(msg, sig): + key = "e179017a-62b0-4996-8a38-e91aa9f1" + return sig == sign(key, msg, hashlib.sha256) #bad + +def constant_time_string_compare(a, b): + if len(a) != len(b): + return False + + result = 0 + + for x, y in zip(a, b): + result |= ord(x) ^ ord(y) + + return result == 0 diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeader.py b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeader.py new file mode 100644 index 00000000000..211c36274d7 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeader.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +""" +@Desc :Timing Attack Against Header +""" +from flask import Flask +from flask import request +import hmac + +app = Flask(__name__) + +@app.route('/bad') +def bad(): + if not request.headers.get('X-Auth-Token') == "token": + raise Exception('bad token') + return 'bad' + +@app.route('/good') +def good(): + tok = request.headers.get('X-Auth-Token') + if not hmac.compare_digest(tok, "token"): + raise Exception('bad token') + return 'good' + +if __name__ == '__main__': + app.debug = True + app.run() diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.expected b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.expected new file mode 100644 index 00000000000..14c8b8bf1eb --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.expected @@ -0,0 +1,6 @@ +edges +nodes +| TimingAttackAgainstHeader.py:14:12:14:46 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +subpaths +#select +| TimingAttackAgainstHeader.py:14:12:14:46 | ControlFlowNode for Attribute() | TimingAttackAgainstHeader.py:14:12:14:46 | ControlFlowNode for Attribute() | TimingAttackAgainstHeader.py:14:12:14:46 | ControlFlowNode for Attribute() | Timing attack against $@ validation. | TimingAttackAgainstHeader.py:14:12:14:46 | ControlFlowNode for Attribute() | client-supplied token | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.qlref b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.qlref new file mode 100644 index 00000000000..9da35da9d6d --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.qlref @@ -0,0 +1 @@ +experimental/Security/CWE-208/TimingAttackAgainstHeaderValue/TimingAttackAgainstHeaderValue.ql diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.expected b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.expected new file mode 100644 index 00000000000..ec99cbceec9 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.expected @@ -0,0 +1,33 @@ +edges +| TimingAttackAgainstSensitiveInfo.py:0:0:0:0 | ModuleVariableNode for TimingAttackAgainstSensitiveInfo.request | TimingAttackAgainstSensitiveInfo.py:14:8:14:14 | ControlFlowNode for request | +| TimingAttackAgainstSensitiveInfo.py:0:0:0:0 | ModuleVariableNode for TimingAttackAgainstSensitiveInfo.request | TimingAttackAgainstSensitiveInfo.py:15:20:15:26 | ControlFlowNode for request | +| TimingAttackAgainstSensitiveInfo.py:0:0:0:0 | ModuleVariableNode for TimingAttackAgainstSensitiveInfo.request | TimingAttackAgainstSensitiveInfo.py:20:8:20:14 | ControlFlowNode for request | +| TimingAttackAgainstSensitiveInfo.py:0:0:0:0 | ModuleVariableNode for TimingAttackAgainstSensitiveInfo.request | TimingAttackAgainstSensitiveInfo.py:21:20:21:26 | ControlFlowNode for request | +| TimingAttackAgainstSensitiveInfo.py:7:19:7:25 | ControlFlowNode for ImportMember | TimingAttackAgainstSensitiveInfo.py:7:19:7:25 | GSSA Variable request | +| TimingAttackAgainstSensitiveInfo.py:7:19:7:25 | GSSA Variable request | TimingAttackAgainstSensitiveInfo.py:0:0:0:0 | ModuleVariableNode for TimingAttackAgainstSensitiveInfo.request | +| TimingAttackAgainstSensitiveInfo.py:14:8:14:14 | ControlFlowNode for request | TimingAttackAgainstSensitiveInfo.py:15:20:15:31 | ControlFlowNode for Attribute | +| TimingAttackAgainstSensitiveInfo.py:15:20:15:26 | ControlFlowNode for request | TimingAttackAgainstSensitiveInfo.py:15:20:15:31 | ControlFlowNode for Attribute | +| TimingAttackAgainstSensitiveInfo.py:15:20:15:31 | ControlFlowNode for Attribute | TimingAttackAgainstSensitiveInfo.py:15:20:15:38 | ControlFlowNode for Subscript | +| TimingAttackAgainstSensitiveInfo.py:15:20:15:38 | ControlFlowNode for Subscript | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | +| TimingAttackAgainstSensitiveInfo.py:20:8:20:14 | ControlFlowNode for request | TimingAttackAgainstSensitiveInfo.py:21:20:21:31 | ControlFlowNode for Attribute | +| TimingAttackAgainstSensitiveInfo.py:21:20:21:26 | ControlFlowNode for request | TimingAttackAgainstSensitiveInfo.py:21:20:21:31 | ControlFlowNode for Attribute | +| TimingAttackAgainstSensitiveInfo.py:21:20:21:31 | ControlFlowNode for Attribute | TimingAttackAgainstSensitiveInfo.py:21:20:21:38 | ControlFlowNode for Subscript | +| TimingAttackAgainstSensitiveInfo.py:21:20:21:38 | ControlFlowNode for Subscript | TimingAttackAgainstSensitiveInfo.py:22:38:22:45 | ControlFlowNode for password | +nodes +| TimingAttackAgainstSensitiveInfo.py:0:0:0:0 | ModuleVariableNode for TimingAttackAgainstSensitiveInfo.request | semmle.label | ModuleVariableNode for TimingAttackAgainstSensitiveInfo.request | +| TimingAttackAgainstSensitiveInfo.py:7:19:7:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| TimingAttackAgainstSensitiveInfo.py:7:19:7:25 | GSSA Variable request | semmle.label | GSSA Variable request | +| TimingAttackAgainstSensitiveInfo.py:14:8:14:14 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| TimingAttackAgainstSensitiveInfo.py:15:20:15:26 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| TimingAttackAgainstSensitiveInfo.py:15:20:15:31 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| TimingAttackAgainstSensitiveInfo.py:15:20:15:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | semmle.label | ControlFlowNode for password | +| TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | semmle.label | ControlFlowNode for password | +| TimingAttackAgainstSensitiveInfo.py:20:8:20:14 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| TimingAttackAgainstSensitiveInfo.py:21:20:21:26 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | +| TimingAttackAgainstSensitiveInfo.py:21:20:21:31 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| TimingAttackAgainstSensitiveInfo.py:21:20:21:38 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| TimingAttackAgainstSensitiveInfo.py:22:38:22:45 | ControlFlowNode for password | semmle.label | ControlFlowNode for password | +subpaths +#select +| TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | Timing attack against $@ validation. | TimingAttackAgainstSensitiveInfo.py:16:16:16:23 | ControlFlowNode for password | client-supplied token | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.qlref b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.qlref new file mode 100644 index 00000000000..acfe13f6aad --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.qlref @@ -0,0 +1 @@ +experimental/Security/CWE-208/TimingAttackAgainstSensitiveInfo/PossibleTimingAttackAgainstSensitiveInfo.ql diff --git a/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.py b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.py new file mode 100644 index 00000000000..a34b3b7c5ae --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-208/TimingAttackAgainstSensitiveInfo/TimingAttackAgainstSensitiveInfo.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +""" +@Desc :timing attack against Secret +""" +from flask import Flask +from flask import request +from django.utils.crypto import constant_time_compare + +app = Flask(__name__) + +@app.route('/bad', methods = ['POST', 'GET']) +def bad(): + if request.method == 'POST': + password = request.form['pwd'] + return password == "1234" + +@app.route('/good', methods = ['POST', 'GET']) +def good(): + if request.method == 'POST': + password = request.form['pwd'] + return constant_time_compare(password, "1234") + +if __name__ == '__main__': + app.debug = True + app.run() diff --git a/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/UnsafeUsageOfClientSideEncryptionVersion.expected b/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/UnsafeUsageOfClientSideEncryptionVersion.expected new file mode 100644 index 00000000000..12dfeafb931 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/UnsafeUsageOfClientSideEncryptionVersion.expected @@ -0,0 +1,66 @@ +edges +| test.py:0:0:0:0 | ModuleVariableNode for test.BSC | test.py:7:19:7:21 | ControlFlowNode for BSC | +| test.py:0:0:0:0 | ModuleVariableNode for test.BSC | test.py:35:19:35:21 | ControlFlowNode for BSC | +| test.py:0:0:0:0 | ModuleVariableNode for test.BSC | test.py:66:19:66:21 | ControlFlowNode for BSC | +| test.py:3:1:3:3 | GSSA Variable BSC | test.py:0:0:0:0 | ModuleVariableNode for test.BSC | +| test.py:3:7:3:51 | ControlFlowNode for Attribute() | test.py:3:1:3:3 | GSSA Variable BSC | +| test.py:7:19:7:21 | ControlFlowNode for BSC | test.py:8:5:8:15 | ControlFlowNode for blob_client | +| test.py:8:5:8:15 | ControlFlowNode for blob_client | test.py:9:5:9:15 | ControlFlowNode for blob_client | +| test.py:9:5:9:15 | ControlFlowNode for blob_client | test.py:9:5:9:15 | [post] ControlFlowNode for blob_client | +| test.py:9:5:9:15 | [post] ControlFlowNode for blob_client | test.py:11:9:11:19 | ControlFlowNode for blob_client | +| test.py:15:27:15:71 | ControlFlowNode for Attribute() | test.py:16:5:16:23 | ControlFlowNode for blob_service_client | +| test.py:16:5:16:23 | ControlFlowNode for blob_service_client | test.py:17:5:17:23 | ControlFlowNode for blob_service_client | +| test.py:17:5:17:23 | ControlFlowNode for blob_service_client | test.py:17:5:17:23 | [post] ControlFlowNode for blob_service_client | +| test.py:17:5:17:23 | [post] ControlFlowNode for blob_service_client | test.py:21:9:21:19 | ControlFlowNode for blob_client | +| test.py:25:24:25:66 | ControlFlowNode for Attribute() | test.py:26:5:26:20 | ControlFlowNode for container_client | +| test.py:26:5:26:20 | ControlFlowNode for container_client | test.py:27:5:27:20 | ControlFlowNode for container_client | +| test.py:27:5:27:20 | ControlFlowNode for container_client | test.py:27:5:27:20 | [post] ControlFlowNode for container_client | +| test.py:27:5:27:20 | [post] ControlFlowNode for container_client | test.py:31:9:31:19 | ControlFlowNode for blob_client | +| test.py:35:19:35:21 | ControlFlowNode for BSC | test.py:36:5:36:15 | ControlFlowNode for blob_client | +| test.py:36:5:36:15 | ControlFlowNode for blob_client | test.py:37:5:37:15 | ControlFlowNode for blob_client | +| test.py:37:5:37:15 | ControlFlowNode for blob_client | test.py:37:5:37:15 | [post] ControlFlowNode for blob_client | +| test.py:37:5:37:15 | [post] ControlFlowNode for blob_client | test.py:43:9:43:19 | ControlFlowNode for blob_client | +| test.py:66:19:66:21 | ControlFlowNode for BSC | test.py:67:5:67:15 | ControlFlowNode for blob_client | +| test.py:67:5:67:15 | ControlFlowNode for blob_client | test.py:68:5:68:15 | ControlFlowNode for blob_client | +| test.py:68:5:68:15 | ControlFlowNode for blob_client | test.py:68:5:68:15 | [post] ControlFlowNode for blob_client | +| test.py:68:5:68:15 | [post] ControlFlowNode for blob_client | test.py:69:12:69:22 | ControlFlowNode for blob_client | +| test.py:69:12:69:22 | ControlFlowNode for blob_client | test.py:73:10:73:33 | ControlFlowNode for get_unsafe_blob_client() | +| test.py:73:10:73:33 | ControlFlowNode for get_unsafe_blob_client() | test.py:75:9:75:10 | ControlFlowNode for bc | +nodes +| test.py:0:0:0:0 | ModuleVariableNode for test.BSC | semmle.label | ModuleVariableNode for test.BSC | +| test.py:3:1:3:3 | GSSA Variable BSC | semmle.label | GSSA Variable BSC | +| test.py:3:7:3:51 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| test.py:7:19:7:21 | ControlFlowNode for BSC | semmle.label | ControlFlowNode for BSC | +| test.py:8:5:8:15 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client | +| test.py:9:5:9:15 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client | +| test.py:9:5:9:15 | [post] ControlFlowNode for blob_client | semmle.label | [post] ControlFlowNode for blob_client | +| test.py:11:9:11:19 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client | +| test.py:15:27:15:71 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| test.py:16:5:16:23 | ControlFlowNode for blob_service_client | semmle.label | ControlFlowNode for blob_service_client | +| test.py:17:5:17:23 | ControlFlowNode for blob_service_client | semmle.label | ControlFlowNode for blob_service_client | +| test.py:17:5:17:23 | [post] ControlFlowNode for blob_service_client | semmle.label | [post] ControlFlowNode for blob_service_client | +| test.py:21:9:21:19 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client | +| test.py:25:24:25:66 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| test.py:26:5:26:20 | ControlFlowNode for container_client | semmle.label | ControlFlowNode for container_client | +| test.py:27:5:27:20 | ControlFlowNode for container_client | semmle.label | ControlFlowNode for container_client | +| test.py:27:5:27:20 | [post] ControlFlowNode for container_client | semmle.label | [post] ControlFlowNode for container_client | +| test.py:31:9:31:19 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client | +| test.py:35:19:35:21 | ControlFlowNode for BSC | semmle.label | ControlFlowNode for BSC | +| test.py:36:5:36:15 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client | +| test.py:37:5:37:15 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client | +| test.py:37:5:37:15 | [post] ControlFlowNode for blob_client | semmle.label | [post] ControlFlowNode for blob_client | +| test.py:43:9:43:19 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client | +| test.py:66:19:66:21 | ControlFlowNode for BSC | semmle.label | ControlFlowNode for BSC | +| test.py:67:5:67:15 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client | +| test.py:68:5:68:15 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client | +| test.py:68:5:68:15 | [post] ControlFlowNode for blob_client | semmle.label | [post] ControlFlowNode for blob_client | +| test.py:69:12:69:22 | ControlFlowNode for blob_client | semmle.label | ControlFlowNode for blob_client | +| test.py:73:10:73:33 | ControlFlowNode for get_unsafe_blob_client() | semmle.label | ControlFlowNode for get_unsafe_blob_client() | +| test.py:75:9:75:10 | ControlFlowNode for bc | semmle.label | ControlFlowNode for bc | +subpaths +#select +| test.py:11:9:11:19 | ControlFlowNode for blob_client | test.py:3:7:3:51 | ControlFlowNode for Attribute() | test.py:11:9:11:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption | +| test.py:21:9:21:19 | ControlFlowNode for blob_client | test.py:15:27:15:71 | ControlFlowNode for Attribute() | test.py:21:9:21:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption | +| test.py:31:9:31:19 | ControlFlowNode for blob_client | test.py:25:24:25:66 | ControlFlowNode for Attribute() | test.py:31:9:31:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption | +| test.py:43:9:43:19 | ControlFlowNode for blob_client | test.py:3:7:3:51 | ControlFlowNode for Attribute() | test.py:43:9:43:19 | ControlFlowNode for blob_client | Unsafe usage of v1 version of Azure Storage client-side encryption | +| test.py:75:9:75:10 | ControlFlowNode for bc | test.py:3:7:3:51 | ControlFlowNode for Attribute() | test.py:75:9:75:10 | ControlFlowNode for bc | Unsafe usage of v1 version of Azure Storage client-side encryption | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/UnsafeUsageOfClientSideEncryptionVersion.qlref b/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/UnsafeUsageOfClientSideEncryptionVersion.qlref new file mode 100644 index 00000000000..b737b32c815 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/UnsafeUsageOfClientSideEncryptionVersion.qlref @@ -0,0 +1 @@ +experimental/Security/CWE-327/Azure/UnsafeUsageOfClientSideEncryptionVersion.ql diff --git a/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/test.py b/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/test.py new file mode 100644 index 00000000000..32fa60c6193 --- /dev/null +++ b/python/ql/test/experimental/query-tests/Security/CWE-327-UnsafeUsageOfClientSideEncryptionVersion/test.py @@ -0,0 +1,89 @@ +from azure.storage.blob import BlobServiceClient, ContainerClient, BlobClient + +BSC = BlobServiceClient.from_connection_string(...) + +def unsafe(): + # does not set encryption_version to 2.0, default is unsafe + blob_client = BSC.get_blob_client(...) + blob_client.require_encryption = True + blob_client.key_encryption_key = ... + with open("decryptedcontentfile.txt", "rb") as stream: + blob_client.upload_blob(stream) # BAD + + +def unsafe_setting_on_blob_service_client(): + blob_service_client = BlobServiceClient.from_connection_string(...) + blob_service_client.require_encryption = True + blob_service_client.key_encryption_key = ... + + blob_client = blob_service_client.get_blob_client(...) + with open("decryptedcontentfile.txt", "rb") as stream: + blob_client.upload_blob(stream) + + +def unsafe_setting_on_container_client(): + container_client = ContainerClient.from_connection_string(...) + container_client.require_encryption = True + container_client.key_encryption_key = ... + + blob_client = container_client.get_blob_client(...) + with open("decryptedcontentfile.txt", "rb") as stream: + blob_client.upload_blob(stream) + + +def potentially_unsafe(use_new_version=False): + blob_client = BSC.get_blob_client(...) + blob_client.require_encryption = True + blob_client.key_encryption_key = ... + + if use_new_version: + blob_client.encryption_version = '2.0' + + with open("decryptedcontentfile.txt", "rb") as stream: + blob_client.upload_blob(stream) # BAD + + +def safe(): + blob_client = BSC.get_blob_client(...) + blob_client.require_encryption = True + blob_client.key_encryption_key = ... + # GOOD: Must use `encryption_version` set to `2.0` + blob_client.encryption_version = '2.0' + with open("decryptedcontentfile.txt", "rb") as stream: + blob_client.upload_blob(stream) # OK + + +def safe_different_order(): + blob_client: BlobClient = BSC.get_blob_client(...) + blob_client.encryption_version = '2.0' + blob_client.require_encryption = True + blob_client.key_encryption_key = ... + with open("decryptedcontentfile.txt", "rb") as stream: + blob_client.upload_blob(stream) # OK + + +def get_unsafe_blob_client(): + blob_client = BSC.get_blob_client(...) + blob_client.require_encryption = True + blob_client.key_encryption_key = ... + return blob_client + + +def unsafe_with_calls(): + bc = get_unsafe_blob_client() + with open("decryptedcontentfile.txt", "rb") as stream: + bc.upload_blob(stream) # BAD + + +def get_safe_blob_client(): + blob_client = BSC.get_blob_client(...) + blob_client.require_encryption = True + blob_client.key_encryption_key = ... + blob_client.encryption_version = '2.0' + return blob_client + + +def safe_with_calls(): + bc = get_safe_blob_client() + with open("decryptedcontentfile.txt", "rb") as stream: + bc.upload_blob(stream) # OK diff --git a/python/ql/test/library-tests/frameworks/aiosqlite/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/aiosqlite/ConceptsTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/library-tests/frameworks/aiosqlite/ConceptsTest.ql b/python/ql/test/library-tests/frameworks/aiosqlite/ConceptsTest.ql new file mode 100644 index 00000000000..b557a0bccb6 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/aiosqlite/ConceptsTest.ql @@ -0,0 +1,2 @@ +import python +import experimental.meta.ConceptsTest diff --git a/python/ql/test/library-tests/frameworks/aiosqlite/test.py b/python/ql/test/library-tests/frameworks/aiosqlite/test.py new file mode 100644 index 00000000000..888f9377694 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/aiosqlite/test.py @@ -0,0 +1,27 @@ +import aiosqlite + +# see https://pypi.org/project/aiosqlite/ + +async def test(): + db = await aiosqlite.connect(...) + + await db.execute("sql") # $ getSql="sql" constructedSql="sql" + await db.execute(sql="sql") # $ getSql="sql" constructedSql="sql" + + cursor = await db.cursor() + cursor.execute("sql") # $ constructedSql="sql" + + cursor = await db.execute("sql") # $ getSql="sql" constructedSql="sql" + cursor.execute("sql") # $ constructedSql="sql" + + async with aiosqlite.connect(...) as db: + db.row_factory = aiosqlite.Row + async with db.execute("sql") as cursor: # $ getSql="sql" constructedSql="sql" + async for row in cursor: + print(row['column']) + + # nonstandard + await db.execute_insert("sql") # $ getSql="sql" constructedSql="sql" + await db.execute_fetchall("sql") # $ getSql="sql" constructedSql="sql" + await db.executescript("sql") # $ getSql="sql" constructedSql="sql" + await db.executescript(sql_script="sql") # $ getSql="sql" constructedSql="sql" diff --git a/python/ql/test/library-tests/frameworks/asyncpg/test.py b/python/ql/test/library-tests/frameworks/asyncpg/test.py index ad99751ba3d..3286c6795e8 100644 --- a/python/ql/test/library-tests/frameworks/asyncpg/test.py +++ b/python/ql/test/library-tests/frameworks/asyncpg/test.py @@ -22,6 +22,9 @@ async def test_connection(): finally: await conn.close() + conn = await asyncpg.connection.connect() + conn.execute("sql") # $ mad-sink[sql-injection]="sql" + async def test_prepared_statement(): conn = await asyncpg.connect() diff --git a/python/ql/test/library-tests/frameworks/cassandra-driver/ConceptsTest.expected b/python/ql/test/library-tests/frameworks/cassandra-driver/ConceptsTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/library-tests/frameworks/cassandra-driver/ConceptsTest.ql b/python/ql/test/library-tests/frameworks/cassandra-driver/ConceptsTest.ql new file mode 100644 index 00000000000..b557a0bccb6 --- /dev/null +++ b/python/ql/test/library-tests/frameworks/cassandra-driver/ConceptsTest.ql @@ -0,0 +1,2 @@ +import python +import experimental.meta.ConceptsTest diff --git a/python/ql/test/library-tests/frameworks/cassandra-driver/test.py b/python/ql/test/library-tests/frameworks/cassandra-driver/test.py new file mode 100644 index 00000000000..dfcdb133e4b --- /dev/null +++ b/python/ql/test/library-tests/frameworks/cassandra-driver/test.py @@ -0,0 +1,12 @@ +from cassandra.cluster import Cluster + +cluster = Cluster(...) +session = cluster.connect() + +session.execute("sql") # $ getSql="sql" + +future = session.execute_async("sql") # $ constructedSql="sql" +future.result() + +prepared = session.prepare("sql") # $ constructedSql="sql" +session.execute(prepared) # $ SPURIOUS: getSql=prepared diff --git a/python/ql/test/library-tests/frameworks/stdlib/pep249.py b/python/ql/test/library-tests/frameworks/stdlib/pep249.py index 3b82e5fb61a..6f601f5b6c2 100644 --- a/python/ql/test/library-tests/frameworks/stdlib/pep249.py +++ b/python/ql/test/library-tests/frameworks/stdlib/pep249.py @@ -6,3 +6,10 @@ db.execute("some sql", (42,)) # $ getSql="some sql" cursor = db.cursor() cursor.execute("some sql", (42,)) # $ getSql="some sql" +cursor.executescript("sql") # $ getSql="sql" +cursor.executescript(sql_script="sql") # $ getSql="sql" + +import sqlite3.dbapi2 +conn = sqlite3.dbapi2.connect() +cursor = conn.cursor() +cursor.execute("some sql") # $ getSql="some sql" diff --git a/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.expected b/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.expected index d6bc954de82..491a2382364 100644 --- a/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.expected +++ b/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.expected @@ -10,17 +10,26 @@ | InsecureProtocol.py:19:1:19:19 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified by $@. | InsecureProtocol.py:19:1:19:19 | ControlFlowNode for Attribute() | call to SSL.Context | | InsecureProtocol.py:23:1:23:43 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified by $@. | InsecureProtocol.py:23:1:23:43 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | | InsecureProtocol.py:24:1:24:35 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version SSLv2 specified by $@. | InsecureProtocol.py:24:1:24:35 | ControlFlowNode for SSLContext() | call to SSLContext | +| import_all_one_file.py:25:14:25:45 | ControlFlowNode for copy_completely_insecure_context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | import_all_one_file.py:9:36:9:67 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| import_all_one_file.py:25:14:25:45 | ControlFlowNode for copy_completely_insecure_context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | import_all_one_file.py:9:36:9:67 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| import_all_one_file.py:29:14:29:39 | ControlFlowNode for copy_also_insecure_context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | import_all_one_file.py:12:30:12:61 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| import_use.py:13:14:13:40 | ControlFlowNode for completely_insecure_context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | import_def.py:7:31:7:62 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| import_use.py:13:14:13:40 | ControlFlowNode for completely_insecure_context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | import_def.py:7:31:7:62 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| import_use.py:17:14:17:34 | ControlFlowNode for also_insecure_context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | import_def.py:10:25:10:56 | ControlFlowNode for Attribute() | call to ssl.SSLContext | | pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv2 allowed by $@. | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | | pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@. | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | | pyOpenSSL_fluent.py:18:27:18:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv2 allowed by $@. | pyOpenSSL_fluent.py:15:15:15:44 | ControlFlowNode for Attribute() | call to SSL.Context | | pyOpenSSL_fluent.py:18:27:18:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@. | pyOpenSSL_fluent.py:15:15:15:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:18:27:18:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | pyOpenSSL_fluent.py:15:15:15:44 | ControlFlowNode for Attribute() | call to SSL.Context | | ssl_fluent.py:9:14:9:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | ssl_fluent.py:6:15:6:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | | ssl_fluent.py:9:14:9:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:6:15:6:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | | ssl_fluent.py:19:14:19:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:15:15:15:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | | ssl_fluent.py:28:14:28:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:24:15:24:53 | ControlFlowNode for Attribute() | call to ssl.SSLContext | | ssl_fluent.py:37:14:37:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:33:15:33:53 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:57:14:57:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv2 allowed by $@. | ssl_fluent.py:54:15:54:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:57:14:57:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@. | ssl_fluent.py:54:15:54:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:57:14:57:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | ssl_fluent.py:54:15:54:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:57:14:57:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:54:15:54:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | | ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | ssl_fluent.py:62:12:62:43 | ControlFlowNode for Attribute() | call to ssl.SSLContext | | ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | ssl_fluent.py:101:15:101:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | | ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:62:12:62:43 | ControlFlowNode for Attribute() | call to ssl.SSLContext | diff --git a/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/import_all_one_file.py b/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/import_all_one_file.py new file mode 100644 index 00000000000..aab459ceeea --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/import_all_one_file.py @@ -0,0 +1,30 @@ +# use to compare alerts without import + +import ssl + +copy_secure_context = ssl.SSLContext(ssl.PROTOCOL_TLS) +copy_secure_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 + +# this is just to allow us to see how un-altered exports work +copy_completely_insecure_context = ssl.SSLContext(ssl.PROTOCOL_TLS) + +# and an insecure export that is refined +copy_also_insecure_context = ssl.SSLContext(ssl.PROTOCOL_TLS) +copy_also_insecure_context.options |= ssl.OP_NO_TLSv1 + + + +import socket +hostname = 'www.python.org' + +with socket.create_connection((hostname, 443)) as sock: + with copy_secure_context.wrap_socket(sock, server_hostname=hostname) as ssock: + print(ssock.version()) + +with socket.create_connection((hostname, 443)) as sock: + with copy_completely_insecure_context.wrap_socket(sock, server_hostname=hostname) as ssock: + print(ssock.version()) + +with socket.create_connection((hostname, 443)) as sock: + with copy_also_insecure_context.wrap_socket(sock, server_hostname=hostname) as ssock: + print(ssock.version()) diff --git a/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/import_def.py b/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/import_def.py new file mode 100644 index 00000000000..d8e37542b94 --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/import_def.py @@ -0,0 +1,11 @@ +import ssl + +secure_context = ssl.SSLContext(ssl.PROTOCOL_TLS) +secure_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 + +# this is just to allow us to see how un-altered exports work +completely_insecure_context = ssl.SSLContext(ssl.PROTOCOL_TLS) + +# and an insecure export that is refined +also_insecure_context = ssl.SSLContext(ssl.PROTOCOL_TLS) +also_insecure_context.options |= ssl.OP_NO_TLSv1 diff --git a/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/import_use.py b/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/import_use.py new file mode 100644 index 00000000000..3c12fd81355 --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/import_use.py @@ -0,0 +1,18 @@ +# check that query works properly with imports + +import socket +from import_def import secure_context, completely_insecure_context, also_insecure_context + +hostname = 'www.python.org' + +with socket.create_connection((hostname, 443)) as sock: + with secure_context.wrap_socket(sock, server_hostname=hostname) as ssock: + print(ssock.version()) + +with socket.create_connection((hostname, 443)) as sock: + with completely_insecure_context.wrap_socket(sock, server_hostname=hostname) as ssock: + print(ssock.version()) + +with socket.create_connection((hostname, 443)) as sock: + with also_insecure_context.wrap_socket(sock, server_hostname=hostname) as ssock: + print(ssock.version()) diff --git a/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/PolynomialBackTracking.expected b/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/PolynomialBackTracking.expected index 21215fc17b3..1aa6d91f343 100644 --- a/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/PolynomialBackTracking.expected +++ b/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/PolynomialBackTracking.expected @@ -2,3 +2,4 @@ | test.py:9:14:9:29 | Str | test.py:9:27:9:29 | \\d+ | Strings starting with '0.9' and with many repetitions of '99' can start matching anywhere after the start of the preceeding \\d+ | | test.py:11:22:11:33 | Str | test.py:11:31:11:33 | \\s+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+$ | | test.py:18:14:18:25 | Str | test.py:18:23:18:25 | \\s+ | Strings with many repetitions of ' ' can start matching anywhere after the start of the preceeding \\s+$ | +| test.py:20:23:20:274 | Str | test.py:20:273:20:274 | .* | Strings starting with 'AAAAAAAAAAAAAAAAAAAABBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC' and with many repetitions of 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC' can start matching anywhere after the start of the preceeding (AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)(AA\|BB)C.*Y | diff --git a/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/PolynomialReDoS.expected b/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/PolynomialReDoS.expected index ccbc591eb85..396a7de9a84 100644 --- a/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/PolynomialReDoS.expected +++ b/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/PolynomialReDoS.expected @@ -29,3 +29,4 @@ subpaths | test.py:9:32:9:35 | ControlFlowNode for text | test.py:2:26:2:32 | ControlFlowNode for ImportMember | test.py:9:32:9:35 | ControlFlowNode for text | This $@ that depends on a $@ may run slow on strings starting with '0.9' and with many repetitions of '99'. | test.py:9:27:9:29 | \\d+ | regular expression | test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | test.py:12:17:12:20 | ControlFlowNode for text | test.py:2:26:2:32 | ControlFlowNode for ImportMember | test.py:12:17:12:20 | ControlFlowNode for text | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | test.py:11:31:11:33 | \\s+ | regular expression | test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | | test.py:16:24:16:30 | ControlFlowNode for my_text | test.py:2:26:2:32 | ControlFlowNode for ImportMember | test.py:16:24:16:30 | ControlFlowNode for my_text | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | test.py:18:23:18:25 | \\s+ | regular expression | test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| test.py:21:18:21:21 | ControlFlowNode for text | test.py:2:26:2:32 | ControlFlowNode for ImportMember | test.py:21:18:21:21 | ControlFlowNode for text | This $@ that depends on a $@ may run slow on strings starting with 'AAAAAAAAAAAAAAAAAAAABBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC' and with many repetitions of 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC'. | test.py:20:273:20:274 | .* | regular expression | test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/test.py b/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/test.py index a6b75b4bd38..622fa6803b9 100644 --- a/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/test.py +++ b/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/test.py @@ -17,6 +17,6 @@ def code_execution(): indirect(r"^\s+|\s+$", text) - reg2 = re.compile(r"(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)C.*") + reg2 = re.compile(r"(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)C.*Y") reg2.sub("", text) # NOT OK diff --git a/ql/Cargo.lock b/ql/Cargo.lock index 08d54ab697a..41b76f14cfc 100644 Binary files a/ql/Cargo.lock and b/ql/Cargo.lock differ diff --git a/ql/Cargo.toml b/ql/Cargo.toml index 4bc60c3333d..5e42fc8d5e5 100644 --- a/ql/Cargo.toml +++ b/ql/Cargo.toml @@ -1,8 +1,5 @@ [workspace] members = [ - "autobuilder", "extractor", - "generator", - "node-types", "buramu", ] diff --git a/ql/autobuilder/Cargo.toml b/ql/autobuilder/Cargo.toml deleted file mode 100644 index ac39f025ade..00000000000 --- a/ql/autobuilder/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "ql-autobuilder" -version = "0.1.0" -authors = ["GitHub"] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] diff --git a/ql/buramu/Cargo.toml b/ql/buramu/Cargo.toml index c7e1918975d..5b87a8a90be 100644 --- a/ql/buramu/Cargo.toml +++ b/ql/buramu/Cargo.toml @@ -9,4 +9,4 @@ edition = "2018" lazy_static = "1.4.0" chrono = "0.4.24" rayon = "1.7.0" -regex = "1.7.1" +regex = "1.7.3" diff --git a/ql/extractor/Cargo.toml b/ql/extractor/Cargo.toml index 308953d1f8f..fe4712a03d5 100644 --- a/ql/extractor/Cargo.toml +++ b/ql/extractor/Cargo.toml @@ -7,8 +7,6 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -flate2 = "1.0" -node-types = { path = "../node-types" } tree-sitter = ">= 0.20, < 0.21" tree-sitter-ql = { git = "https://github.com/tree-sitter/tree-sitter-ql.git", rev = "d08db734f8dc52f6bc04db53a966603122bc6985"} tree-sitter-ql-dbscheme = { git = "https://github.com/erik-krogh/tree-sitter-ql-dbscheme.git", rev = "63e1344353f63931e88bfbc2faa2e78e1421b213"} @@ -19,5 +17,5 @@ clap = "2.33" tracing = "0.1" tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } rayon = "1.7.0" -num_cpus = "1.14.0" -regex = "1.7.1" +regex = "1.7.3" +codeql-extractor = { path = "../../shared/tree-sitter-extractor" } diff --git a/ql/autobuilder/src/main.rs b/ql/extractor/src/bin/autobuilder.rs similarity index 100% rename from ql/autobuilder/src/main.rs rename to ql/extractor/src/bin/autobuilder.rs diff --git a/ql/extractor/src/main.rs b/ql/extractor/src/bin/extractor.rs similarity index 82% rename from ql/extractor/src/main.rs rename to ql/extractor/src/bin/extractor.rs index da7f263e7ef..210abaf49d4 100644 --- a/ql/extractor/src/main.rs +++ b/ql/extractor/src/bin/extractor.rs @@ -1,41 +1,9 @@ -mod extractor; -mod trap; - -extern crate num_cpus; - use rayon::prelude::*; use std::fs; use std::io::BufRead; use std::path::{Path, PathBuf}; -/** - * Gets the number of threads the extractor should use, by reading the - * CODEQL_THREADS environment variable and using it as described in the - * extractor spec: - * - * "If the number is positive, it indicates the number of threads that should - * be used. If the number is negative or zero, it should be added to the number - * of cores available on the machine to determine how many threads to use - * (minimum of 1). If unspecified, should be considered as set to -1." - */ -fn num_codeql_threads() -> usize { - let threads_str = std::env::var("CODEQL_THREADS").unwrap_or_else(|_| "-1".to_owned()); - match threads_str.parse::<i32>() { - Ok(num) if num <= 0 => { - let reduction = -num as usize; - std::cmp::max(1, num_cpus::get() - reduction) - } - Ok(num) => num as usize, - - Err(_) => { - tracing::error!( - "Unable to parse CODEQL_THREADS value '{}'; defaulting to 1 thread.", - &threads_str - ); - 1 - } - } -} +use codeql_extractor::{diagnostics, extractor, node_types, trap}; fn main() -> std::io::Result<()> { tracing_subscriber::fmt() @@ -45,7 +13,23 @@ fn main() -> std::io::Result<()> { .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) .init(); - let num_threads = num_codeql_threads(); + let diagnostics = diagnostics::DiagnosticLoggers::new("ql"); + let mut main_thread_logger = diagnostics.logger(); + let num_threads = match codeql_extractor::options::num_threads() { + Ok(num) => num, + Err(e) => { + main_thread_logger.write( + main_thread_logger + .new_entry("configuration-error", "Configuration error") + .message( + "{}; defaulting to 1 thread.", + &[diagnostics::MessageArg::Code(&e)], + ) + .severity(diagnostics::Severity::Warning), + ); + 1 + } + }; tracing::info!( "Using {} {}", num_threads, @@ -55,6 +39,20 @@ fn main() -> std::io::Result<()> { "threads" } ); + let trap_compression = match trap::Compression::from_env("CODEQL_QL_TRAP_COMPRESSION") { + Ok(x) => x, + Err(e) => { + main_thread_logger.write( + main_thread_logger + .new_entry("configuration-error", "Configuration error") + .message("{}; using gzip.", &[diagnostics::MessageArg::Code(&e)]) + .severity(diagnostics::Severity::Warning), + ); + trap::Compression::Gzip + } + }; + drop(main_thread_logger); + rayon::ThreadPoolBuilder::new() .num_threads(num_threads) .build_global() @@ -79,7 +77,6 @@ fn main() -> std::io::Result<()> { .value_of("output-dir") .expect("missing --output-dir"); let trap_dir = PathBuf::from(trap_dir); - let trap_compression = trap::Compression::from_env("CODEQL_QL_TRAP_COMPRESSION"); let file_list = matches.value_of("file-list").expect("missing --file-list"); let file_list = fs::File::open(file_list)?; @@ -119,26 +116,29 @@ fn main() -> std::io::Result<()> { let source = std::fs::read(&path)?; let code_ranges = vec![]; let mut trap_writer = trap::Writer::new(); + let mut diagnostics_writer = diagnostics.logger(); if line.ends_with(".dbscheme") { extractor::extract( dbscheme, "dbscheme", &dbscheme_schema, + &mut diagnostics_writer, &mut trap_writer, &path, &source, &code_ranges, - )? + ) } else if line.ends_with("qlpack.yml") { extractor::extract( yaml, "yaml", &yaml_schema, + &mut diagnostics_writer, &mut trap_writer, &path, &source, &code_ranges, - )? + ) } else if line.ends_with(".json") || line.ends_with(".jsonl") || line.ends_with(".jsonc") @@ -147,31 +147,34 @@ fn main() -> std::io::Result<()> { json, "json", &json_schema, + &mut diagnostics_writer, &mut trap_writer, &path, &source, &code_ranges, - )? + ) } else if line.ends_with(".blame") { extractor::extract( blame, "blame", &blame_schema, + &mut diagnostics_writer, &mut trap_writer, &path, &source, &code_ranges, - )? + ) } else { extractor::extract( language, "ql", &schema, + &mut diagnostics_writer, &mut trap_writer, &path, &source, &code_ranges, - )? + ) } std::fs::create_dir_all(&src_archive_file.parent().unwrap())?; std::fs::copy(&path, &src_archive_file)?; diff --git a/ql/generator/src/main.rs b/ql/extractor/src/bin/generator.rs similarity index 99% rename from ql/generator/src/main.rs rename to ql/extractor/src/bin/generator.rs index 8c6bf63d859..8baed6d21a5 100644 --- a/ql/generator/src/main.rs +++ b/ql/extractor/src/bin/generator.rs @@ -1,9 +1,3 @@ -mod dbscheme; -mod language; -mod ql; -mod ql_gen; - -use language::Language; use std::collections::BTreeMap as Map; use std::collections::BTreeSet as Set; use std::fs::File; @@ -11,6 +5,9 @@ use std::io::LineWriter; use std::io::Write; use std::path::PathBuf; +use codeql_extractor::generator::{dbscheme, language::Language, ql, ql_gen}; +use codeql_extractor::node_types; + /// Given the name of the parent node, and its field information, returns a pair, /// the first of which is the field's type. The second is an optional dbscheme /// entry that should be added. diff --git a/ql/extractor/src/extractor.rs b/ql/extractor/src/extractor.rs deleted file mode 100644 index f5557e5a188..00000000000 --- a/ql/extractor/src/extractor.rs +++ /dev/null @@ -1,650 +0,0 @@ -use crate::trap; -use node_types::{EntryKind, Field, NodeTypeMap, Storage, TypeName}; -use std::collections::BTreeMap as Map; -use std::collections::BTreeSet as Set; -use std::fmt; -use std::path::Path; - -use tracing::{error, info, span, Level}; -use tree_sitter::{Language, Node, Parser, Range, Tree}; - -pub fn populate_file(writer: &mut trap::Writer, absolute_path: &Path) -> trap::Label { - let (file_label, fresh) = - writer.global_id(&trap::full_id_for_file(&normalize_path(absolute_path))); - if fresh { - writer.add_tuple( - "files", - vec![ - trap::Arg::Label(file_label), - trap::Arg::String(normalize_path(absolute_path)), - ], - ); - populate_parent_folders(writer, file_label, absolute_path.parent()); - } - file_label -} - -fn populate_empty_file(writer: &mut trap::Writer) -> trap::Label { - let (file_label, fresh) = writer.global_id("empty;sourcefile"); - if fresh { - writer.add_tuple( - "files", - vec![ - trap::Arg::Label(file_label), - trap::Arg::String("".to_string()), - ], - ); - } - file_label -} - -pub fn populate_empty_location(writer: &mut trap::Writer) { - let file_label = populate_empty_file(writer); - location(writer, file_label, 0, 0, 0, 0); -} - -pub fn populate_parent_folders( - writer: &mut trap::Writer, - child_label: trap::Label, - path: Option<&Path>, -) { - let mut path = path; - let mut child_label = child_label; - loop { - match path { - None => break, - Some(folder) => { - let (folder_label, fresh) = - writer.global_id(&trap::full_id_for_folder(&normalize_path(folder))); - writer.add_tuple( - "containerparent", - vec![ - trap::Arg::Label(folder_label), - trap::Arg::Label(child_label), - ], - ); - if fresh { - writer.add_tuple( - "folders", - vec![ - trap::Arg::Label(folder_label), - trap::Arg::String(normalize_path(folder)), - ], - ); - path = folder.parent(); - child_label = folder_label; - } else { - break; - } - } - } - } -} - -fn location( - writer: &mut trap::Writer, - file_label: trap::Label, - start_line: usize, - start_column: usize, - end_line: usize, - end_column: usize, -) -> trap::Label { - let (loc_label, fresh) = writer.global_id(&format!( - "loc,{{{}}},{},{},{},{}", - file_label, start_line, start_column, end_line, end_column - )); - if fresh { - writer.add_tuple( - "locations_default", - vec![ - trap::Arg::Label(loc_label), - trap::Arg::Label(file_label), - trap::Arg::Int(start_line), - trap::Arg::Int(start_column), - trap::Arg::Int(end_line), - trap::Arg::Int(end_column), - ], - ); - } - loc_label -} - -/// Extracts the source file at `path`, which is assumed to be canonicalized. -pub fn extract( - language: Language, - language_prefix: &str, - schema: &NodeTypeMap, - trap_writer: &mut trap::Writer, - path: &Path, - source: &[u8], - ranges: &[Range], -) -> std::io::Result<()> { - let path_str = format!("{}", path.display()); - let span = span!( - Level::TRACE, - "extract", - file = %path_str - ); - - let _enter = span.enter(); - - info!("extracting: {}", path_str); - - let mut parser = Parser::new(); - parser.set_language(language).unwrap(); - parser.set_included_ranges(ranges).unwrap(); - let tree = parser.parse(&source, None).expect("Failed to parse file"); - trap_writer.comment(format!("Auto-generated TRAP file for {}", path_str)); - let file_label = populate_file(trap_writer, path); - let mut visitor = Visitor::new( - source, - trap_writer, - // TODO: should we handle path strings that are not valid UTF8 better? - &path_str, - file_label, - language_prefix, - schema, - ); - traverse(&tree, &mut visitor); - - parser.reset(); - Ok(()) -} - -/// Normalizes the path according the common CodeQL specification. Assumes that -/// `path` has already been canonicalized using `std::fs::canonicalize`. -fn normalize_path(path: &Path) -> String { - if cfg!(windows) { - // The way Rust canonicalizes paths doesn't match the CodeQL spec, so we - // have to do a bit of work removing certain prefixes and replacing - // backslashes. - let mut components: Vec<String> = Vec::new(); - for component in path.components() { - match component { - std::path::Component::Prefix(prefix) => match prefix.kind() { - std::path::Prefix::Disk(letter) | std::path::Prefix::VerbatimDisk(letter) => { - components.push(format!("{}:", letter as char)); - } - std::path::Prefix::Verbatim(x) | std::path::Prefix::DeviceNS(x) => { - components.push(x.to_string_lossy().to_string()); - } - std::path::Prefix::UNC(server, share) - | std::path::Prefix::VerbatimUNC(server, share) => { - components.push(server.to_string_lossy().to_string()); - components.push(share.to_string_lossy().to_string()); - } - }, - std::path::Component::Normal(n) => { - components.push(n.to_string_lossy().to_string()); - } - std::path::Component::RootDir => {} - std::path::Component::CurDir => {} - std::path::Component::ParentDir => {} - } - } - components.join("/") - } else { - // For other operating systems, we can use the canonicalized path - // without modifications. - format!("{}", path.display()) - } -} - -struct ChildNode { - field_name: Option<&'static str>, - label: trap::Label, - type_name: TypeName, -} - -struct Visitor<'a> { - /// The file path of the source code (as string) - path: &'a str, - /// The label to use whenever we need to refer to the `@file` entity of this - /// source file. - file_label: trap::Label, - /// The source code as a UTF-8 byte array - source: &'a [u8], - /// A trap::Writer to accumulate trap entries - trap_writer: &'a mut trap::Writer, - /// A counter for top-level child nodes - toplevel_child_counter: usize, - /// Language-specific name of the AST info table - ast_node_info_table_name: String, - /// Language-specific name of the tokeninfo table - tokeninfo_table_name: String, - /// A lookup table from type name to node types - schema: &'a NodeTypeMap, - /// A stack for gathering information from child nodes. Whenever a node is - /// entered the parent's [Label], child counter, and an empty list is pushed. - /// All children append their data to the list. When the visitor leaves a - /// node the list containing the child data is popped from the stack and - /// matched against the dbscheme for the node. If the expectations are met - /// the corresponding row definitions are added to the trap_output. - stack: Vec<(trap::Label, usize, Vec<ChildNode>)>, -} - -impl<'a> Visitor<'a> { - fn new( - source: &'a [u8], - trap_writer: &'a mut trap::Writer, - path: &'a str, - file_label: trap::Label, - language_prefix: &str, - schema: &'a NodeTypeMap, - ) -> Visitor<'a> { - Visitor { - path, - file_label, - source, - trap_writer, - toplevel_child_counter: 0, - ast_node_info_table_name: format!("{}_ast_node_info", language_prefix), - tokeninfo_table_name: format!("{}_tokeninfo", language_prefix), - schema, - stack: Vec::new(), - } - } - - fn record_parse_error( - &mut self, - error_message: String, - full_error_message: String, - loc: trap::Label, - ) { - error!("{}", full_error_message); - let id = self.trap_writer.fresh_id(); - self.trap_writer.add_tuple( - "diagnostics", - vec![ - trap::Arg::Label(id), - trap::Arg::Int(40), // severity 40 = error - trap::Arg::String("parse_error".to_string()), - trap::Arg::String(error_message), - trap::Arg::String(full_error_message), - trap::Arg::Label(loc), - ], - ); - } - - fn record_parse_error_for_node( - &mut self, - error_message: String, - full_error_message: String, - node: Node, - ) { - let (start_line, start_column, end_line, end_column) = location_for(self.source, node); - let loc = location( - self.trap_writer, - self.file_label, - start_line, - start_column, - end_line, - end_column, - ); - self.record_parse_error(error_message, full_error_message, loc); - } - - fn enter_node(&mut self, node: Node) -> bool { - if node.is_error() || node.is_missing() { - let error_message = if node.is_missing() { - format!("parse error: expecting '{}'", node.kind()) - } else { - "parse error".to_string() - }; - let full_error_message = format!( - "{}:{}: {}", - &self.path, - node.start_position().row + 1, - error_message - ); - self.record_parse_error_for_node(error_message, full_error_message, node); - return false; - } - - let id = self.trap_writer.fresh_id(); - - self.stack.push((id, 0, Vec::new())); - true - } - - fn leave_node(&mut self, field_name: Option<&'static str>, node: Node) { - if node.is_error() || node.is_missing() { - return; - } - let (id, _, child_nodes) = self.stack.pop().expect("Vistor: empty stack"); - let (start_line, start_column, end_line, end_column) = location_for(self.source, node); - let loc = location( - self.trap_writer, - self.file_label, - start_line, - start_column, - end_line, - end_column, - ); - let table = self - .schema - .get(&TypeName { - kind: node.kind().to_owned(), - named: node.is_named(), - }) - .unwrap(); - let mut valid = true; - let (parent_id, parent_index) = match self.stack.last_mut() { - Some(p) if !node.is_extra() => { - p.1 += 1; - (p.0, p.1 - 1) - } - _ => { - self.toplevel_child_counter += 1; - (self.file_label, self.toplevel_child_counter - 1) - } - }; - match &table.kind { - EntryKind::Token { kind_id, .. } => { - self.trap_writer.add_tuple( - &self.ast_node_info_table_name, - vec![ - trap::Arg::Label(id), - trap::Arg::Label(parent_id), - trap::Arg::Int(parent_index), - trap::Arg::Label(loc), - ], - ); - self.trap_writer.add_tuple( - &self.tokeninfo_table_name, - vec![ - trap::Arg::Label(id), - trap::Arg::Int(*kind_id), - sliced_source_arg(self.source, node), - ], - ); - } - EntryKind::Table { - fields, - name: table_name, - } => { - if let Some(args) = self.complex_node(&node, fields, &child_nodes, id) { - self.trap_writer.add_tuple( - &self.ast_node_info_table_name, - vec![ - trap::Arg::Label(id), - trap::Arg::Label(parent_id), - trap::Arg::Int(parent_index), - trap::Arg::Label(loc), - ], - ); - let mut all_args = vec![trap::Arg::Label(id)]; - all_args.extend(args); - self.trap_writer.add_tuple(table_name, all_args); - } - } - _ => { - let error_message = format!("unknown table type: '{}'", node.kind()); - let full_error_message = format!( - "{}:{}: {}", - &self.path, - node.start_position().row + 1, - error_message - ); - self.record_parse_error(error_message, full_error_message, loc); - - valid = false; - } - } - if valid && !node.is_extra() { - // Extra nodes are independent root nodes and do not belong to the parent node - // Therefore we should not register them in the parent vector - if let Some(parent) = self.stack.last_mut() { - parent.2.push(ChildNode { - field_name, - label: id, - type_name: TypeName { - kind: node.kind().to_owned(), - named: node.is_named(), - }, - }); - }; - } - } - - fn complex_node( - &mut self, - node: &Node, - fields: &[Field], - child_nodes: &[ChildNode], - parent_id: trap::Label, - ) -> Option<Vec<trap::Arg>> { - let mut map: Map<&Option<String>, (&Field, Vec<trap::Arg>)> = Map::new(); - for field in fields { - map.insert(&field.name, (field, Vec::new())); - } - for child_node in child_nodes { - if let Some((field, values)) = map.get_mut(&child_node.field_name.map(|x| x.to_owned())) - { - //TODO: handle error and missing nodes - if self.type_matches(&child_node.type_name, &field.type_info) { - if let node_types::FieldTypeInfo::ReservedWordInt(int_mapping) = - &field.type_info - { - // We can safely unwrap because type_matches checks the key is in the map. - let (int_value, _) = int_mapping.get(&child_node.type_name.kind).unwrap(); - values.push(trap::Arg::Int(*int_value)); - } else { - values.push(trap::Arg::Label(child_node.label)); - } - } else if field.name.is_some() { - let error_message = format!( - "type mismatch for field {}::{} with type {:?} != {:?}", - node.kind(), - child_node.field_name.unwrap_or("child"), - child_node.type_name, - field.type_info - ); - let full_error_message = format!( - "{}:{}: {}", - &self.path, - node.start_position().row + 1, - error_message - ); - self.record_parse_error_for_node(error_message, full_error_message, *node); - } - } else if child_node.field_name.is_some() || child_node.type_name.named { - let error_message = format!( - "value for unknown field: {}::{} and type {:?}", - node.kind(), - &child_node.field_name.unwrap_or("child"), - &child_node.type_name - ); - let full_error_message = format!( - "{}:{}: {}", - &self.path, - node.start_position().row + 1, - error_message - ); - self.record_parse_error_for_node(error_message, full_error_message, *node); - } - } - let mut args = Vec::new(); - let mut is_valid = true; - for field in fields { - let child_values = &map.get(&field.name).unwrap().1; - match &field.storage { - Storage::Column { name: column_name } => { - if child_values.len() == 1 { - args.push(child_values.first().unwrap().clone()); - } else { - is_valid = false; - let error_message = format!( - "{} for field: {}::{}", - if child_values.is_empty() { - "missing value" - } else { - "too many values" - }, - node.kind(), - column_name - ); - let full_error_message = format!( - "{}:{}: {}", - &self.path, - node.start_position().row + 1, - error_message - ); - self.record_parse_error_for_node(error_message, full_error_message, *node); - } - } - Storage::Table { - name: table_name, - has_index, - column_name: _, - } => { - for (index, child_value) in child_values.iter().enumerate() { - if !*has_index && index > 0 { - error!( - "{}:{}: too many values for field: {}::{}", - &self.path, - node.start_position().row + 1, - node.kind(), - table_name, - ); - break; - } - let mut args = vec![trap::Arg::Label(parent_id)]; - if *has_index { - args.push(trap::Arg::Int(index)) - } - args.push(child_value.clone()); - self.trap_writer.add_tuple(table_name, args); - } - } - } - } - if is_valid { - Some(args) - } else { - None - } - } - - fn type_matches(&self, tp: &TypeName, type_info: &node_types::FieldTypeInfo) -> bool { - match type_info { - node_types::FieldTypeInfo::Single(single_type) => { - if tp == single_type { - return true; - } - if let EntryKind::Union { members } = &self.schema.get(single_type).unwrap().kind { - if self.type_matches_set(tp, members) { - return true; - } - } - } - node_types::FieldTypeInfo::Multiple { types, .. } => { - return self.type_matches_set(tp, types); - } - - node_types::FieldTypeInfo::ReservedWordInt(int_mapping) => { - return !tp.named && int_mapping.contains_key(&tp.kind) - } - } - false - } - - fn type_matches_set(&self, tp: &TypeName, types: &Set<TypeName>) -> bool { - if types.contains(tp) { - return true; - } - for other in types.iter() { - if let EntryKind::Union { members } = &self.schema.get(other).unwrap().kind { - if self.type_matches_set(tp, members) { - return true; - } - } - } - false - } -} - -// Emit a slice of a source file as an Arg. -fn sliced_source_arg(source: &[u8], n: Node) -> trap::Arg { - let range = n.byte_range(); - trap::Arg::String(String::from_utf8_lossy(&source[range.start..range.end]).into_owned()) -} - -// Emit a pair of `TrapEntry`s for the provided node, appropriately calibrated. -// The first is the location and label definition, and the second is the -// 'Located' entry. -fn location_for(source: &[u8], n: Node) -> (usize, usize, usize, usize) { - // Tree-sitter row, column values are 0-based while CodeQL starts - // counting at 1. In addition Tree-sitter's row and column for the - // end position are exclusive while CodeQL's end positions are inclusive. - // This means that all values should be incremented by 1 and in addition the - // end position needs to be shift 1 to the left. In most cases this means - // simply incrementing all values except the end column except in cases where - // the end column is 0 (start of a line). In such cases the end position must be - // set to the end of the previous line. - let start_line = n.start_position().row + 1; - let start_col = n.start_position().column + 1; - let mut end_line = n.end_position().row + 1; - let mut end_col = n.end_position().column; - if start_line > end_line || start_line == end_line && start_col > end_col { - // the range is empty, clip it to sensible values - end_line = start_line; - end_col = start_col - 1; - } else if end_col == 0 { - // end_col = 0 means that we are at the start of a line - // unfortunately 0 is invalid as column number, therefore - // we should update the end location to be the end of the - // previous line - let mut index = n.end_byte(); - if index > 0 && index <= source.len() { - index -= 1; - if source[index] != b'\n' { - error!("expecting a line break symbol, but none found while correcting end column value"); - } - end_line -= 1; - end_col = 1; - while index > 0 && source[index - 1] != b'\n' { - index -= 1; - end_col += 1; - } - } else { - error!( - "cannot correct end column value: end_byte index {} is not in range [1,{}]", - index, - source.len() - ); - } - } - (start_line, start_col, end_line, end_col) -} - -fn traverse(tree: &Tree, visitor: &mut Visitor) { - let cursor = &mut tree.walk(); - visitor.enter_node(cursor.node()); - let mut recurse = true; - loop { - if recurse && cursor.goto_first_child() { - recurse = visitor.enter_node(cursor.node()); - } else { - visitor.leave_node(cursor.field_name(), cursor.node()); - - if cursor.goto_next_sibling() { - recurse = visitor.enter_node(cursor.node()); - } else if cursor.goto_parent() { - recurse = false; - } else { - break; - } - } - } -} - -// Numeric indices. -#[derive(Debug, Copy, Clone)] -struct Index(usize); - -impl fmt::Display for Index { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.0) - } -} diff --git a/ql/extractor/src/trap.rs b/ql/extractor/src/trap.rs deleted file mode 100644 index 35a9b69f255..00000000000 --- a/ql/extractor/src/trap.rs +++ /dev/null @@ -1,275 +0,0 @@ -use std::borrow::Cow; -use std::fmt; -use std::io::{BufWriter, Write}; -use std::path::Path; - -use flate2::write::GzEncoder; - -pub struct Writer { - /// The accumulated trap entries - trap_output: Vec<Entry>, - /// A counter for generating fresh labels - counter: u32, - /// cache of global keys - global_keys: std::collections::HashMap<String, Label>, -} - -impl Writer { - pub fn new() -> Writer { - Writer { - counter: 0, - trap_output: Vec::new(), - global_keys: std::collections::HashMap::new(), - } - } - - pub fn fresh_id(&mut self) -> Label { - let label = Label(self.counter); - self.counter += 1; - self.trap_output.push(Entry::FreshId(label)); - label - } - - /// Gets a label that will hold the unique ID of the passed string at import time. - /// This can be used for incrementally importable TRAP files -- use globally unique - /// strings to compute a unique ID for table tuples. - /// - /// Note: You probably want to make sure that the key strings that you use are disjoint - /// for disjoint column types; the standard way of doing this is to prefix (or append) - /// the column type name to the ID. Thus, you might identify methods in Java by the - /// full ID "methods_com.method.package.DeclaringClass.method(argumentList)". - pub fn global_id(&mut self, key: &str) -> (Label, bool) { - if let Some(label) = self.global_keys.get(key) { - return (*label, false); - } - let label = Label(self.counter); - self.counter += 1; - self.global_keys.insert(key.to_owned(), label); - self.trap_output - .push(Entry::MapLabelToKey(label, key.to_owned())); - (label, true) - } - - pub fn add_tuple(&mut self, table_name: &str, args: Vec<Arg>) { - self.trap_output - .push(Entry::GenericTuple(table_name.to_owned(), args)) - } - - pub fn comment(&mut self, text: String) { - self.trap_output.push(Entry::Comment(text)); - } - - pub fn write_to_file(&self, path: &Path, compression: Compression) -> std::io::Result<()> { - let trap_file = std::fs::File::create(path)?; - match compression { - Compression::None => { - let mut trap_file = BufWriter::new(trap_file); - self.write_trap_entries(&mut trap_file) - } - Compression::Gzip => { - let trap_file = GzEncoder::new(trap_file, flate2::Compression::fast()); - let mut trap_file = BufWriter::new(trap_file); - self.write_trap_entries(&mut trap_file) - } - } - } - - fn write_trap_entries<W: Write>(&self, file: &mut W) -> std::io::Result<()> { - for trap_entry in &self.trap_output { - writeln!(file, "{}", trap_entry)?; - } - std::io::Result::Ok(()) - } -} - -pub enum Entry { - /// Maps the label to a fresh id, e.g. `#123=*`. - FreshId(Label), - /// Maps the label to a key, e.g. `#7=@"foo"`. - MapLabelToKey(Label, String), - /// foo_bar(arg*) - GenericTuple(String, Vec<Arg>), - Comment(String), -} - -impl fmt::Display for Entry { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Entry::FreshId(label) => write!(f, "{}=*", label), - Entry::MapLabelToKey(label, key) => { - write!(f, "{}=@\"{}\"", label, key.replace("\"", "\"\"")) - } - Entry::GenericTuple(name, args) => { - write!(f, "{}(", name)?; - for (index, arg) in args.iter().enumerate() { - if index > 0 { - write!(f, ",")?; - } - write!(f, "{}", arg)?; - } - write!(f, ")") - } - Entry::Comment(line) => write!(f, "// {}", line), - } - } -} - -#[derive(Debug, Copy, Clone)] -// Identifiers of the form #0, #1... -pub struct Label(u32); - -impl fmt::Display for Label { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "#{:x}", self.0) - } -} - -// Some untyped argument to a TrapEntry. -#[derive(Debug, Clone)] -pub enum Arg { - Label(Label), - Int(usize), - String(String), -} - -const MAX_STRLEN: usize = 1048576; - -impl fmt::Display for Arg { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Arg::Label(x) => write!(f, "{}", x), - Arg::Int(x) => write!(f, "{}", x), - Arg::String(x) => write!( - f, - "\"{}\"", - limit_string(x, MAX_STRLEN).replace("\"", "\"\"") - ), - } - } -} - -pub struct Program(Vec<Entry>); - -impl fmt::Display for Program { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut text = String::new(); - for trap_entry in &self.0 { - text.push_str(&format!("{}\n", trap_entry)); - } - write!(f, "{}", text) - } -} - -pub fn full_id_for_file(normalized_path: &str) -> String { - format!("{};sourcefile", escape_key(normalized_path)) -} - -pub fn full_id_for_folder(normalized_path: &str) -> String { - format!("{};folder", escape_key(normalized_path)) -} - -/// Escapes a string for use in a TRAP key, by replacing special characters with -/// HTML entities. -fn escape_key<'a, S: Into<Cow<'a, str>>>(key: S) -> Cow<'a, str> { - fn needs_escaping(c: char) -> bool { - matches!(c, '&' | '{' | '}' | '"' | '@' | '#') - } - - let key = key.into(); - if key.contains(needs_escaping) { - let mut escaped = String::with_capacity(2 * key.len()); - for c in key.chars() { - match c { - '&' => escaped.push_str("&"), - '{' => escaped.push_str("{"), - '}' => escaped.push_str("}"), - '"' => escaped.push_str("""), - '@' => escaped.push_str("@"), - '#' => escaped.push_str("#"), - _ => escaped.push(c), - } - } - Cow::Owned(escaped) - } else { - key - } -} - -/// Limit the length (in bytes) of a string. If the string's length in bytes is -/// less than or equal to the limit then the entire string is returned. Otherwise -/// the string is sliced at the provided limit. If there is a multi-byte character -/// at the limit then the returned slice will be slightly shorter than the limit to -/// avoid splitting that multi-byte character. -fn limit_string(string: &str, max_size: usize) -> &str { - if string.len() <= max_size { - return string; - } - let p = string.as_bytes(); - let mut index = max_size; - // We want to clip the string at [max_size]; however, the character at that position - // may span several bytes. We need to find the first byte of the character. In UTF-8 - // encoded data any byte that matches the bit pattern 10XXXXXX is not a start byte. - // Therefore we decrement the index as long as there are bytes matching this pattern. - // This ensures we cut the string at the border between one character and another. - while index > 0 && (p[index] & 0b11000000) == 0b10000000 { - index -= 1; - } - &string[0..index] -} - -#[derive(Clone, Copy)] -pub enum Compression { - None, - Gzip, -} - -impl Compression { - pub fn from_env(var_name: &str) -> Compression { - match std::env::var(var_name) { - Ok(method) => match Compression::from_string(&method) { - Some(c) => c, - None => { - tracing::error!("Unknown compression method '{}'; using gzip.", &method); - Compression::Gzip - } - }, - // Default compression method if the env var isn't set: - Err(_) => Compression::Gzip, - } - } - - pub fn from_string(s: &str) -> Option<Compression> { - match s.to_lowercase().as_ref() { - "none" => Some(Compression::None), - "gzip" => Some(Compression::Gzip), - _ => None, - } - } - - pub fn extension(&self) -> &str { - match self { - Compression::None => "trap", - Compression::Gzip => "trap.gz", - } - } -} - -#[test] -fn limit_string_test() { - assert_eq!("hello", limit_string(&"hello world".to_owned(), 5)); - assert_eq!("hi ☹", limit_string(&"hi ☹☹".to_owned(), 6)); - assert_eq!("hi ", limit_string(&"hi ☹☹".to_owned(), 5)); -} - -#[test] -fn escape_key_test() { - assert_eq!("foo!", escape_key("foo!")); - assert_eq!("foo{}", escape_key("foo{}")); - assert_eq!("{}", escape_key("{}")); - assert_eq!("", escape_key("")); - assert_eq!("/path/to/foo.rb", escape_key("/path/to/foo.rb")); - assert_eq!( - "/path/to/foo&{}"@#.rb", - escape_key("/path/to/foo&{}\"@#.rb") - ); -} diff --git a/ql/generator/Cargo.toml b/ql/generator/Cargo.toml deleted file mode 100644 index 4fcc98be310..00000000000 --- a/ql/generator/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "ql-generator" -version = "0.1.0" -authors = ["GitHub"] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -clap = "2.33" -node-types = { path = "../node-types" } -tracing = "0.1" -tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } -tree-sitter-ql = { git = "https://github.com/tree-sitter/tree-sitter-ql.git", rev = "d08db734f8dc52f6bc04db53a966603122bc6985"} -tree-sitter-ql-dbscheme = { git = "https://github.com/erik-krogh/tree-sitter-ql-dbscheme.git", rev = "63e1344353f63931e88bfbc2faa2e78e1421b213"} -tree-sitter-ql-yaml = {git = "https://github.com/erik-krogh/tree-sitter-ql.git", rev = "cf704bf3671e1ae148e173464fb65a4d2bbf5f99"} -tree-sitter-blame = {path = "../buramu/tree-sitter-blame"} -tree-sitter-json = { git = "https://github.com/tausbn/tree-sitter-json.git", rev = "745663ee997f1576fe1e7187e6347e0db36ec7a9"} diff --git a/ql/generator/src/dbscheme.rs b/ql/generator/src/dbscheme.rs deleted file mode 100644 index 335eee1950c..00000000000 --- a/ql/generator/src/dbscheme.rs +++ /dev/null @@ -1,130 +0,0 @@ -use crate::ql; -use std::collections::BTreeSet as Set; -use std::fmt; -/// Represents a distinct entry in the database schema. -pub enum Entry<'a> { - /// An entry defining a database table. - Table(Table<'a>), - /// An entry defining a database table. - Case(Case<'a>), - /// An entry defining type that is a union of other types. - Union(Union<'a>), -} - -/// A table in the database schema. -pub struct Table<'a> { - pub name: &'a str, - pub columns: Vec<Column<'a>>, - pub keysets: Option<Vec<&'a str>>, -} - -/// A union in the database schema. -pub struct Union<'a> { - pub name: &'a str, - pub members: Set<&'a str>, -} - -/// A table in the database schema. -pub struct Case<'a> { - pub name: &'a str, - pub column: &'a str, - pub branches: Vec<(usize, &'a str)>, -} - -/// A column in a table. -pub struct Column<'a> { - pub db_type: DbColumnType, - pub name: &'a str, - pub unique: bool, - pub ql_type: ql::Type<'a>, - pub ql_type_is_ref: bool, -} - -/// The database column type. -pub enum DbColumnType { - Int, - String, -} - -impl<'a> fmt::Display for Case<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!(f, "case @{}.{} of", &self.name, &self.column)?; - let mut sep = " "; - for (c, tp) in &self.branches { - writeln!(f, "{} {} = @{}", sep, c, tp)?; - sep = "|"; - } - writeln!(f, ";") - } -} - -impl<'a> fmt::Display for Table<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some(keyset) = &self.keysets { - write!(f, "#keyset[")?; - for (key_index, key) in keyset.iter().enumerate() { - if key_index > 0 { - write!(f, ", ")?; - } - write!(f, "{}", key)?; - } - writeln!(f, "]")?; - } - - writeln!(f, "{}(", self.name)?; - for (column_index, column) in self.columns.iter().enumerate() { - write!(f, " ")?; - if column.unique { - write!(f, "unique ")?; - } - write!( - f, - "{} ", - match column.db_type { - DbColumnType::Int => "int", - DbColumnType::String => "string", - } - )?; - write!(f, "{}: {}", column.name, column.ql_type)?; - if column.ql_type_is_ref { - write!(f, " ref")?; - } - if column_index + 1 != self.columns.len() { - write!(f, ",")?; - } - writeln!(f)?; - } - write!(f, ");")?; - - Ok(()) - } -} - -impl<'a> fmt::Display for Union<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "@{} = ", self.name)?; - let mut first = true; - for member in &self.members { - if first { - first = false; - } else { - write!(f, " | ")?; - } - write!(f, "@{}", member)?; - } - Ok(()) - } -} - -/// Generates the dbscheme by writing the given dbscheme `entries` to the `file`. -pub fn write<'a>(file: &mut dyn std::io::Write, entries: &'a [Entry]) -> std::io::Result<()> { - for entry in entries { - match entry { - Entry::Case(case) => write!(file, "{}\n\n", case)?, - Entry::Table(table) => write!(file, "{}\n\n", table)?, - Entry::Union(union) => write!(file, "{}\n\n", union)?, - } - } - - Ok(()) -} diff --git a/ql/generator/src/ql_gen.rs b/ql/generator/src/ql_gen.rs deleted file mode 100644 index 007509e0074..00000000000 --- a/ql/generator/src/ql_gen.rs +++ /dev/null @@ -1,565 +0,0 @@ -use crate::ql; -use std::collections::BTreeSet; - -/// Creates the hard-coded `AstNode` class that acts as a supertype of all -/// classes we generate. -pub fn create_ast_node_class<'a>(ast_node: &'a str, node_info_table: &'a str) -> ql::Class<'a> { - // Default implementation of `toString` calls `this.getAPrimaryQlClass()` - let to_string = ql::Predicate { - qldoc: Some(String::from( - "Gets a string representation of this element.", - )), - name: "toString", - overridden: false, - is_final: false, - return_type: Some(ql::Type::String), - formal_parameters: vec![], - body: ql::Expression::Equals( - Box::new(ql::Expression::Var("result")), - Box::new(ql::Expression::Dot( - Box::new(ql::Expression::Var("this")), - "getAPrimaryQlClass", - vec![], - )), - ), - }; - let get_location = ql::Predicate { - name: "getLocation", - qldoc: Some(String::from("Gets the location of this element.")), - overridden: false, - is_final: true, - return_type: Some(ql::Type::Normal("L::Location")), - formal_parameters: vec![], - body: ql::Expression::Pred( - node_info_table, - vec![ - ql::Expression::Var("this"), - ql::Expression::Var("_"), // parent - ql::Expression::Var("_"), // parent index - ql::Expression::Var("result"), // location - ], - ), - }; - let get_a_field_or_child = create_none_predicate( - Some(String::from("Gets a field or child node of this node.")), - "getAFieldOrChild", - false, - Some(ql::Type::Normal("AstNode")), - ); - let get_parent = ql::Predicate { - qldoc: Some(String::from("Gets the parent of this element.")), - name: "getParent", - overridden: false, - is_final: true, - return_type: Some(ql::Type::Normal("AstNode")), - formal_parameters: vec![], - body: ql::Expression::Pred( - node_info_table, - vec![ - ql::Expression::Var("this"), - ql::Expression::Var("result"), - ql::Expression::Var("_"), // parent index - ql::Expression::Var("_"), // location - ], - ), - }; - let get_parent_index = ql::Predicate { - qldoc: Some(String::from( - "Gets the index of this node among the children of its parent.", - )), - name: "getParentIndex", - overridden: false, - is_final: true, - return_type: Some(ql::Type::Int), - formal_parameters: vec![], - body: ql::Expression::Pred( - node_info_table, - vec![ - ql::Expression::Var("this"), - ql::Expression::Var("_"), // parent - ql::Expression::Var("result"), // parent index - ql::Expression::Var("_"), // location - ], - ), - }; - let get_a_primary_ql_class = ql::Predicate { - qldoc: Some(String::from( - "Gets the name of the primary QL class for this element.", - )), - name: "getAPrimaryQlClass", - overridden: false, - is_final: false, - return_type: Some(ql::Type::String), - formal_parameters: vec![], - body: ql::Expression::Equals( - Box::new(ql::Expression::Var("result")), - Box::new(ql::Expression::String("???")), - ), - }; - let get_primary_ql_classes = ql::Predicate { - qldoc: Some( - "Gets a comma-separated list of the names of the primary CodeQL \ - classes to which this element belongs." - .to_owned(), - ), - name: "getPrimaryQlClasses", - overridden: false, - is_final: false, - return_type: Some(ql::Type::String), - formal_parameters: vec![], - body: ql::Expression::Equals( - Box::new(ql::Expression::Var("result")), - Box::new(ql::Expression::Aggregate { - name: "concat", - vars: vec![], - range: None, - expr: Box::new(ql::Expression::Dot( - Box::new(ql::Expression::Var("this")), - "getAPrimaryQlClass", - vec![], - )), - second_expr: Some(Box::new(ql::Expression::String(","))), - }), - ), - }; - ql::Class { - qldoc: Some(String::from("The base class for all AST nodes")), - name: "AstNode", - is_abstract: false, - supertypes: vec![ql::Type::At(ast_node)].into_iter().collect(), - characteristic_predicate: None, - predicates: vec![ - to_string, - get_location, - get_parent, - get_parent_index, - get_a_field_or_child, - get_a_primary_ql_class, - get_primary_ql_classes, - ], - } -} - -pub fn create_token_class<'a>(token_type: &'a str, tokeninfo: &'a str) -> ql::Class<'a> { - let tokeninfo_arity = 3; // id, kind, value - let get_value = ql::Predicate { - qldoc: Some(String::from("Gets the value of this token.")), - name: "getValue", - overridden: false, - is_final: true, - return_type: Some(ql::Type::String), - formal_parameters: vec![], - body: create_get_field_expr_for_column_storage("result", tokeninfo, 1, tokeninfo_arity), - }; - let to_string = ql::Predicate { - qldoc: Some(String::from( - "Gets a string representation of this element.", - )), - name: "toString", - overridden: true, - is_final: true, - return_type: Some(ql::Type::String), - formal_parameters: vec![], - body: ql::Expression::Equals( - Box::new(ql::Expression::Var("result")), - Box::new(ql::Expression::Dot( - Box::new(ql::Expression::Var("this")), - "getValue", - vec![], - )), - ), - }; - ql::Class { - qldoc: Some(String::from("A token.")), - name: "Token", - is_abstract: false, - supertypes: vec![ql::Type::At(token_type), ql::Type::Normal("AstNode")] - .into_iter() - .collect(), - characteristic_predicate: None, - predicates: vec![ - get_value, - to_string, - create_get_a_primary_ql_class("Token", false), - ], - } -} - -// Creates the `ReservedWord` class. -pub fn create_reserved_word_class(db_name: &str) -> ql::Class { - let class_name = "ReservedWord"; - let get_a_primary_ql_class = create_get_a_primary_ql_class(class_name, true); - ql::Class { - qldoc: Some(String::from("A reserved word.")), - name: class_name, - is_abstract: false, - supertypes: vec![ql::Type::At(db_name), ql::Type::Normal("Token")] - .into_iter() - .collect(), - characteristic_predicate: None, - predicates: vec![get_a_primary_ql_class], - } -} - -/// Creates a predicate whose body is `none()`. -fn create_none_predicate<'a>( - qldoc: Option<String>, - name: &'a str, - overridden: bool, - return_type: Option<ql::Type<'a>>, -) -> ql::Predicate<'a> { - ql::Predicate { - qldoc, - name, - overridden, - is_final: false, - return_type, - formal_parameters: Vec::new(), - body: ql::Expression::Pred("none", vec![]), - } -} - -/// Creates an overridden `getAPrimaryQlClass` predicate that returns the given -/// name. -fn create_get_a_primary_ql_class(class_name: &str, is_final: bool) -> ql::Predicate { - ql::Predicate { - qldoc: Some(String::from( - "Gets the name of the primary QL class for this element.", - )), - name: "getAPrimaryQlClass", - overridden: true, - is_final, - return_type: Some(ql::Type::String), - formal_parameters: vec![], - body: ql::Expression::Equals( - Box::new(ql::Expression::Var("result")), - Box::new(ql::Expression::String(class_name)), - ), - } -} - -/// Returns an expression to get a field that's defined as a column in the parent's table. -/// -/// # Arguments -/// -/// * `result_var_name` - the name of the variable to which the resulting value should be bound -/// * `table_name` - the name of parent's defining table -/// * `column_index` - the index in that table that defines the field -/// * `arity` - the total number of columns in the table -fn create_get_field_expr_for_column_storage<'a>( - result_var_name: &'a str, - table_name: &'a str, - column_index: usize, - arity: usize, -) -> ql::Expression<'a> { - let num_underscores_before = column_index; - let num_underscores_after = arity - 2 - num_underscores_before; - ql::Expression::Pred( - table_name, - [ - vec![ql::Expression::Var("this")], - vec![ql::Expression::Var("_"); num_underscores_before], - vec![ql::Expression::Var(result_var_name)], - vec![ql::Expression::Var("_"); num_underscores_after], - ] - .concat(), - ) -} - -/// Returns an expression to get the field with the given index from its -/// auxiliary table. The index name can be "_" so the expression will hold for -/// all indices. -fn create_get_field_expr_for_table_storage<'a>( - result_var_name: &'a str, - table_name: &'a str, - index_var_name: Option<&'a str>, -) -> ql::Expression<'a> { - ql::Expression::Pred( - table_name, - match index_var_name { - Some(index_var_name) => vec![ - ql::Expression::Var("this"), - ql::Expression::Var(index_var_name), - ql::Expression::Var(result_var_name), - ], - None => vec![ql::Expression::Var("this"), ql::Expression::Var("result")], - }, - ) -} - -/// Creates a pair consisting of a predicate to get the given field, and an -/// optional expression that will get the same field. When the field can occur -/// multiple times, the predicate will take an index argument, while the -/// expression will use the "don't care" expression to hold for all occurrences. -/// -/// # Arguments -/// -/// `main_table_name` - the name of the defining table for the parent node -/// `main_table_arity` - the number of columns in the main table -/// `main_table_column_index` - a mutable reference to a column index indicating -/// where the field is in the main table. If this is used (i.e. the field has -/// column storage), then the index is incremented. -/// `parent_name` - the name of the parent node -/// `field` - the field whose getters we are creating -/// `field_type` - the db name of the field's type (possibly being a union we created) -fn create_field_getters<'a>( - main_table_name: &'a str, - main_table_arity: usize, - main_table_column_index: &mut usize, - field: &'a node_types::Field, - nodes: &'a node_types::NodeTypeMap, -) -> (ql::Predicate<'a>, Option<ql::Expression<'a>>) { - let return_type = match &field.type_info { - node_types::FieldTypeInfo::Single(t) => { - Some(ql::Type::Normal(&nodes.get(t).unwrap().ql_class_name)) - } - node_types::FieldTypeInfo::Multiple { - types: _, - dbscheme_union: _, - ql_class, - } => Some(ql::Type::Normal(ql_class)), - node_types::FieldTypeInfo::ReservedWordInt(_) => Some(ql::Type::String), - }; - let formal_parameters = match &field.storage { - node_types::Storage::Column { .. } => vec![], - node_types::Storage::Table { has_index, .. } => { - if *has_index { - vec![ql::FormalParameter { - name: "i", - param_type: ql::Type::Int, - }] - } else { - vec![] - } - } - }; - - // For the expression to get a value, what variable name should the result - // be bound to? - let get_value_result_var_name = match &field.type_info { - node_types::FieldTypeInfo::ReservedWordInt(_) => "value", - node_types::FieldTypeInfo::Single(_) => "result", - node_types::FieldTypeInfo::Multiple { .. } => "result", - }; - - // Two expressions for getting the value. One that's suitable use in the - // getter predicate (where there may be a specific index), and another for - // use in `getAFieldOrChild` (where we use a "don't care" expression to - // match any index). - let (get_value, get_value_any_index) = match &field.storage { - node_types::Storage::Column { name: _ } => { - let column_index = *main_table_column_index; - *main_table_column_index += 1; - ( - create_get_field_expr_for_column_storage( - get_value_result_var_name, - main_table_name, - column_index, - main_table_arity, - ), - create_get_field_expr_for_column_storage( - get_value_result_var_name, - main_table_name, - column_index, - main_table_arity, - ), - ) - } - node_types::Storage::Table { - name: field_table_name, - has_index, - column_name: _, - } => ( - create_get_field_expr_for_table_storage( - get_value_result_var_name, - field_table_name, - if *has_index { Some("i") } else { None }, - ), - create_get_field_expr_for_table_storage( - get_value_result_var_name, - field_table_name, - if *has_index { Some("_") } else { None }, - ), - ), - }; - let (body, optional_expr) = match &field.type_info { - node_types::FieldTypeInfo::ReservedWordInt(int_mapping) => { - // Create an expression that binds the corresponding string to `result` for each `value`, e.g.: - // result = "foo" and value = 0 or - // result = "bar" and value = 1 or - // result = "baz" and value = 2 - let disjuncts = int_mapping - .iter() - .map(|(token_str, (value, _))| { - ql::Expression::And(vec![ - ql::Expression::Equals( - Box::new(ql::Expression::Var("result")), - Box::new(ql::Expression::String(token_str)), - ), - ql::Expression::Equals( - Box::new(ql::Expression::Var("value")), - Box::new(ql::Expression::Integer(*value)), - ), - ]) - }) - .collect(); - ( - ql::Expression::Aggregate { - name: "exists", - vars: vec![ql::FormalParameter { - name: "value", - param_type: ql::Type::Int, - }], - range: Some(Box::new(get_value)), - expr: Box::new(ql::Expression::Or(disjuncts)), - second_expr: None, - }, - // Since the getter returns a string and not an AstNode, it won't be part of getAFieldOrChild: - None, - ) - } - node_types::FieldTypeInfo::Single(_) | node_types::FieldTypeInfo::Multiple { .. } => { - (get_value, Some(get_value_any_index)) - } - }; - let qldoc = match &field.name { - Some(name) => format!("Gets the node corresponding to the field `{}`.", name), - None => { - if formal_parameters.is_empty() { - "Gets the child of this node.".to_owned() - } else { - "Gets the `i`th child of this node.".to_owned() - } - } - }; - ( - ql::Predicate { - qldoc: Some(qldoc), - name: &field.getter_name, - overridden: false, - is_final: true, - return_type, - formal_parameters, - body, - }, - optional_expr, - ) -} - -/// Converts the given node types into CodeQL classes wrapping the dbscheme. -pub fn convert_nodes(nodes: &node_types::NodeTypeMap) -> Vec<ql::TopLevel> { - let mut classes: Vec<ql::TopLevel> = Vec::new(); - let mut token_kinds = BTreeSet::new(); - for (type_name, node) in nodes { - if let node_types::EntryKind::Token { .. } = &node.kind { - if type_name.named { - token_kinds.insert(&type_name.kind); - } - } - } - - for (type_name, node) in nodes { - match &node.kind { - node_types::EntryKind::Token { kind_id: _ } => { - if type_name.named { - let get_a_primary_ql_class = - create_get_a_primary_ql_class(&node.ql_class_name, true); - let mut supertypes: BTreeSet<ql::Type> = BTreeSet::new(); - supertypes.insert(ql::Type::At(&node.dbscheme_name)); - supertypes.insert(ql::Type::Normal("Token")); - classes.push(ql::TopLevel::Class(ql::Class { - qldoc: Some(format!("A class representing `{}` tokens.", type_name.kind)), - name: &node.ql_class_name, - is_abstract: false, - supertypes, - characteristic_predicate: None, - predicates: vec![get_a_primary_ql_class], - })); - } - } - node_types::EntryKind::Union { members: _ } => { - // It's a tree-sitter supertype node, so we're wrapping a dbscheme - // union type. - classes.push(ql::TopLevel::Class(ql::Class { - qldoc: None, - name: &node.ql_class_name, - is_abstract: false, - supertypes: vec![ - ql::Type::At(&node.dbscheme_name), - ql::Type::Normal("AstNode"), - ] - .into_iter() - .collect(), - characteristic_predicate: None, - predicates: vec![], - })); - } - node_types::EntryKind::Table { - name: main_table_name, - fields, - } => { - if fields.is_empty() { - panic!("Encountered node '{}' with no fields", type_name.kind); - } - - // Count how many columns there will be in the main table. There - // will be one for the id, plus one for each field that's stored - // as a column. - let main_table_arity = 1 + fields - .iter() - .filter(|&f| matches!(f.storage, node_types::Storage::Column { .. })) - .count(); - - let main_class_name = &node.ql_class_name; - let mut main_class = ql::Class { - qldoc: Some(format!("A class representing `{}` nodes.", type_name.kind)), - name: main_class_name, - is_abstract: false, - supertypes: vec![ - ql::Type::At(&node.dbscheme_name), - ql::Type::Normal("AstNode"), - ] - .into_iter() - .collect(), - characteristic_predicate: None, - predicates: vec![create_get_a_primary_ql_class(main_class_name, true)], - }; - - let mut main_table_column_index: usize = 0; - let mut get_child_exprs: Vec<ql::Expression> = Vec::new(); - - // Iterate through the fields, creating: - // - classes to wrap union types if fields need them, - // - predicates to access the fields, - // - the QL expressions to access the fields that will be part of getAFieldOrChild. - for field in fields { - let (get_pred, get_child_expr) = create_field_getters( - main_table_name, - main_table_arity, - &mut main_table_column_index, - field, - nodes, - ); - main_class.predicates.push(get_pred); - if let Some(get_child_expr) = get_child_expr { - get_child_exprs.push(get_child_expr) - } - } - - main_class.predicates.push(ql::Predicate { - qldoc: Some(String::from("Gets a field or child node of this node.")), - name: "getAFieldOrChild", - overridden: true, - is_final: true, - return_type: Some(ql::Type::Normal("AstNode")), - formal_parameters: vec![], - body: ql::Expression::Or(get_child_exprs), - }); - - classes.push(ql::TopLevel::Class(main_class)); - } - } - } - - classes -} diff --git a/ql/node-types/Cargo.toml b/ql/node-types/Cargo.toml deleted file mode 100644 index 181bd6481e9..00000000000 --- a/ql/node-types/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "node-types" -version = "0.1.0" -authors = ["GitHub"] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" diff --git a/ql/node-types/src/lib.rs b/ql/node-types/src/lib.rs deleted file mode 100644 index 9467e23fd62..00000000000 --- a/ql/node-types/src/lib.rs +++ /dev/null @@ -1,449 +0,0 @@ -use serde::Deserialize; -use std::collections::BTreeMap; -use std::path::Path; - -use std::collections::BTreeSet as Set; -use std::fs; - -/// A lookup table from TypeName to Entry. -pub type NodeTypeMap = BTreeMap<TypeName, Entry>; - -#[derive(Debug)] -pub struct Entry { - pub dbscheme_name: String, - pub ql_class_name: String, - pub kind: EntryKind, -} - -#[derive(Debug)] -pub enum EntryKind { - Union { members: Set<TypeName> }, - Table { name: String, fields: Vec<Field> }, - Token { kind_id: usize }, -} - -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)] -pub struct TypeName { - pub kind: String, - pub named: bool, -} - -#[derive(Debug)] -pub enum FieldTypeInfo { - /// The field has a single type. - Single(TypeName), - - /// The field can take one of several types, so we also provide the name of - /// the database union type that wraps them, and the corresponding QL class - /// name. - Multiple { - types: Set<TypeName>, - dbscheme_union: String, - ql_class: String, - }, - - /// The field can be one of several tokens, so the db type will be an `int` - /// with a `case @foo.kind` for each possibility. - ReservedWordInt(BTreeMap<String, (usize, String)>), -} - -#[derive(Debug)] -pub struct Field { - pub parent: TypeName, - pub type_info: FieldTypeInfo, - /// The name of the field or None for the anonymous 'children' - /// entry from node_types.json - pub name: Option<String>, - /// The name of the predicate to get this field. - pub getter_name: String, - pub storage: Storage, -} - -fn name_for_field_or_child(name: &Option<String>) -> String { - match name { - Some(name) => name.clone(), - None => "child".to_owned(), - } -} - -#[derive(Debug)] -pub enum Storage { - /// the field is stored as a column in the parent table - Column { name: String }, - /// the field is stored in a link table - Table { - /// the name of the table - name: String, - /// the name of the column for the field in the dbscheme - column_name: String, - /// does it have an associated index column? - has_index: bool, - }, -} - -impl Storage { - pub fn is_column(&self) -> bool { - match self { - Storage::Column { .. } => true, - _ => false, - } - } -} -pub fn read_node_types(prefix: &str, node_types_path: &Path) -> std::io::Result<NodeTypeMap> { - let file = fs::File::open(node_types_path)?; - let node_types: Vec<NodeInfo> = serde_json::from_reader(file)?; - Ok(convert_nodes(prefix, &node_types)) -} - -pub fn read_node_types_str(prefix: &str, node_types_json: &str) -> std::io::Result<NodeTypeMap> { - let node_types: Vec<NodeInfo> = serde_json::from_str(node_types_json)?; - Ok(convert_nodes(prefix, &node_types)) -} - -fn convert_type(node_type: &NodeType) -> TypeName { - TypeName { - kind: node_type.kind.to_string(), - named: node_type.named, - } -} - -fn convert_types(node_types: &[NodeType]) -> Set<TypeName> { - node_types.iter().map(convert_type).collect() -} - -pub fn convert_nodes(prefix: &str, nodes: &[NodeInfo]) -> NodeTypeMap { - let mut entries = NodeTypeMap::new(); - let mut token_kinds = Set::new(); - - // First, find all the token kinds - for node in nodes { - if node.subtypes.is_none() - && node.fields.as_ref().map_or(0, |x| x.len()) == 0 - && node.children.is_none() - { - let type_name = TypeName { - kind: node.kind.clone(), - named: node.named, - }; - token_kinds.insert(type_name); - } - } - - for node in nodes { - let flattened_name = &node_type_name(&node.kind, node.named); - let dbscheme_name = escape_name(flattened_name); - let ql_class_name = dbscheme_name_to_class_name(&dbscheme_name); - let dbscheme_name = format!("{}_{}", prefix, &dbscheme_name); - if let Some(subtypes) = &node.subtypes { - // It's a tree-sitter supertype node, for which we create a union - // type. - entries.insert( - TypeName { - kind: node.kind.clone(), - named: node.named, - }, - Entry { - dbscheme_name, - ql_class_name, - kind: EntryKind::Union { - members: convert_types(subtypes), - }, - }, - ); - } else if node.fields.as_ref().map_or(0, |x| x.len()) == 0 && node.children.is_none() { - // Token kind, handled above. - } else { - // It's a product type, defined by a table. - let type_name = TypeName { - kind: node.kind.clone(), - named: node.named, - }; - let table_name = escape_name(&(format!("{}_def", &flattened_name))); - let table_name = format!("{}_{}", prefix, &table_name); - - let mut fields = Vec::new(); - - // If the type also has fields or children, then we create either - // auxiliary tables or columns in the defining table for them. - if let Some(node_fields) = &node.fields { - for (field_name, field_info) in node_fields { - add_field( - prefix, - &type_name, - Some(field_name.to_string()), - field_info, - &mut fields, - &token_kinds, - ); - } - } - if let Some(children) = &node.children { - // Treat children as if they were a field called 'child'. - add_field( - prefix, - &type_name, - None, - children, - &mut fields, - &token_kinds, - ); - } - entries.insert( - type_name, - Entry { - dbscheme_name, - ql_class_name, - kind: EntryKind::Table { - name: table_name, - fields, - }, - }, - ); - } - } - let mut counter = 0; - for type_name in token_kinds { - let entry = if type_name.named { - counter += 1; - let unprefixed_name = node_type_name(&type_name.kind, true); - Entry { - dbscheme_name: escape_name(&format!("{}_token_{}", &prefix, &unprefixed_name)), - ql_class_name: dbscheme_name_to_class_name(&escape_name(&unprefixed_name)), - kind: EntryKind::Token { kind_id: counter }, - } - } else { - Entry { - dbscheme_name: format!("{}_reserved_word", &prefix), - ql_class_name: "ReservedWord".to_owned(), - kind: EntryKind::Token { kind_id: 0 }, - } - }; - entries.insert(type_name, entry); - } - entries -} - -fn add_field( - prefix: &str, - parent_type_name: &TypeName, - field_name: Option<String>, - field_info: &FieldInfo, - fields: &mut Vec<Field>, - token_kinds: &Set<TypeName>, -) { - let parent_flattened_name = node_type_name(&parent_type_name.kind, parent_type_name.named); - let column_name = escape_name(&name_for_field_or_child(&field_name)); - let storage = if !field_info.multiple && field_info.required { - // This field must appear exactly once, so we add it as - // a column to the main table for the node type. - Storage::Column { name: column_name } - } else { - // Put the field in an auxiliary table. - let has_index = field_info.multiple; - let field_table_name = escape_name(&format!( - "{}_{}_{}", - &prefix, - parent_flattened_name, - &name_for_field_or_child(&field_name) - )); - Storage::Table { - has_index, - name: field_table_name, - column_name, - } - }; - let converted_types = convert_types(&field_info.types); - let type_info = if storage.is_column() - && field_info - .types - .iter() - .all(|t| !t.named && token_kinds.contains(&convert_type(t))) - { - // All possible types for this field are reserved words. The db - // representation will be an `int` with a `case @foo.field = ...` to - // enumerate the possible values. - let mut field_token_ints: BTreeMap<String, (usize, String)> = BTreeMap::new(); - for (counter, t) in converted_types.into_iter().enumerate() { - let dbscheme_variant_name = - escape_name(&format!("{}_{}_{}", &prefix, parent_flattened_name, t.kind)); - field_token_ints.insert(t.kind.to_owned(), (counter, dbscheme_variant_name)); - } - FieldTypeInfo::ReservedWordInt(field_token_ints) - } else if field_info.types.len() == 1 { - FieldTypeInfo::Single(converted_types.into_iter().next().unwrap()) - } else { - // The dbscheme type for this field will be a union. In QL, it'll just be AstNode. - FieldTypeInfo::Multiple { - types: converted_types, - dbscheme_union: format!( - "{}_{}_{}_type", - &prefix, - &parent_flattened_name, - &name_for_field_or_child(&field_name) - ), - ql_class: "AstNode".to_owned(), - } - }; - let getter_name = format!( - "get{}", - dbscheme_name_to_class_name(&escape_name(&name_for_field_or_child(&field_name))) - ); - fields.push(Field { - parent: TypeName { - kind: parent_type_name.kind.to_string(), - named: parent_type_name.named, - }, - type_info, - name: field_name, - getter_name, - storage, - }); -} -#[derive(Deserialize)] -pub struct NodeInfo { - #[serde(rename = "type")] - pub kind: String, - pub named: bool, - #[serde(skip_serializing_if = "Option::is_none")] - pub fields: Option<BTreeMap<String, FieldInfo>>, - #[serde(skip_serializing_if = "Option::is_none")] - pub children: Option<FieldInfo>, - #[serde(skip_serializing_if = "Option::is_none")] - pub subtypes: Option<Vec<NodeType>>, -} - -#[derive(Deserialize)] -pub struct NodeType { - #[serde(rename = "type")] - pub kind: String, - pub named: bool, -} - -#[derive(Deserialize)] -pub struct FieldInfo { - pub multiple: bool, - pub required: bool, - pub types: Vec<NodeType>, -} - -/// Given a tree-sitter node type's (kind, named) pair, returns a single string -/// representing the (unescaped) name we'll use to refer to corresponding QL -/// type. -fn node_type_name(kind: &str, named: bool) -> String { - if named { - kind.to_string() - } else { - format!("{}_unnamed", kind) - } -} - -const RESERVED_KEYWORDS: [&str; 14] = [ - "boolean", "case", "date", "float", "int", "key", "of", "order", "ref", "string", "subtype", - "type", "unique", "varchar", -]; - -/// Returns a string that's a copy of `name` but suitably escaped to be a valid -/// QL identifier. -fn escape_name(name: &str) -> String { - let mut result = String::new(); - - // If there's a leading underscore, replace it with 'underscore_'. - if let Some(c) = name.chars().next() { - if c == '_' { - result.push_str("underscore"); - } - } - for c in name.chars() { - match c { - '{' => result.push_str("lbrace"), - '}' => result.push_str("rbrace"), - '<' => result.push_str("langle"), - '>' => result.push_str("rangle"), - '[' => result.push_str("lbracket"), - ']' => result.push_str("rbracket"), - '(' => result.push_str("lparen"), - ')' => result.push_str("rparen"), - '|' => result.push_str("pipe"), - '=' => result.push_str("equal"), - '~' => result.push_str("tilde"), - '?' => result.push_str("question"), - '`' => result.push_str("backtick"), - '^' => result.push_str("caret"), - '!' => result.push_str("bang"), - '#' => result.push_str("hash"), - '%' => result.push_str("percent"), - '&' => result.push_str("ampersand"), - '.' => result.push_str("dot"), - ',' => result.push_str("comma"), - '/' => result.push_str("slash"), - ':' => result.push_str("colon"), - ';' => result.push_str("semicolon"), - '"' => result.push_str("dquote"), - '*' => result.push_str("star"), - '+' => result.push_str("plus"), - '-' => result.push_str("minus"), - '@' => result.push_str("at"), - _ if c.is_uppercase() => { - result.push('_'); - result.push_str(&c.to_lowercase().to_string()) - } - _ => result.push(c), - } - } - - for &keyword in &RESERVED_KEYWORDS { - if result == keyword { - result.push_str("__"); - break; - } - } - - result -} - -pub fn to_snake_case(word: &str) -> String { - let mut prev_upper = true; - let mut result = String::new(); - for c in word.chars() { - if c.is_uppercase() { - if !prev_upper { - result.push('_') - } - prev_upper = true; - result.push(c.to_ascii_lowercase()); - } else { - prev_upper = false; - result.push(c); - } - } - result -} -/// Given a valid dbscheme name (i.e. in snake case), produces the equivalent QL -/// name (i.e. in CamelCase). For example, "foo_bar_baz" becomes "FooBarBaz". -fn dbscheme_name_to_class_name(dbscheme_name: &str) -> String { - fn to_title_case(word: &str) -> String { - let mut first = true; - let mut result = String::new(); - for c in word.chars() { - if first { - first = false; - result.push(c.to_ascii_uppercase()); - } else { - result.push(c); - } - } - result - } - dbscheme_name - .split('_') - .map(to_title_case) - .collect::<Vec<String>>() - .join("") -} - -#[test] -fn to_snake_case_test() { - assert_eq!("python", to_snake_case("Python")); - assert_eq!("yaml", to_snake_case("YAML")); - assert_eq!("set_literal", to_snake_case("SetLiteral")); -} diff --git a/ql/ql/src/codeql_ql/StructuredLogs.qll b/ql/ql/src/codeql_ql/StructuredLogs.qll index f2e6939f7e6..60ea7e014ed 100644 --- a/ql/ql/src/codeql_ql/StructuredLogs.qll +++ b/ql/ql/src/codeql_ql/StructuredLogs.qll @@ -405,7 +405,7 @@ module KindPredicatesLog { or cand.(InLayer).getComputeRecursiveEvent() = recursive ) and - cand.hasLocationInfo(filepath, startline, _, _, _) + cand.getLocation().hasLocationInfo(filepath, startline, _, _, _) | cand order by filepath, startline ) diff --git a/ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll b/ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll index 1e7bfa71352..d15da37b4f2 100644 --- a/ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll +++ b/ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll @@ -1866,12 +1866,6 @@ module JSON { /** Gets the location of this element. */ final L::Location getLocation() { json_ast_node_info(this, _, _, result) } - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - /** Gets the parent of this element. */ final AstNode getParent() { json_ast_node_info(this, result, _, _) } diff --git a/ql/ql/src/queries/diagnostics/EmptyConsistencies.ql b/ql/ql/src/queries/diagnostics/EmptyConsistencies.ql index 5009e9370fb..85a65fbfdeb 100644 --- a/ql/ql/src/queries/diagnostics/EmptyConsistencies.ql +++ b/ql/ql/src/queries/diagnostics/EmptyConsistencies.ql @@ -58,6 +58,7 @@ where or ModConsistency::noResolve(node) and msg = "ModConsistency::noResolve" ) and + none() and // disabled for now not node.getLocation() .getFile() .getAbsolutePath() diff --git a/ql/rust-toolchain.toml b/ql/rust-toolchain.toml index 38ca5da4f14..04b7b3d5fd6 100644 --- a/ql/rust-toolchain.toml +++ b/ql/rust-toolchain.toml @@ -2,6 +2,6 @@ # extractor. It is set to the lowest version of Rust we want to support. [toolchain] -channel = "1.59" +channel = "1.68" profile = "minimal" components = [ "rustfmt" ] diff --git a/ql/scripts/create-extractor-pack.ps1 b/ql/scripts/create-extractor-pack.ps1 index 65b4dfc348a..1229621c2c1 100644 --- a/ql/scripts/create-extractor-pack.ps1 +++ b/ql/scripts/create-extractor-pack.ps1 @@ -1,6 +1,6 @@ cargo build --release -cargo run --release -p ql-generator -- --dbscheme ql/src/ql.dbscheme --library ql/src/codeql_ql/ast/internal/TreeSitter.qll +cargo run --release --bin generator -- --dbscheme ql/src/ql.dbscheme --library ql/src/codeql_ql/ast/internal/TreeSitter.qll codeql query format -i ql\src\codeql_ql\ast\internal\TreeSitter.qll if (Test-Path -Path extractor-pack) { @@ -10,5 +10,5 @@ mkdir extractor-pack | Out-Null cp codeql-extractor.yml, ql\src\ql.dbscheme, ql\src\ql.dbscheme.stats extractor-pack cp -Recurse tools extractor-pack mkdir extractor-pack\tools\win64 | Out-Null -cp target\release\ql-extractor.exe extractor-pack\tools\win64\extractor.exe -cp target\release\ql-autobuilder.exe extractor-pack\tools\win64\autobuilder.exe +cp target\release\extractor.exe extractor-pack\tools\win64\extractor.exe +cp target\release\autobuilder.exe extractor-pack\tools\win64\autobuilder.exe diff --git a/ql/scripts/create-extractor-pack.sh b/ql/scripts/create-extractor-pack.sh index d1b3c6312d9..01fbc2ad5a7 100755 --- a/ql/scripts/create-extractor-pack.sh +++ b/ql/scripts/create-extractor-pack.sh @@ -20,13 +20,12 @@ else fi cargo build --release - -cargo run --release -p ql-generator -- --dbscheme ql/src/ql.dbscheme --library ql/src/codeql_ql/ast/internal/TreeSitter.qll +cargo run --release --bin generator -- --dbscheme ql/src/ql.dbscheme --library ql/src/codeql_ql/ast/internal/TreeSitter.qll $CODEQL_BINARY query format -i ql/src/codeql_ql/ast/internal/TreeSitter.qll rm -rf extractor-pack mkdir -p extractor-pack cp -r codeql-extractor.yml tools ql/src/ql.dbscheme ql/src/ql.dbscheme.stats extractor-pack/ mkdir -p extractor-pack/tools/${platform} -cp target/release/ql-extractor extractor-pack/tools/${platform}/extractor -cp target/release/ql-autobuilder extractor-pack/tools/${platform}/autobuilder +cp target/release/extractor extractor-pack/tools/${platform}/extractor +cp target/release/autobuilder extractor-pack/tools/${platform}/autobuilder diff --git a/ruby/Makefile b/ruby/Makefile index 09f4deb1e85..f106d42a3bf 100644 --- a/ruby/Makefile +++ b/ruby/Makefile @@ -38,14 +38,14 @@ tools: $(BIN_FILES) rm -rf tools/bin mkdir tools/bin cp -r target/release/ruby-autobuilder$(EXE) tools/bin/autobuilder$(EXE) - cp -r target/release/ruby-extractor$(EXE) tools/bin/extractor$(EXE) + cp -r target/release/ruby-extractor$(EXE) tools/bin/extractor$(EXE) target/release/%$(EXE): - cargo build --release --bin $(basename $(notdir $@)) + cd extractor && cargo build --release dbscheme: - cargo build --bin ruby-generator - cargo run -p ruby-generator -- --dbscheme ql/lib/ruby.dbscheme --library ql/lib/codeql/ruby/ast/internal/TreeSitter.qll + cd extractor && cargo build --release + extractor/target/release/generator --dbscheme ql/lib/ruby.dbscheme --library ql/lib/codeql/ruby/ast/internal/TreeSitter.qll codeql query format -i ql/lib/codeql/ruby/ast/internal/TreeSitter.qll .PHONY: extractor @@ -63,8 +63,8 @@ extractor: $(FILES) $(BIN_FILES) cp tools/autobuild.cmd extractor-pack/tools/autobuild.cmd cp ql/lib/ruby.dbscheme.stats extractor-pack/ruby.dbscheme.stats cp ql/lib/ruby.dbscheme extractor-pack/ruby.dbscheme - cp target/release/ruby-extractor$(EXE) extractor-pack/tools/$(CODEQL_PLATFORM)/extractor$(EXE) - cp target/release/ruby-autobuilder$(EXE) extractor-pack/tools/$(CODEQL_PLATFORM)/autobuilder$(EXE) + cp extractor/target/release/extractor$(EXE) extractor-pack/tools/$(CODEQL_PLATFORM)/extractor$(EXE) + cp extractor/target/release/autobuilder$(EXE) extractor-pack/tools/$(CODEQL_PLATFORM)/autobuilder$(EXE) test: extractor dbscheme codeql test run --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --search-path extractor-pack --consistency-queries ql/consistency-queries ql/test diff --git a/ruby/actions/create-extractor-pack/action.yml b/ruby/actions/create-extractor-pack/action.yml index 4396b7f79cc..7f18dea5902 100644 --- a/ruby/actions/create-extractor-pack/action.yml +++ b/ruby/actions/create-extractor-pack/action.yml @@ -24,6 +24,6 @@ runs: if: steps.cache-extractor.outputs.cache-hit != 'true' shell: bash run: | - cargo install cross --version 0.2.1 + cargo install cross --version 0.2.5 scripts/create-extractor-pack.sh working-directory: ruby diff --git a/ruby/doc/HOWTO.md b/ruby/doc/HOWTO.md index d2c4c316db5..ccfb8c9bc5e 100644 --- a/ruby/doc/HOWTO.md +++ b/ruby/doc/HOWTO.md @@ -7,7 +7,7 @@ This document contains information about common development tasks. [Install Rust](https://www.rust-lang.org/tools/install), then run: ```bash -cargo build --release +(cd extractor && cargo build --release) ``` ## Generating the database schema and QL library @@ -16,7 +16,7 @@ The generated `ql/lib/ruby.dbscheme` and `ql/lib/codeql/ruby/ast/internal/TreeSi ```bash # Run the generator -cargo run --release -p ruby-generator -- --dbscheme ql/lib/ruby.dbscheme --library ql/lib/codeql/ruby/ast/internal/TreeSitter.qll +(cd extractor && cargo run --release --bin generator -- --dbscheme ../ql/lib/ruby.dbscheme --library ../ql/lib/codeql/ruby/ast/internal/TreeSitter.qll) # Then auto-format the QL library codeql query format -i ql/lib/codeql/ruby/ast/internal/TreeSitter.qll ``` diff --git a/ruby/extractor/Cargo.lock b/ruby/extractor/Cargo.lock index 6722006cd3a..8d7f908a802 100644 Binary files a/ruby/extractor/Cargo.lock and b/ruby/extractor/Cargo.lock differ diff --git a/ruby/extractor/Cargo.toml b/ruby/extractor/Cargo.toml index 3a36533d280..ced118609fd 100644 --- a/ruby/extractor/Cargo.toml +++ b/ruby/extractor/Cargo.toml @@ -7,7 +7,6 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -flate2 = "1.0" tree-sitter = "0.20" tree-sitter-embedded-template = { git = "https://github.com/tree-sitter/tree-sitter-embedded-template.git", rev = "203f7bd3c1bbfbd98fc19add4b8fcb213c059205" } tree-sitter-ruby = { git = "https://github.com/tree-sitter/tree-sitter-ruby.git", rev = "206c7077164372c596ffa8eaadb9435c28941364" } @@ -15,10 +14,7 @@ clap = "3.0" tracing = "0.1" tracing-subscriber = { version = "0.3.3", features = ["env-filter"] } rayon = "1.5.0" -num_cpus = "1.14.0" regex = "1.7.1" encoding = "0.2" lazy_static = "1.4.0" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -chrono = { version = "0.4.19", features = ["serde"] } +codeql-extractor = { path = "../../shared/tree-sitter-extractor" } diff --git a/ruby/extractor/Cross.toml b/ruby/extractor/Cross.toml index 17726bd5e82..f3ed51aee59 100644 --- a/ruby/extractor/Cross.toml +++ b/ruby/extractor/Cross.toml @@ -1,2 +1,8 @@ [target.x86_64-unknown-linux-gnu] image = "centos/devtoolset-7-toolchain-centos7" + +[build.env] +# Provide the path to the shared extractor +# Cross mounts this directory as a volume, so builds inside the docker container +# can see it. +volumes = ["__CODEQL-EXTRACTOR=../../shared/tree-sitter-extractor"] diff --git a/ruby/extractor/rust-toolchain.toml b/ruby/extractor/rust-toolchain.toml index a4602066f4b..e56467f055c 100644 --- a/ruby/extractor/rust-toolchain.toml +++ b/ruby/extractor/rust-toolchain.toml @@ -2,6 +2,6 @@ # extractor. It is set to the lowest version of Rust we want to support. [toolchain] -channel = "1.54" +channel = "1.68" profile = "minimal" components = [ "rustfmt" ] diff --git a/ruby/extractor/src/bin/extractor.rs b/ruby/extractor/src/bin/extractor.rs index 300a94444a6..b6fda52f4fb 100644 --- a/ruby/extractor/src/bin/extractor.rs +++ b/ruby/extractor/src/bin/extractor.rs @@ -1,9 +1,8 @@ #[macro_use] extern crate lazy_static; -extern crate num_cpus; use clap::arg; -use encoding::{self}; +use encoding; use rayon::prelude::*; use std::borrow::Cow; use std::fs; @@ -11,33 +10,7 @@ use std::io::BufRead; use std::path::{Path, PathBuf}; use tree_sitter::{Language, Parser, Range}; -use ruby_extractor::{diagnostics, extractor, file_paths, node_types, trap}; - -/** - * Gets the number of threads the extractor should use, by reading the - * CODEQL_THREADS environment variable and using it as described in the - * extractor spec: - * - * "If the number is positive, it indicates the number of threads that should - * be used. If the number is negative or zero, it should be added to the number - * of cores available on the machine to determine how many threads to use - * (minimum of 1). If unspecified, should be considered as set to -1." - */ -fn num_codeql_threads() -> Result<usize, String> { - let threads_str = std::env::var("CODEQL_THREADS").unwrap_or_else(|_| "-1".to_owned()); - match threads_str.parse::<i32>() { - Ok(num) if num <= 0 => { - let reduction = -num as usize; - Ok(std::cmp::max(1, num_cpus::get() - reduction)) - } - Ok(num) => Ok(num as usize), - - Err(_) => Err(format!( - "Unable to parse CODEQL_THREADS value '{}'", - &threads_str - )), - } -} +use codeql_extractor::{diagnostics, extractor, file_paths, node_types, trap}; lazy_static! { static ref CP_NUMBER: regex::Regex = regex::Regex::new("cp([0-9]+)").unwrap(); @@ -67,7 +40,7 @@ fn main() -> std::io::Result<()> { .init(); let diagnostics = diagnostics::DiagnosticLoggers::new("ruby"); let mut main_thread_logger = diagnostics.logger(); - let num_threads = match num_codeql_threads() { + let num_threads = match codeql_extractor::options::num_threads() { Ok(num) => num, Err(e) => { main_thread_logger.write( @@ -307,8 +280,10 @@ fn scan_erb( } } } + if result.is_empty() { let root = tree.root_node(); + // Add an empty range at the end of the file result.push(Range { start_byte: root.end_byte(), @@ -320,6 +295,8 @@ fn scan_erb( (result, line_breaks) } +/// Advance `index` to the next non-whitespace character. +/// Newlines are **not** considered whitespace. fn skip_space(content: &[u8], index: usize) -> usize { let mut index = index; while index < content.len() { diff --git a/ruby/extractor/src/bin/generator.rs b/ruby/extractor/src/bin/generator.rs index 61d8efd671b..172575bc17e 100644 --- a/ruby/extractor/src/bin/generator.rs +++ b/ruby/extractor/src/bin/generator.rs @@ -6,8 +6,8 @@ use std::io::LineWriter; use std::io::Write; use std::path::PathBuf; -use ruby_extractor::generator::{dbscheme, language::Language, ql, ql_gen}; -use ruby_extractor::node_types; +use codeql_extractor::generator::{dbscheme, language::Language, ql, ql_gen}; +use codeql_extractor::node_types; /// Given the name of the parent node, and its field information, returns a pair, /// the first of which is the field's type. The second is an optional dbscheme diff --git a/ruby/extractor/src/generator/language.rs b/ruby/extractor/src/generator/language.rs deleted file mode 100644 index f0b0ed1790f..00000000000 --- a/ruby/extractor/src/generator/language.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub struct Language { - pub name: String, - pub node_types: &'static str, -} diff --git a/ruby/extractor/src/generator/ql.rs b/ruby/extractor/src/generator/ql.rs deleted file mode 100644 index 7dd94f24bea..00000000000 --- a/ruby/extractor/src/generator/ql.rs +++ /dev/null @@ -1,295 +0,0 @@ -use std::collections::BTreeSet; -use std::fmt; - -#[derive(Clone, Eq, PartialEq, Hash)] -pub enum TopLevel<'a> { - Class(Class<'a>), - Import(Import<'a>), - Module(Module<'a>), -} - -impl<'a> fmt::Display for TopLevel<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - TopLevel::Import(imp) => write!(f, "{}", imp), - TopLevel::Class(cls) => write!(f, "{}", cls), - TopLevel::Module(m) => write!(f, "{}", m), - } - } -} - -#[derive(Clone, Eq, PartialEq, Hash)] -pub struct Import<'a> { - pub module: &'a str, - pub alias: Option<&'a str>, -} - -impl<'a> fmt::Display for Import<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "import {}", &self.module)?; - if let Some(name) = &self.alias { - write!(f, " as {}", name)?; - } - Ok(()) - } -} -#[derive(Clone, Eq, PartialEq, Hash)] -pub struct Class<'a> { - pub qldoc: Option<String>, - pub name: &'a str, - pub is_abstract: bool, - pub supertypes: BTreeSet<Type<'a>>, - pub characteristic_predicate: Option<Expression<'a>>, - pub predicates: Vec<Predicate<'a>>, -} - -impl<'a> fmt::Display for Class<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if let Some(qldoc) = &self.qldoc { - write!(f, "/** {} */", qldoc)?; - } - if self.is_abstract { - write!(f, "abstract ")?; - } - write!(f, "class {} extends ", &self.name)?; - for (index, supertype) in self.supertypes.iter().enumerate() { - if index > 0 { - write!(f, ", ")?; - } - write!(f, "{}", supertype)?; - } - writeln!(f, " {{ ")?; - - if let Some(charpred) = &self.characteristic_predicate { - writeln!( - f, - " {}", - Predicate { - qldoc: None, - name: self.name, - overridden: false, - is_final: false, - return_type: None, - formal_parameters: vec![], - body: charpred.clone(), - } - )?; - } - - for predicate in &self.predicates { - writeln!(f, " {}", predicate)?; - } - - write!(f, "}}")?; - - Ok(()) - } -} - -#[derive(Clone, Eq, PartialEq, Hash)] -pub struct Module<'a> { - pub qldoc: Option<String>, - pub name: &'a str, - pub body: Vec<TopLevel<'a>>, -} - -impl<'a> fmt::Display for Module<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if let Some(qldoc) = &self.qldoc { - write!(f, "/** {} */", qldoc)?; - } - writeln!(f, "module {} {{ ", self.name)?; - for decl in &self.body { - writeln!(f, " {}", decl)?; - } - write!(f, "}}")?; - Ok(()) - } -} -// The QL type of a column. -#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] -pub enum Type<'a> { - /// Primitive `int` type. - Int, - - /// Primitive `string` type. - String, - - /// A database type that will need to be referred to with an `@` prefix. - At(&'a str), - - /// A user-defined type. - Normal(&'a str), -} - -impl<'a> fmt::Display for Type<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Type::Int => write!(f, "int"), - Type::String => write!(f, "string"), - Type::Normal(name) => write!(f, "{}", name), - Type::At(name) => write!(f, "@{}", name), - } - } -} - -#[derive(Clone, Eq, PartialEq, Hash)] -pub enum Expression<'a> { - Var(&'a str), - String(&'a str), - Integer(usize), - Pred(&'a str, Vec<Expression<'a>>), - And(Vec<Expression<'a>>), - Or(Vec<Expression<'a>>), - Equals(Box<Expression<'a>>, Box<Expression<'a>>), - Dot(Box<Expression<'a>>, &'a str, Vec<Expression<'a>>), - Aggregate { - name: &'a str, - vars: Vec<FormalParameter<'a>>, - range: Option<Box<Expression<'a>>>, - expr: Box<Expression<'a>>, - second_expr: Option<Box<Expression<'a>>>, - }, -} - -impl<'a> fmt::Display for Expression<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Expression::Var(x) => write!(f, "{}", x), - Expression::String(s) => write!(f, "\"{}\"", s), - Expression::Integer(n) => write!(f, "{}", n), - Expression::Pred(n, args) => { - write!(f, "{}(", n)?; - for (index, arg) in args.iter().enumerate() { - if index > 0 { - write!(f, ", ")?; - } - write!(f, "{}", arg)?; - } - write!(f, ")") - } - Expression::And(conjuncts) => { - if conjuncts.is_empty() { - write!(f, "any()") - } else { - for (index, conjunct) in conjuncts.iter().enumerate() { - if index > 0 { - write!(f, " and ")?; - } - write!(f, "({})", conjunct)?; - } - Ok(()) - } - } - Expression::Or(disjuncts) => { - if disjuncts.is_empty() { - write!(f, "none()") - } else { - for (index, disjunct) in disjuncts.iter().enumerate() { - if index > 0 { - write!(f, " or ")?; - } - write!(f, "({})", disjunct)?; - } - Ok(()) - } - } - Expression::Equals(a, b) => write!(f, "{} = {}", a, b), - Expression::Dot(x, member_pred, args) => { - write!(f, "{}.{}(", x, member_pred)?; - for (index, arg) in args.iter().enumerate() { - if index > 0 { - write!(f, ", ")?; - } - write!(f, "{}", arg)?; - } - write!(f, ")") - } - Expression::Aggregate { - name, - vars, - range, - expr, - second_expr, - } => { - write!(f, "{}(", name)?; - if !vars.is_empty() { - for (index, var) in vars.iter().enumerate() { - if index > 0 { - write!(f, ", ")?; - } - write!(f, "{}", var)?; - } - write!(f, " | ")?; - } - if let Some(range) = range { - write!(f, "{} | ", range)?; - } - write!(f, "{}", expr)?; - if let Some(second_expr) = second_expr { - write!(f, ", {}", second_expr)?; - } - write!(f, ")") - } - } - } -} - -#[derive(Clone, Eq, PartialEq, Hash)] -pub struct Predicate<'a> { - pub qldoc: Option<String>, - pub name: &'a str, - pub overridden: bool, - pub is_final: bool, - pub return_type: Option<Type<'a>>, - pub formal_parameters: Vec<FormalParameter<'a>>, - pub body: Expression<'a>, -} - -impl<'a> fmt::Display for Predicate<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if let Some(qldoc) = &self.qldoc { - write!(f, "/** {} */", qldoc)?; - } - if self.is_final { - write!(f, "final ")?; - } - if self.overridden { - write!(f, "override ")?; - } - match &self.return_type { - None => write!(f, "predicate ")?, - Some(return_type) => write!(f, "{} ", return_type)?, - } - write!(f, "{}(", self.name)?; - for (index, param) in self.formal_parameters.iter().enumerate() { - if index > 0 { - write!(f, ", ")?; - } - write!(f, "{}", param)?; - } - write!(f, ") {{ {} }}", self.body)?; - - Ok(()) - } -} - -#[derive(Clone, Eq, PartialEq, Hash)] -pub struct FormalParameter<'a> { - pub name: &'a str, - pub param_type: Type<'a>, -} - -impl<'a> fmt::Display for FormalParameter<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} {}", self.param_type, self.name) - } -} - -/// Generates a QL library by writing the given `elements` to the `file`. -pub fn write<'a>(file: &mut dyn std::io::Write, elements: &'a [TopLevel]) -> std::io::Result<()> { - for element in elements { - write!(file, "{}\n\n", &element)?; - } - Ok(()) -} diff --git a/ruby/ql/lib/change-notes/2023-03-21-evaluation-order.md b/ruby/ql/lib/change-notes/2023-03-21-evaluation-order.md new file mode 100644 index 00000000000..0b943101e43 --- /dev/null +++ b/ruby/ql/lib/change-notes/2023-03-21-evaluation-order.md @@ -0,0 +1,5 @@ +--- + category: minorAnalysis +--- +* Control flow graph: the evaluation order of scope expressions and receivers in multiple assignments has been adjusted to match the changes made in Ruby +3.1 and 3.2. diff --git a/ruby/ql/lib/change-notes/2023-03-23-dataflow-renaming.md b/ruby/ql/lib/change-notes/2023-03-23-dataflow-renaming.md new file mode 100644 index 00000000000..54df71fae46 --- /dev/null +++ b/ruby/ql/lib/change-notes/2023-03-23-dataflow-renaming.md @@ -0,0 +1,6 @@ +--- +category: deprecated +--- +* The recently introduced new data flow and taint tracking APIs have had a + number of module and predicate renamings. The old APIs remain in place for + now. diff --git a/ruby/ql/lib/change-notes/2023-03-28-dataflow-rm-footgun.md b/ruby/ql/lib/change-notes/2023-03-28-dataflow-rm-footgun.md new file mode 100644 index 00000000000..82dc0a1d893 --- /dev/null +++ b/ruby/ql/lib/change-notes/2023-03-28-dataflow-rm-footgun.md @@ -0,0 +1,4 @@ +--- +category: fix +--- +* Fixed some accidental predicate visibility in the backwards-compatible wrapper for data flow configurations. In particular `DataFlow::hasFlowPath`, `DataFlow::hasFlow`, `DataFlow::hasFlowTo`, and `DataFlow::hasFlowToExpr` were accidentally exposed in a single version. diff --git a/ruby/ql/lib/codeql/ruby/ast/Constant.qll b/ruby/ql/lib/codeql/ruby/ast/Constant.qll index b76fac8d47f..0a716ed8407 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Constant.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Constant.qll @@ -235,55 +235,6 @@ class ConstantAccess extends Expr, TConstantAccess { } } -private class TokenConstantAccess extends ConstantAccess, TTokenConstantAccess { - private Ruby::Constant g; - - TokenConstantAccess() { this = TTokenConstantAccess(g) } - - final override string getName() { result = g.getValue() } -} - -private class ScopeResolutionConstantAccess extends ConstantAccess, TScopeResolutionConstantAccess { - private Ruby::ScopeResolution g; - private Ruby::Constant constant; - - ScopeResolutionConstantAccess() { this = TScopeResolutionConstantAccess(g, constant) } - - final override string getName() { result = constant.getValue() } - - final override Expr getScopeExpr() { toGenerated(result) = g.getScope() } - - final override predicate hasGlobalScope() { not exists(g.getScope()) } -} - -private class ConstantReadAccessSynth extends ConstantAccess, TConstantReadAccessSynth { - private string value; - - ConstantReadAccessSynth() { this = TConstantReadAccessSynth(_, _, value) } - - final override string getName() { - if this.hasGlobalScope() then result = value.suffix(2) else result = value - } - - final override Expr getScopeExpr() { synthChild(this, 0, result) } - - final override predicate hasGlobalScope() { value.matches("::%") } -} - -private class ConstantWriteAccessSynth extends ConstantAccess, TConstantWriteAccessSynth { - private string value; - - ConstantWriteAccessSynth() { this = TConstantWriteAccessSynth(_, _, value) } - - final override string getName() { - if this.hasGlobalScope() then result = value.suffix(2) else result = value - } - - final override Expr getScopeExpr() { synthChild(this, 0, result) } - - final override predicate hasGlobalScope() { value.matches("::%") } -} - /** * A use (read) of a constant. * diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Call.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Call.qll index b6ac243e891..74acef8e860 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Call.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Call.qll @@ -43,11 +43,16 @@ class MethodCallSynth extends MethodCallImpl, TMethodCallSynth { final override AstNode getReceiverImpl() { synthChild(this, 0, result) } - final override AstNode getArgumentImpl(int n) { synthChild(this, n + 1, result) and n >= 0 } + final override AstNode getArgumentImpl(int n) { + synthChild(this, n + 1, result) and + n in [0 .. this.getNumberOfArgumentsImpl() - 1] + } final override int getNumberOfArgumentsImpl() { this = TMethodCallSynth(_, _, _, _, result) } - final override Block getBlockImpl() { synthChild(this, -2, result) } + final override Block getBlockImpl() { + synthChild(this, this.getNumberOfArgumentsImpl() + 1, result) + } } class IdentifierMethodCall extends MethodCallImpl, TIdentifierMethodCall { diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Constant.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Constant.qll index 53355695e57..d68a5582e17 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Constant.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Constant.qll @@ -1,6 +1,8 @@ private import codeql.ruby.AST +private import codeql.ruby.ast.internal.AST private import codeql.ruby.ast.internal.Literal private import codeql.ruby.ast.internal.Module +private import codeql.ruby.ast.internal.TreeSitter private import codeql.ruby.controlflow.CfgNodes private import codeql.ruby.dataflow.SSA private import ExprNodes @@ -559,3 +561,60 @@ private predicate isArrayExpr(Expr e, ArrayLiteralCfgNode arr) { // results if the source is a phi node. forex(ExprCfgNode n | n = e.getAControlFlowNode() | isArrayConstant(n, arr)) } + +private class TokenConstantAccess extends ConstantAccess, TTokenConstantAccess { + private Ruby::Constant g; + + TokenConstantAccess() { this = TTokenConstantAccess(g) } + + final override string getName() { result = g.getValue() } +} + +/** + * A constant access that has a scope resolution qualifier. + */ +class ScopeResolutionConstantAccess extends ConstantAccess, TScopeResolutionConstantAccess { + private Ruby::ScopeResolution g; + private Ruby::Constant constant; + + ScopeResolutionConstantAccess() { this = TScopeResolutionConstantAccess(g, constant) } + + /** + * Gets the name of the constant. + */ + final override string getName() { result = constant.getValue() } + + /** Gets the scope resolution expression. */ + final override Expr getScopeExpr() { toGenerated(result) = g.getScope() } + + /** Holds if this constant access has a global scope. */ + final override predicate hasGlobalScope() { not exists(g.getScope()) } +} + +private class ConstantReadAccessSynth extends ConstantAccess, TConstantReadAccessSynth { + private string value; + + ConstantReadAccessSynth() { this = TConstantReadAccessSynth(_, _, value) } + + final override string getName() { + if this.hasGlobalScope() then result = value.suffix(2) else result = value + } + + final override Expr getScopeExpr() { synthChild(this, 0, result) } + + final override predicate hasGlobalScope() { value.matches("::%") } +} + +private class ConstantWriteAccessSynth extends ConstantAccess, TConstantWriteAccessSynth { + private string value; + + ConstantWriteAccessSynth() { this = TConstantWriteAccessSynth(_, _, value) } + + final override string getName() { + if this.hasGlobalScope() then result = value.suffix(2) else result = value + } + + final override Expr getScopeExpr() { synthChild(this, 0, result) } + + final override predicate hasGlobalScope() { value.matches("::%") } +} diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll index 8160966ac1a..9e8ca5e8fba 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll @@ -4,7 +4,9 @@ private import AST private import TreeSitter class StmtSequenceSynth extends StmtSequence, TStmtSequenceSynth { - final override Stmt getStmt(int n) { synthChild(this, n, result) } + final override Stmt getStmt(int n) { + result = rank[n + 1](int i, Stmt s | synthChild(this, i, s) | s order by i) + } final override string toString() { result = "..." } } diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll index 7b8ab7acba3..f6fa4ca1528 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll @@ -21,6 +21,8 @@ private module Cached { qName = getAnAssumedGlobalConst() or qName = namespaceDeclaration(_) + or + qName = getAnAssumedGlobalNamespacePrefix(_) } or TUnresolved(Namespace n) { not exists(namespaceDeclaration(n)) } @@ -36,6 +38,8 @@ private module Cached { TResolved(container) = resolveConstantReadAccess(n.getScopeExpr()) and result = scopeAppend(container, n.getName()) ) + or + result = getAnAssumedGlobalNamespacePrefix(n) } cached @@ -407,12 +411,35 @@ private module ResolveImpl { */ string getAnAssumedGlobalConst() { exists(ConstantAccess access | - not exists(access.getScopeExpr()) and result = access.getName() and isToplevel(access) ) } + private ConstantAccess getANamespaceScopeInTopLevel() { + result.(Namespace).getEnclosingModule() instanceof Toplevel + or + result = getANamespaceScopeInTopLevel().getScopeExpr() + } + + /** + * Gets the syntactical qualified name of the given constant access, which must be a top-level + * namespace or scope prefix thereof. + * + * For example, for `module A::B::C` this gets `A`, `A::B`, and `A::B::C` for the two prefixes + * and the module itself, respectively. + */ + string getAnAssumedGlobalNamespacePrefix(ConstantAccess access) { + access = getANamespaceScopeInTopLevel() and + ( + not exists(access.getScopeExpr()) and + result = access.getName() + or + result = + scopeAppend(getAnAssumedGlobalNamespacePrefix(access.getScopeExpr()), access.getName()) + ) + } + pragma[nomagic] private string isDefinedConstantNonRec(string container, string name) { result = resolveConstantWriteAccessNonRec(_, container, name) @@ -420,6 +447,12 @@ private module ResolveImpl { result = [builtin(), getAnAssumedGlobalConst()] and name = result and container = "Object" + or + exists(ConstantAccess access | + container = getAnAssumedGlobalNamespacePrefix(access.getScopeExpr()) and + name = access.getName() and + result = getAnAssumedGlobalNamespacePrefix(access) + ) } pragma[nomagic] diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll index 289f812931c..6c92f401001 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll @@ -3,6 +3,7 @@ private import AST private import TreeSitter private import codeql.ruby.ast.internal.Call +private import codeql.ruby.ast.internal.Constant private import codeql.ruby.ast.internal.Expr private import codeql.ruby.ast.internal.Variable private import codeql.ruby.ast.internal.Pattern @@ -817,7 +818,7 @@ private module AssignOperationDesugar { i in [0 .. sao.getNumberOfArguments()] or parent = setter and - i = opAssignIndex + 1 and + i = opAssignIndex and child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(sao, opAssignIndex))) ) @@ -950,22 +951,60 @@ private module DestructuredAssignDesugar { } } + abstract private class LhsWithReceiver extends Expr { + abstract Expr getReceiver(); + + abstract SynthKind getSynthKind(); + } + + private class LhsCall extends LhsWithReceiver instanceof MethodCall { + final override Expr getReceiver() { result = MethodCall.super.getReceiver() } + + final override SynthKind getSynthKind() { + result = MethodCallKind(super.getMethodName(), false, super.getNumberOfArguments()) + } + } + + private class LhsScopedConstant extends LhsWithReceiver, ScopeResolutionConstantAccess { + LhsScopedConstant() { exists(this.getScopeExpr()) } + + final override Expr getReceiver() { result = this.getScopeExpr() } + + final override SynthKind getSynthKind() { result = ConstantWriteAccessKind(this.getName()) } + } + pragma[nomagic] private predicate destructuredAssignSynthesis(AstNode parent, int i, Child child) { - exists(DestructuredAssignExpr tae | + exists(DestructuredAssignExpr tae, int total | total = tae.getNumberOfElements() | parent = tae and i = -1 and child = SynthChild(StmtSequenceKind()) or exists(AstNode seq | seq = TStmtSequenceSynth(tae, -1) | + exists(LhsWithReceiver mc, int j | mc = tae.getElement(j) | + parent = seq and + i = j and + child = SynthChild(AssignExprKind()) + or + exists(AstNode assign | assign = TAssignExprSynth(seq, j) | + parent = assign and + i = 0 and + child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(tae, j))) + or + parent = assign and + i = 1 and + child = childRef(mc.getReceiver()) + ) + ) + or parent = seq and - i = 0 and + i = total and child = SynthChild(AssignExprKind()) or - exists(AstNode assign | assign = TAssignExprSynth(seq, 0) | + exists(AstNode assign | assign = TAssignExprSynth(seq, total) | parent = assign and i = 0 and - child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(tae, 0))) + child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(tae, total))) or parent = assign and i = 1 and @@ -981,10 +1020,35 @@ private module DestructuredAssignDesugar { restIndex = tae.getRestIndexOrNumberOfElements() | parent = seq and - i = j + 1 and + i = j + 1 + total and child = SynthChild(AssignExprKind()) or - exists(AstNode assign | assign = TAssignExprSynth(seq, j + 1) | + exists(AstNode assign | assign = TAssignExprSynth(seq, j + 1 + total) | + exists(LhsWithReceiver mc | mc = elem | + parent = assign and + i = 0 and + child = SynthChild(mc.getSynthKind()) + or + exists(AstNode call | synthChild(assign, 0, call) | + parent = call and + i = 0 and + child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(tae, j))) + or + parent = call and + child = childRef(mc.(MethodCall).getArgument(i - 1)) + ) + ) + or + ( + elem instanceof VariableAccess + or + elem instanceof ConstantAccess and + not exists(Ruby::ScopeResolution g | + elem = TScopeResolutionConstantAccess(g, _) and exists(g.getScope()) + ) + or + elem instanceof DestructuredLhsExpr + ) and parent = assign and i = 0 and child = childRef(elem) @@ -995,7 +1059,7 @@ private module DestructuredAssignDesugar { or parent = TMethodCallSynth(assign, 1, _, _, _) and i = 0 and - child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(tae, 0))) + child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(tae, total))) or j < restIndex and parent = TMethodCallSynth(assign, 1, _, _, _) and @@ -1016,14 +1080,14 @@ private module DestructuredAssignDesugar { child = SynthChild(IntegerLiteralKind(j)) or i = 1 and - child = SynthChild(IntegerLiteralKind(restIndex - tae.getNumberOfElements())) + child = SynthChild(IntegerLiteralKind(restIndex - total)) ) ) or j > restIndex and parent = TMethodCallSynth(assign, 1, _, _, _) and i = 1 and - child = SynthChild(IntegerLiteralKind(j - tae.getNumberOfElements())) + child = SynthChild(IntegerLiteralKind(j - total)) ) ) ) @@ -1050,26 +1114,48 @@ private module DestructuredAssignDesugar { final override predicate location(AstNode n, Location l) { exists(DestructuredAssignExpr tae, StmtSequence seq | seq = tae.getDesugared() | - n = seq.getStmt(0) and + synthChild(seq, tae.getNumberOfElements(), n) and hasLocation(tae.getRightOperand(), l) or - exists(AstNode elem, int j | + exists(LhsWithReceiver elem, int j | elem = tae.getElement(j) and - n = seq.getStmt(j + 1) and + synthChild(seq, j, n) and + hasLocation(elem.getReceiver(), l) + ) + or + exists(AstNode elem, int j | elem = tae.getElement(j) | + synthChild(seq, j + 1 + tae.getNumberOfElements(), n) and hasLocation(elem, l) ) ) } final override predicate localVariable(AstNode n, int i) { - n instanceof DestructuredAssignExpr and - i = 0 + i = [0 .. n.(DestructuredAssignExpr).getNumberOfElements()] + } + + final override predicate constantWriteAccess(string name) { + exists(DestructuredAssignExpr tae, LhsScopedConstant ca | + ca = tae.getElement(_) and + name = ca.getName() + ) } final override predicate methodCall(string name, boolean setter, int arity) { name = "[]" and setter = false and arity = 1 + or + exists(DestructuredAssignExpr tae, MethodCall mc | + mc = tae.getElement(_) and + name = mc.getMethodName() and + setter = false and + arity = mc.getNumberOfArguments() + ) + } + + final override predicate excludeFromControlFlowTree(AstNode n) { + n = any(DestructuredAssignExpr tae).getElement(_).(LhsWithReceiver) } } } @@ -1192,10 +1278,10 @@ private module ForLoopDesugar { child = childRef(for.getValue()) // value is the Enumerable or parent = eachCall and - i = -2 and + i = 1 and child = SynthChild(BraceBlockKind()) or - exists(Block block | block = TBraceBlockSynth(eachCall, -2) | + exists(Block block | block = TBraceBlockSynth(eachCall, 1) | // block params parent = block and i = 0 and @@ -1442,14 +1528,13 @@ private module SafeNavigationCallDesugar { i = 1 ) or - parent = TMethodCallSynth(ifExpr, 2, _, _, _) and - ( + exists(int arity | parent = TMethodCallSynth(ifExpr, 2, _, _, arity) | i = 0 and child = SynthChild(local) or child = childRef(call.getArgumentImpl(i - 1)) or - child = childRef(call.getBlockImpl()) and i = -2 + child = childRef(call.getBlockImpl()) and i = arity + 1 ) ) ) diff --git a/ruby/ql/lib/codeql/ruby/dataflow/FlowSteps.qll b/ruby/ql/lib/codeql/ruby/dataflow/FlowSteps.qll index 881441fc765..f509208aab3 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/FlowSteps.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/FlowSteps.qll @@ -2,10 +2,8 @@ * Provides classes representing various flow steps for taint tracking. */ +private import codeql.util.Unit private import codeql.ruby.DataFlow -private import internal.DataFlowPrivate as DFPrivate - -private class Unit = DFPrivate::Unit; /** * A module importing the frameworks that implement additional flow steps, diff --git a/ruby/ql/lib/codeql/ruby/dataflow/SSA.qll b/ruby/ql/lib/codeql/ruby/dataflow/SSA.qll index 241b2bb763a..97bb3407b57 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/SSA.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/SSA.qll @@ -216,9 +216,9 @@ module Ssa { ) } - final override string toString() { result = Definition.super.toString() } + final override string toString() { result = write.toString() } - final override Location getLocation() { result = this.getControlFlowNode().getLocation() } + final override Location getLocation() { result = write.getLocation() } } /** diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlow.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlow.qll index 617362ab4f0..865d7b4d6ce 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlow.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlow.qll @@ -2,7 +2,7 @@ * Provides an implementation of global (interprocedural) data flow. This file * re-exports the local (intraprocedural) data flow analysis from * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Make` and `MakeWithState` modules. + * through the `Global` and `GlobalWithState` modules. */ private import DataFlowImplCommon @@ -73,10 +73,10 @@ signature module ConfigSig { */ default FlowFeature getAFeature() { none() } - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ default predicate sourceGrouping(Node source, string sourceGroup) { none() } - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ default predicate sinkGrouping(Node sink, string sinkGroup) { none() } /** @@ -166,10 +166,10 @@ signature module StateConfigSig { */ default FlowFeature getAFeature() { none() } - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ default predicate sourceGrouping(Node source, string sourceGroup) { none() } - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ default predicate sinkGrouping(Node sink, string sinkGroup) { none() } /** @@ -182,15 +182,15 @@ signature module StateConfigSig { } /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * Gets the exploration limit for `partialFlow` and `partialFlowRev` * measured in approximate number of interprocedural steps. */ signature int explorationLimitSig(); /** - * The output of a data flow computation. + * The output of a global data flow computation. */ -signature module DataFlowSig { +signature module GlobalFlowSig { /** * A `Node` augmented with a call context (except for sinks) and an access path. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. @@ -203,28 +203,28 @@ signature module DataFlowSig { * The corresponding paths are generated from the end-points and the graph * included in the module `PathGraph`. */ - predicate hasFlowPath(PathNode source, PathNode sink); + predicate flowPath(PathNode source, PathNode sink); /** * Holds if data can flow from `source` to `sink`. */ - predicate hasFlow(Node source, Node sink); + predicate flow(Node source, Node sink); /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowTo(Node sink); + predicate flowTo(Node sink); /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowToExpr(DataFlowExpr sink); + predicate flowToExpr(DataFlowExpr sink); } /** - * Constructs a standard data flow computation. + * Constructs a global data flow computation. */ -module Make<ConfigSig Config> implements DataFlowSig { +module Global<ConfigSig Config> implements GlobalFlowSig { private module C implements FullStateConfigSig { import DefaultState<Config> import Config @@ -233,10 +233,15 @@ module Make<ConfigSig Config> implements DataFlowSig { import Impl<C> } +/** DEPRECATED: Use `Global` instead. */ +deprecated module Make<ConfigSig Config> implements GlobalFlowSig { + import Global<Config> +} + /** - * Constructs a data flow computation using flow state. + * Constructs a global data flow computation using flow state. */ -module MakeWithState<StateConfigSig Config> implements DataFlowSig { +module GlobalWithState<StateConfigSig Config> implements GlobalFlowSig { private module C implements FullStateConfigSig { import Config } @@ -244,6 +249,11 @@ module MakeWithState<StateConfigSig Config> implements DataFlowSig { import Impl<C> } +/** DEPRECATED: Use `GlobalWithState` instead. */ +deprecated module MakeWithState<StateConfigSig Config> implements GlobalFlowSig { + import GlobalWithState<Config> +} + signature class PathNodeSig { /** Gets a textual representation of this element. */ string toString(); diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll index c47b0308855..6ea97954bdf 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll @@ -8,6 +8,7 @@ private import DataFlowImplCommon private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommonPublic +private import codeql.util.Unit import DataFlow /** @@ -91,10 +92,10 @@ signature module FullStateConfigSig { */ FlowFeature getAFeature(); - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ predicate sourceGrouping(Node source, string sourceGroup); - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ predicate sinkGrouping(Node sink, string sinkGroup); /** @@ -445,11 +446,7 @@ module Impl<FullStateConfigSig Config> { } private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } + class Ap = Unit; private class Cc = boolean; @@ -3633,7 +3630,7 @@ module Impl<FullStateConfigSig Config> { * The corresponding paths are generated from the end-points and the graph * included in the module `PathGraph`. */ - predicate hasFlowPath(PathNode source, PathNode sink) { + predicate flowPath(PathNode source, PathNode sink) { exists(PathNodeImpl flowsource, PathNodeImpl flowsink | source = flowsource and sink = flowsink | @@ -3643,6 +3640,9 @@ module Impl<FullStateConfigSig Config> { ) } + /** DEPRECATED: Use `flowPath` instead. */ + deprecated predicate hasFlowPath = flowPath/2; + private predicate flowsTo(PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink) { flowsource.isSource() and flowsource.getNodeEx().asNode() = source and @@ -3653,17 +3653,26 @@ module Impl<FullStateConfigSig Config> { /** * Holds if data can flow from `source` to `sink`. */ - predicate hasFlow(Node source, Node sink) { flowsTo(_, _, source, sink) } + predicate flow(Node source, Node sink) { flowsTo(_, _, source, sink) } + + /** DEPRECATED: Use `flow` instead. */ + deprecated predicate hasFlow = flow/2; /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + predicate flowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + + /** DEPRECATED: Use `flowTo` instead. */ + deprecated predicate hasFlowTo = flowTo/1; /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate flowToExpr(DataFlowExpr sink) { flowTo(exprNode(sink)) } + + /** DEPRECATED: Use `flowToExpr` instead. */ + deprecated predicate hasFlowToExpr = flowToExpr/1; private predicate finalStats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples @@ -4574,7 +4583,7 @@ module Impl<FullStateConfigSig Config> { * * To use this in a `path-problem` query, import the module `PartialPathGraph`. */ - predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { + predicate partialFlow(PartialPathNode source, PartialPathNode node, int dist) { partialFlow(source, node) and dist = node.getSourceDistance() } @@ -4594,7 +4603,7 @@ module Impl<FullStateConfigSig Config> { * Note that reverse flow has slightly lower precision than the corresponding * forward flow, as reverse flow disregards type pruning among other features. */ - predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { + predicate partialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { revPartialFlow(node, sink) and dist = node.getSinkDistance() } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll index e6bdc74cceb..be70086a93a 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl<Config> as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll index e6bdc74cceb..be70086a93a 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl<Config> as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll index d09fdcfca3e..e6fce328326 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll @@ -140,10 +140,8 @@ private module LambdaFlow { } pragma[nomagic] - private TReturnPositionSimple viableReturnPosLambda( - DataFlowCall call, DataFlowCallOption lastCall, ReturnKind kind - ) { - result = TReturnPositionSimple0(viableCallableLambda(call, lastCall), kind) + private TReturnPositionSimple viableReturnPosLambda(DataFlowCall call, ReturnKind kind) { + result = TReturnPositionSimple0(viableCallableLambda(call, _), kind) } private predicate viableReturnPosOutNonLambda( @@ -155,11 +153,12 @@ private module LambdaFlow { ) } + pragma[nomagic] private predicate viableReturnPosOutLambda( - DataFlowCall call, DataFlowCallOption lastCall, TReturnPositionSimple pos, OutNode out + DataFlowCall call, TReturnPositionSimple pos, OutNode out ) { exists(ReturnKind kind | - pos = viableReturnPosLambda(call, lastCall, kind) and + pos = viableReturnPosLambda(call, kind) and out = getAnOutNode(call, kind) ) } @@ -188,6 +187,7 @@ private module LambdaFlow { else any() } + pragma[assume_small_delta] pragma[nomagic] predicate revLambdaFlow0( DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn, @@ -274,6 +274,7 @@ private module LambdaFlow { ) } + pragma[assume_small_delta] pragma[nomagic] predicate revLambdaFlowOut( DataFlowCall lambdaCall, LambdaCallKind kind, TReturnPositionSimple pos, DataFlowType t, @@ -285,7 +286,7 @@ private module LambdaFlow { or // non-linear recursion revLambdaFlowOutLambdaCall(lambdaCall, kind, out, t, toJump, call, lastCall) and - viableReturnPosOutLambda(call, _, pos, out) + viableReturnPosOutLambda(call, pos, out) ) } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll index e6bdc74cceb..be70086a93a 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl<Config> as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll index e6bdc74cceb..be70086a93a 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl<Config> as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll index cfce508e706..86bc852200d 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll @@ -1,4 +1,5 @@ private import codeql.util.Boolean +private import codeql.util.Unit private import codeql.ruby.AST private import codeql.ruby.ast.internal.Synthesis private import codeql.ruby.CFG @@ -528,10 +529,7 @@ import Cached /** Holds if `n` should be hidden from path explanations. */ predicate nodeIsHidden(Node n) { exists(SsaImpl::DefinitionExt def | def = n.(SsaDefinitionExtNode).getDefinitionExt() | - def instanceof Ssa::PhiNode or - def instanceof SsaImpl::PhiReadNode or - def instanceof Ssa::CapturedEntryDefinition or - def instanceof Ssa::CapturedCallDefinition + not def instanceof Ssa::WriteDefinition ) or n = LocalFlow::getParameterDefNode(_) @@ -1333,7 +1331,15 @@ private module PostUpdateNodes { private import PostUpdateNodes /** A node that performs a type cast. */ -class CastNode extends Node instanceof ReturningNode { } +class CastNode extends Node { + CastNode() { + // ensure that actual return nodes are included in the path graph + this instanceof ReturningNode + or + // ensure that all variable assignments are included in the path graph + this.(SsaDefinitionExtNode).getDefinitionExt() instanceof Ssa::WriteDefinition + } +} class DataFlowExpr = CfgNodes::ExprCfgNode; @@ -1345,15 +1351,6 @@ int accessPathLimit() { result = 5 } */ predicate forceHighPrecision(Content c) { c instanceof Content::ElementContent } -/** The unit type. */ -private newtype TUnit = TMkUnit() - -/** The trivial type with a single element. */ -class Unit extends TUnit { - /** Gets a textual representation of this element. */ - string toString() { result = "unit" } -} - /** * Holds if the node `n` is unreachable when the call context is `call`. */ diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll index 478328d90bf..6665e0e7480 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll @@ -10,6 +10,7 @@ private import FlowSummaryImplSpecific private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommon +private import codeql.util.Unit /** Provides classes and predicates for defining flow summaries. */ module Public { @@ -109,6 +110,7 @@ module Public { } /** Gets the stack obtained by dropping the first `i` elements, if any. */ + pragma[assume_small_delta] SummaryComponentStack drop(int i) { i = 0 and result = this or diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTracking.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTracking.qll index 7f96fe5e6fb..872ac8d4cb8 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTracking.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTracking.qll @@ -33,9 +33,9 @@ private module AddTaintDefaults<DataFlowInternal::FullStateConfigSig Config> imp } /** - * Constructs a standard taint tracking computation. + * Constructs a global taint tracking computation. */ -module Make<DataFlow::ConfigSig Config> implements DataFlow::DataFlowSig { +module Global<DataFlow::ConfigSig Config> implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import DataFlowInternal::DefaultState<Config> import Config @@ -48,10 +48,15 @@ module Make<DataFlow::ConfigSig Config> implements DataFlow::DataFlowSig { import DataFlowInternal::Impl<C> } +/** DEPRECATED: Use `Global` instead. */ +deprecated module Make<DataFlow::ConfigSig Config> implements DataFlow::GlobalFlowSig { + import Global<Config> +} + /** - * Constructs a taint tracking computation using flow state. + * Constructs a global taint tracking computation using flow state. */ -module MakeWithState<DataFlow::StateConfigSig Config> implements DataFlow::DataFlowSig { +module GlobalWithState<DataFlow::StateConfigSig Config> implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import Config } @@ -62,3 +67,8 @@ module MakeWithState<DataFlow::StateConfigSig Config> implements DataFlow::DataF import DataFlowInternal::Impl<C> } + +/** DEPRECATED: Use `GlobalWithState` instead. */ +deprecated module MakeWithState<DataFlow::StateConfigSig Config> implements DataFlow::GlobalFlowSig { + import GlobalWithState<Config> +} diff --git a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll index 1b7e8cb326a..227f4ea22fb 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll @@ -63,10 +63,9 @@ * the type is not intended to match a static type. */ +private import codeql.util.Unit private import ApiGraphModelsSpecific as Specific -private class Unit = Specific::Unit; - private module API = Specific::API; private module DataFlow = Specific::DataFlow; diff --git a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsSpecific.qll b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsSpecific.qll index 500197f2f89..6627bd3faf1 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsSpecific.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsSpecific.qll @@ -20,11 +20,7 @@ */ private import codeql.ruby.AST -private import codeql.ruby.dataflow.internal.DataFlowPrivate as DataFlowPrivate private import ApiGraphModels - -class Unit = DataFlowPrivate::Unit; - // Re-export libraries needed by ApiGraphModels.qll import codeql.ruby.ApiGraphs import codeql.ruby.dataflow.internal.AccessPathSyntax as AccessPathSyntax diff --git a/ruby/ql/lib/codeql/ruby/printAst.qll b/ruby/ql/lib/codeql/ruby/printAst.qll index 25aa7908db3..c15b717610a 100644 --- a/ruby/ql/lib/codeql/ruby/printAst.qll +++ b/ruby/ql/lib/codeql/ruby/printAst.qll @@ -36,8 +36,6 @@ private predicate shouldPrintAstEdge(AstNode parent, string edgeName, AstNode ch any(PrintAstConfiguration config).shouldPrintAstEdge(parent, edgeName, child) } -private int nonSynthIndex() { result = min([-1, any(int i | exists(getSynthChild(_, i)))]) - 1 } - newtype TPrintNode = TPrintRegularAstNode(AstNode n) { shouldPrintNode(n) } or TPrintRegExpNode(RE::RegExpTerm term) { @@ -115,10 +113,23 @@ class PrintRegularAstNode extends PrintAstNode, TPrintRegularAstNode { ) } + private predicate parentIsSynthesized() { + exists(AstNode parent | + shouldPrintAstEdge(parent, _, astNode) and + parent.isSynthesized() + ) + } + private int getSynthAstNodeIndex() { - not astNode.isSynthesized() and result = nonSynthIndex() + this.parentIsSynthesized() and + exists(AstNode parent | + shouldPrintAstEdge(parent, _, astNode) and + parent.isSynthesized() and + synthChild(parent, result, astNode) + ) or - astNode = getSynthChild(astNode.getParent(), result) + not this.parentIsSynthesized() and + result = 0 } override int getOrder() { @@ -129,8 +140,8 @@ class PrintRegularAstNode extends PrintAstNode, TPrintRegularAstNode { | p order by - f.getBaseName(), f.getAbsolutePath(), l.getStartLine(), l.getStartColumn(), - l.getEndLine(), l.getEndColumn(), p.getSynthAstNodeIndex() + f.getBaseName(), f.getAbsolutePath(), l.getStartLine(), p.getSynthAstNodeIndex(), + l.getStartColumn(), l.getEndLine(), l.getEndColumn() ) } diff --git a/ruby/ql/lib/codeql/ruby/security/StoredXSSQuery.qll b/ruby/ql/lib/codeql/ruby/security/StoredXSSQuery.qll index abec1880e65..f08529988c7 100644 --- a/ruby/ql/lib/codeql/ruby/security/StoredXSSQuery.qll +++ b/ruby/ql/lib/codeql/ruby/security/StoredXSSQuery.qll @@ -56,7 +56,7 @@ module StoredXss { } } - import TaintTracking::Make<Config> + import TaintTracking::Global<Config> } /** DEPRECATED: Alias for StoredXss */ diff --git a/ruby/ql/lib/codeql/ruby/security/XSS.qll b/ruby/ql/lib/codeql/ruby/security/XSS.qll index dbed650250e..d4b99766a58 100644 --- a/ruby/ql/lib/codeql/ruby/security/XSS.qll +++ b/ruby/ql/lib/codeql/ruby/security/XSS.qll @@ -304,7 +304,7 @@ private module OrmTracking { } } - import DataFlow::Make<Config> + import DataFlow::Global<Config> } /** Provides default sources, sinks and sanitizers for detecting stored cross-site scripting (XSS) vulnerabilities. */ @@ -336,7 +336,7 @@ module StoredXss { private class OrmFieldAsSource extends Source instanceof DataFlow::CallNode { OrmFieldAsSource() { exists(DataFlow::CallNode subSrc | - OrmTracking::hasFlow(subSrc, this.getReceiver()) and + OrmTracking::flow(subSrc, this.getReceiver()) and subSrc.(OrmInstantiation).methodCallMayAccessField(this.getMethodName()) ) } diff --git a/ruby/ql/src/change-notes/2023-03-24-sensitive-get-query-problem.md b/ruby/ql/src/change-notes/2023-03-24-sensitive-get-query-problem.md new file mode 100644 index 00000000000..b6a090ffec5 --- /dev/null +++ b/ruby/ql/src/change-notes/2023-03-24-sensitive-get-query-problem.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* `rb/sensitive-get-query` no longer reports flow paths from input parameters to sensitive use nodes. This avoids cases where many flow paths could be generated for a single parameter, which caused excessive paths to be generated. diff --git a/ruby/ql/src/queries/security/cwe-079/StoredXSS.ql b/ruby/ql/src/queries/security/cwe-079/StoredXSS.ql index 1dc855230a1..da1bd427589 100644 --- a/ruby/ql/src/queries/security/cwe-079/StoredXSS.ql +++ b/ruby/ql/src/queries/security/cwe-079/StoredXSS.ql @@ -17,6 +17,6 @@ import codeql.ruby.security.StoredXSSQuery import StoredXss::PathGraph from StoredXss::PathNode source, StoredXss::PathNode sink -where StoredXss::hasFlowPath(source, sink) +where StoredXss::flowPath(source, sink) select sink.getNode(), source, sink, "Stored cross-site scripting vulnerability due to $@.", source.getNode(), "stored value" diff --git a/ruby/ql/src/queries/security/cwe-598/SensitiveGetQuery.ql b/ruby/ql/src/queries/security/cwe-598/SensitiveGetQuery.ql index ba3faf3fcae..46dbe7623e9 100644 --- a/ruby/ql/src/queries/security/cwe-598/SensitiveGetQuery.ql +++ b/ruby/ql/src/queries/security/cwe-598/SensitiveGetQuery.ql @@ -2,7 +2,7 @@ * @name Sensitive data read from GET request * @description Placing sensitive data in a GET request increases the risk of * the data being exposed to an attacker. - * @kind path-problem + * @kind problem * @problem.severity warning * @security-severity 6.5 * @precision high @@ -12,12 +12,10 @@ */ import ruby -import DataFlow::PathGraph import codeql.ruby.security.SensitiveGetQueryQuery import codeql.ruby.security.SensitiveActions -from DataFlow::PathNode source, DataFlow::PathNode sink, SensitiveGetQuery::Configuration config -where config.hasFlowPath(source, sink) -select source.getNode(), source, sink, - "$@ for GET requests uses query parameter as sensitive data.", - source.getNode().(SensitiveGetQuery::Source).getHandler(), "Route handler" +from DataFlow::Node source, DataFlow::Node sink, SensitiveGetQuery::Configuration config +where config.hasFlow(source, sink) +select source, "$@ for GET requests uses query parameter as sensitive data.", + source.(SensitiveGetQuery::Source).getHandler(), "Route handler" diff --git a/ruby/ql/test/library-tests/ast/Ast.expected b/ruby/ql/test/library-tests/ast/Ast.expected index 88129998d06..97d154c4175 100644 --- a/ruby/ql/test/library-tests/ast/Ast.expected +++ b/ruby/ql/test/library-tests/ast/Ast.expected @@ -2878,6 +2878,16 @@ operations/operations.rb: # 103| getStmt: [AssignLogicalOrExpr] ... ||= ... # 103| getAnOperand/getLeftOperand: [ConstantAssignment, ConstantReadAccess] CONSTANT4 # 103| getAnOperand/getRightOperand: [IntegerLiteral] 7 +# 104| getStmt: [AssignExpr] ... = ... +# 104| getAnOperand/getLeftOperand: [DestructuredLhsExpr] (..., ...) +# 104| getElement: [ConstantAssignment] FOO +# 104| getElement: [ConstantAssignment] BAR +# 104| getElement: [ConstantAssignment] FOO +# 104| getScopeExpr: [LocalVariableAccess] foo +# 104| getAnOperand/getRightOperand: [ArrayLiteral] [...] +# 104| getElement: [IntegerLiteral] 1 +# 104| getElement: [IntegerLiteral] 2 +# 104| getElement: [IntegerLiteral] 3 params/params.rb: # 1| [Toplevel] params.rb # 4| getStmt: [Method] identifier_method_params diff --git a/ruby/ql/test/library-tests/ast/AstDesugar.expected b/ruby/ql/test/library-tests/ast/AstDesugar.expected index 8479718819c..3625cb83574 100644 --- a/ruby/ql/test/library-tests/ast/AstDesugar.expected +++ b/ruby/ql/test/library-tests/ast/AstDesugar.expected @@ -25,28 +25,28 @@ calls/calls.rb: # 67| getReceiver: [ConstantReadAccess] X # 226| [ForExpr] for ... in ... # 226| getDesugared: [MethodCall] call to each +# 226| getReceiver: [MethodCall] call to bar +# 226| getReceiver: [SelfVariableAccess] self # 226| getBlock: [BraceBlock] { ... } # 226| getParameter: [SimpleParameter] __synth__0__1 # 226| getDefiningAccess: [LocalVariableAccess] __synth__0__1 # 226| getStmt: [AssignExpr] ... = ... -# 226| getAnOperand/getRightOperand: [LocalVariableAccess] __synth__0__1 # 226| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 226| getAnOperand/getRightOperand: [LocalVariableAccess] __synth__0__1 # 227| getStmt: [MethodCall] call to baz # 227| getReceiver: [SelfVariableAccess] self -# 226| getReceiver: [MethodCall] call to bar -# 226| getReceiver: [SelfVariableAccess] self # 229| [ForExpr] for ... in ... # 229| getDesugared: [MethodCall] call to each +# 229| getReceiver: [MethodCall] call to bar +# 229| getReceiver: [ConstantReadAccess] X # 229| getBlock: [BraceBlock] { ... } # 229| getParameter: [SimpleParameter] __synth__0__1 # 229| getDefiningAccess: [LocalVariableAccess] __synth__0__1 # 229| getStmt: [AssignExpr] ... = ... -# 229| getAnOperand/getRightOperand: [LocalVariableAccess] __synth__0__1 # 229| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 229| getAnOperand/getRightOperand: [LocalVariableAccess] __synth__0__1 # 230| getStmt: [MethodCall] call to baz # 230| getReceiver: [ConstantReadAccess] X -# 229| getReceiver: [MethodCall] call to bar -# 229| getReceiver: [ConstantReadAccess] X # 249| [HashLiteral] {...} # 249| getDesugared: [MethodCall] call to [] # 249| getReceiver: [ConstantReadAccess] Hash @@ -65,8 +65,8 @@ calls/calls.rb: # 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| getAnOperand/getRightOperand: [IntegerLiteral] 10 # 316| getStmt: [LocalVariableAccess] __synth__0 # 317| [AssignExpr] ... = ... # 317| getDesugared: [StmtSequence] ... @@ -75,50 +75,23 @@ calls/calls.rb: # 317| getReceiver: [SelfVariableAccess] self # 317| getArgument: [IntegerLiteral] 0 # 317| getArgument: [AssignExpr] ... = ... -# 317| getAnOperand/getRightOperand: [IntegerLiteral] 10 # 317| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 +# 317| getAnOperand/getRightOperand: [IntegerLiteral] 10 # 317| getStmt: [LocalVariableAccess] __synth__0 # 318| [AssignExpr] ... = ... # 318| getDesugared: [StmtSequence] ... # 318| getStmt: [AssignExpr] ... = ... -# 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: [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: [SelfVariableAccess] self +# 318| getStmt: [AssignExpr] ... = ... +# 318| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__1 +# 318| getAnOperand/getRightOperand: [SelfVariableAccess] self +# 318| getStmt: [AssignExpr] ... = ... +# 318| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__2 +# 318| getAnOperand/getRightOperand: [MethodCall] call to foo +# 318| getReceiver: [SelfVariableAccess] self +# 318| getStmt: [AssignExpr] ... = ... +# 318| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__3 # 318| getAnOperand/getRightOperand: [SplatExpr] * ... # 318| getAnOperand/getOperand/getReceiver: [ArrayLiteral] [...] # 318| getDesugared: [MethodCall] call to [] @@ -127,30 +100,50 @@ calls/calls.rb: # 318| getArgument: [IntegerLiteral] 2 # 318| getArgument: [IntegerLiteral] 3 # 318| getArgument: [IntegerLiteral] 4 +# 318| getStmt: [AssignExpr] ... = ... +# 318| getDesugared: [StmtSequence] ... +# 318| getStmt: [SetterMethodCall] call to foo= +# 318| getReceiver: [LocalVariableAccess] __synth__0 +# 318| getArgument: [AssignExpr] ... = ... +# 318| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1 +# 318| getAnOperand/getRightOperand: [MethodCall] call to [] +# 318| getReceiver: [LocalVariableAccess] __synth__3 +# 318| getArgument: [IntegerLiteral] 0 +# 318| getStmt: [LocalVariableAccess] __synth__0__1 +# 318| getAnOperand/getLeftOperand: [MethodCall] call to foo +# 318| getStmt: [AssignExpr] ... = ... +# 318| getDesugared: [StmtSequence] ... +# 318| getStmt: [SetterMethodCall] call to bar= +# 318| getReceiver: [LocalVariableAccess] __synth__1 +# 318| getArgument: [AssignExpr] ... = ... +# 318| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1 +# 318| getAnOperand/getRightOperand: [MethodCall] call to [] +# 318| getReceiver: [LocalVariableAccess] __synth__3 +# 318| getArgument: [RangeLiteral] _ .. _ +# 318| getBegin: [IntegerLiteral] 1 +# 318| getEnd: [IntegerLiteral] -2 +# 318| getStmt: [LocalVariableAccess] __synth__0__1 +# 318| getAnOperand/getLeftOperand: [MethodCall] call to bar +# 318| getStmt: [AssignExpr] ... = ... +# 318| getDesugared: [StmtSequence] ... +# 318| getStmt: [SetterMethodCall] call to []= +# 318| getReceiver: [LocalVariableAccess] __synth__2 +# 318| getArgument: [IntegerLiteral] 4 +# 318| getArgument: [AssignExpr] ... = ... +# 318| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1 +# 318| getAnOperand/getRightOperand: [MethodCall] call to [] +# 318| getReceiver: [LocalVariableAccess] __synth__3 +# 318| getArgument: [IntegerLiteral] -1 +# 318| getStmt: [LocalVariableAccess] __synth__0__1 +# 318| getAnOperand/getLeftOperand: [MethodCall] call to [] # 319| [AssignExpr] ... = ... # 319| getDesugared: [StmtSequence] ... # 319| getStmt: [AssignExpr] ... = ... -# 319| getAnOperand/getLeftOperand: [LocalVariableAccess] a -# 319| getAnOperand/getRightOperand: [MethodCall] call to [] -# 319| getReceiver: [LocalVariableAccess] __synth__0 -# 319| getArgument: [IntegerLiteral] 0 +# 319| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__1 +# 319| getAnOperand/getRightOperand: [MethodCall] call to foo +# 319| getReceiver: [SelfVariableAccess] self # 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| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__2 # 319| getAnOperand/getRightOperand: [SplatExpr] * ... # 319| getAnOperand/getOperand/getReceiver: [ArrayLiteral] [...] # 319| getDesugared: [MethodCall] call to [] @@ -158,34 +151,49 @@ calls/calls.rb: # 319| getArgument: [IntegerLiteral] 1 # 319| getArgument: [IntegerLiteral] 2 # 319| getArgument: [IntegerLiteral] 3 +# 319| getStmt: [AssignExpr] ... = ... +# 319| getAnOperand/getLeftOperand: [LocalVariableAccess] a +# 319| getAnOperand/getRightOperand: [MethodCall] call to [] +# 319| getReceiver: [LocalVariableAccess] __synth__2 +# 319| getArgument: [IntegerLiteral] 0 +# 319| getStmt: [AssignExpr] ... = ... +# 319| getDesugared: [StmtSequence] ... +# 319| getStmt: [SetterMethodCall] call to []= +# 319| getReceiver: [LocalVariableAccess] __synth__1 +# 319| getArgument: [IntegerLiteral] 5 +# 319| getArgument: [AssignExpr] ... = ... +# 319| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1 +# 319| getAnOperand/getRightOperand: [MethodCall] call to [] +# 319| getReceiver: [LocalVariableAccess] __synth__2 +# 319| getArgument: [RangeLiteral] _ .. _ +# 319| getBegin: [IntegerLiteral] 1 +# 319| getEnd: [IntegerLiteral] -1 +# 319| getStmt: [LocalVariableAccess] __synth__0__1 +# 319| getAnOperand/getLeftOperand: [MethodCall] call to [] # 320| [AssignAddExpr] ... += ... # 320| getDesugared: [StmtSequence] ... # 320| getStmt: [AssignExpr] ... = ... -# 320| getAnOperand/getRightOperand: [SelfVariableAccess] self # 320| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 -# 320| getStmt: [SetterMethodCall] call to count= -# 320| getReceiver: [LocalVariableAccess] __synth__0 -# 320| getArgument: [LocalVariableAccess] __synth__1 +# 320| getAnOperand/getRightOperand: [SelfVariableAccess] self # 320| getStmt: [AssignExpr] ... = ... # 320| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__1 # 320| getAnOperand/getRightOperand: [AddExpr] ... + ... # 320| getAnOperand/getLeftOperand/getReceiver: [MethodCall] call to count # 320| getReceiver: [LocalVariableAccess] __synth__0 # 320| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1 +# 320| getStmt: [SetterMethodCall] call to count= +# 320| getReceiver: [LocalVariableAccess] __synth__0 +# 320| getArgument: [LocalVariableAccess] __synth__1 # 320| getStmt: [LocalVariableAccess] __synth__1 # 321| [AssignAddExpr] ... += ... # 321| getDesugared: [StmtSequence] ... # 321| getStmt: [AssignExpr] ... = ... +# 321| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 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| getAnOperand/getRightOperand: [IntegerLiteral] 0 # 321| getStmt: [AssignExpr] ... = ... # 321| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__2 # 321| getAnOperand/getRightOperand: [AddExpr] ... + ... @@ -193,35 +201,33 @@ calls/calls.rb: # 321| getReceiver: [LocalVariableAccess] __synth__0 # 321| getArgument: [LocalVariableAccess] __synth__1 # 321| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1 +# 321| getStmt: [SetterMethodCall] call to []= +# 321| getReceiver: [LocalVariableAccess] __synth__0 +# 321| getArgument: [LocalVariableAccess] __synth__1 +# 321| getArgument: [LocalVariableAccess] __synth__2 # 321| getStmt: [LocalVariableAccess] __synth__2 # 322| [AssignMulExpr] ... *= ... # 322| getDesugared: [StmtSequence] ... # 322| getStmt: [AssignExpr] ... = ... +# 322| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 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| getAnOperand/getRightOperand: [IntegerLiteral] 0 # 322| getStmt: [AssignExpr] ... = ... +# 322| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__2 # 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/getLeftOperand: [LocalVariableAccess] __synth__3 # 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] ... * ... @@ -231,39 +237,15 @@ calls/calls.rb: # 322| getArgument: [LocalVariableAccess] __synth__2 # 322| getArgument: [LocalVariableAccess] __synth__3 # 322| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2 +# 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: [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 @@ -279,26 +261,59 @@ calls/calls.rb: # 342| getArgument: [IntegerLiteral] 4 # 342| getArgument: [IntegerLiteral] 5 # 342| getArgument: [IntegerLiteral] 6 +# 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__3__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__3__1 +# 342| getArgument: [IntegerLiteral] 0 +# 342| getStmt: [AssignExpr] ... = ... +# 342| getAnOperand/getLeftOperand: [LocalVariableAccess] y +# 342| getAnOperand/getRightOperand: [MethodCall] call to [] +# 342| getReceiver: [LocalVariableAccess] __synth__3__1 +# 342| getArgument: [IntegerLiteral] 1 +# 342| getStmt: [AssignExpr] ... = ... +# 342| getAnOperand/getLeftOperand: [LocalVariableAccess] z +# 342| getAnOperand/getRightOperand: [MethodCall] call to [] +# 342| getReceiver: [LocalVariableAccess] __synth__3__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 # 364| [MethodCall] call to empty? # 364| getDesugared: [StmtSequence] ... # 364| getStmt: [AssignExpr] ... = ... +# 364| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1 # 364| getAnOperand/getRightOperand: [MethodCall] call to list # 364| getReceiver: [SelfVariableAccess] self -# 364| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1 # 364| getStmt: [IfExpr] if ... +# 364| getCondition: [MethodCall] call to == +# 364| getReceiver: [NilLiteral] nil +# 364| getArgument: [LocalVariableAccess] __synth__0__1 # 364| getBranch/getThen: [NilLiteral] nil # 364| getBranch/getElse: [MethodCall] call to empty? # 364| getReceiver: [LocalVariableAccess] __synth__0__1 -# 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/getLeftOperand: [LocalVariableAccess] __synth__0__1 # 366| getAnOperand/getRightOperand: [MethodCall] call to foo # 366| getReceiver: [SelfVariableAccess] self -# 366| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1 # 366| getStmt: [IfExpr] if ... +# 366| getCondition: [MethodCall] call to == +# 366| getReceiver: [NilLiteral] nil +# 366| getArgument: [LocalVariableAccess] __synth__0__1 # 366| getBranch/getThen: [NilLiteral] nil # 366| getBranch/getElse: [MethodCall] call to bar # 366| getReceiver: [LocalVariableAccess] __synth__0__1 @@ -308,9 +323,6 @@ calls/calls.rb: # 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 [] @@ -331,10 +343,10 @@ control/cases.rb: # 160| getValue: [MethodCall] call to expr # 160| getReceiver: [SelfVariableAccess] self # 160| getBranch: [InClause] in ... then ... -# 160| getBody: [BooleanLiteral] true # 160| getPattern: [ArrayPattern] [ ..., * ] # 160| getPrefixElement: [IntegerLiteral] 1 # 160| getPrefixElement: [IntegerLiteral] 2 +# 160| getBody: [BooleanLiteral] true # 160| getBranch/getElseBranch: [StmtSequence] else ... # 160| getStmt: [BooleanLiteral] false # 162| [MatchPattern] ... => ... @@ -342,7 +354,6 @@ control/cases.rb: # 162| getValue: [MethodCall] call to expr # 162| getReceiver: [SelfVariableAccess] self # 162| getBranch: [InClause] in ... then ... -# 162| getBody: [NilLiteral] nil # 162| getPattern: [HashPattern] { ..., ** } # 162| getKey: [SymbolLiteral] :x # 162| getComponent: [StringTextComponent] x @@ -350,6 +361,7 @@ control/cases.rb: # 162| getKey: [SymbolLiteral] :y # 162| getComponent: [StringTextComponent] y # 162| getValue: [IntegerLiteral] 1 +# 162| getBody: [NilLiteral] nil constants/constants.rb: # 20| [ArrayLiteral] [...] # 20| getDesugared: [MethodCall] call to [] @@ -583,12 +595,15 @@ literals/literals.rb: control/loops.rb: # 9| [ForExpr] for ... in ... # 9| getDesugared: [MethodCall] call to each +# 9| getReceiver: [RangeLiteral] _ .. _ +# 9| getBegin: [IntegerLiteral] 1 +# 9| getEnd: [IntegerLiteral] 10 # 9| getBlock: [BraceBlock] { ... } # 9| getParameter: [SimpleParameter] __synth__0__1 # 9| getDefiningAccess: [LocalVariableAccess] __synth__0__1 # 9| getStmt: [AssignExpr] ... = ... -# 9| getAnOperand/getRightOperand: [LocalVariableAccess] __synth__0__1 # 9| getAnOperand/getLeftOperand: [LocalVariableAccess] n +# 9| getAnOperand/getRightOperand: [LocalVariableAccess] __synth__0__1 # 10| getStmt: [AssignAddExpr] ... += ... # 10| getDesugared: [AssignExpr] ... = ... # 10| getAnOperand/getLeftOperand: [LocalVariableAccess] sum @@ -598,17 +613,17 @@ control/loops.rb: # 11| getStmt: [AssignExpr] ... = ... # 11| getAnOperand/getLeftOperand: [LocalVariableAccess] foo # 11| getAnOperand/getRightOperand: [LocalVariableAccess] n -# 9| getReceiver: [RangeLiteral] _ .. _ -# 9| getBegin: [IntegerLiteral] 1 -# 9| getEnd: [IntegerLiteral] 10 # 16| [ForExpr] for ... in ... # 16| getDesugared: [MethodCall] call to each +# 16| getReceiver: [RangeLiteral] _ .. _ +# 16| getBegin: [IntegerLiteral] 1 +# 16| getEnd: [IntegerLiteral] 10 # 16| getBlock: [BraceBlock] { ... } # 16| getParameter: [SimpleParameter] __synth__0__1 # 16| getDefiningAccess: [LocalVariableAccess] __synth__0__1 # 16| getStmt: [AssignExpr] ... = ... -# 16| getAnOperand/getRightOperand: [LocalVariableAccess] __synth__0__1 # 16| getAnOperand/getLeftOperand: [LocalVariableAccess] n +# 16| getAnOperand/getRightOperand: [LocalVariableAccess] __synth__0__1 # 17| getStmt: [AssignAddExpr] ... += ... # 17| getDesugared: [AssignExpr] ... = ... # 17| getAnOperand/getLeftOperand: [LocalVariableAccess] sum @@ -621,29 +636,37 @@ control/loops.rb: # 18| getAnOperand/getRightOperand: [SubExpr] ... - ... # 18| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] foo # 18| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] n -# 16| getReceiver: [RangeLiteral] _ .. _ -# 16| getBegin: [IntegerLiteral] 1 -# 16| getEnd: [IntegerLiteral] 10 # 22| [ForExpr] for ... in ... # 22| getDesugared: [MethodCall] call to each +# 22| getReceiver: [HashLiteral] {...} +# 22| getDesugared: [MethodCall] call to [] +# 22| getReceiver: [ConstantReadAccess] Hash +# 22| getArgument: [Pair] Pair +# 22| getKey: [SymbolLiteral] :foo +# 22| getComponent: [StringTextComponent] foo +# 22| getValue: [IntegerLiteral] 0 +# 22| getArgument: [Pair] Pair +# 22| getKey: [SymbolLiteral] :bar +# 22| getComponent: [StringTextComponent] bar +# 22| getValue: [IntegerLiteral] 1 # 22| getBlock: [BraceBlock] { ... } # 22| getParameter: [SimpleParameter] __synth__0__1 # 22| getDefiningAccess: [LocalVariableAccess] __synth__0__1 # 22| getStmt: [AssignExpr] ... = ... # 22| getDesugared: [StmtSequence] ... # 22| getStmt: [AssignExpr] ... = ... -# 22| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1 +# 22| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__2__1 # 22| getAnOperand/getRightOperand: [SplatExpr] * ... # 22| getAnOperand/getOperand/getReceiver: [LocalVariableAccess] __synth__0__1 # 22| getStmt: [AssignExpr] ... = ... # 22| getAnOperand/getLeftOperand: [LocalVariableAccess] key # 22| getAnOperand/getRightOperand: [MethodCall] call to [] -# 22| getReceiver: [LocalVariableAccess] __synth__0__1 +# 22| getReceiver: [LocalVariableAccess] __synth__2__1 # 22| getArgument: [IntegerLiteral] 0 # 22| getStmt: [AssignExpr] ... = ... # 22| getAnOperand/getLeftOperand: [LocalVariableAccess] value # 22| getAnOperand/getRightOperand: [MethodCall] call to [] -# 22| getReceiver: [LocalVariableAccess] __synth__0__1 +# 22| getReceiver: [LocalVariableAccess] __synth__2__1 # 22| getArgument: [IntegerLiteral] 1 # 22| getAnOperand/getLeftOperand: [DestructuredLhsExpr] (..., ...) # 23| getStmt: [AssignAddExpr] ... += ... @@ -658,37 +681,37 @@ control/loops.rb: # 24| getAnOperand/getRightOperand: [MulExpr] ... * ... # 24| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] foo # 24| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] value -# 22| getReceiver: [HashLiteral] {...} -# 22| getDesugared: [MethodCall] call to [] -# 22| getReceiver: [ConstantReadAccess] Hash -# 22| getArgument: [Pair] Pair -# 22| getKey: [SymbolLiteral] :foo -# 22| getComponent: [StringTextComponent] foo -# 22| getValue: [IntegerLiteral] 0 -# 22| getArgument: [Pair] Pair -# 22| getKey: [SymbolLiteral] :bar -# 22| getComponent: [StringTextComponent] bar -# 22| getValue: [IntegerLiteral] 1 # 28| [ForExpr] for ... in ... # 28| getDesugared: [MethodCall] call to each +# 28| getReceiver: [HashLiteral] {...} +# 28| getDesugared: [MethodCall] call to [] +# 28| getReceiver: [ConstantReadAccess] Hash +# 28| getArgument: [Pair] Pair +# 28| getKey: [SymbolLiteral] :foo +# 28| getComponent: [StringTextComponent] foo +# 28| getValue: [IntegerLiteral] 0 +# 28| getArgument: [Pair] Pair +# 28| getKey: [SymbolLiteral] :bar +# 28| getComponent: [StringTextComponent] bar +# 28| getValue: [IntegerLiteral] 1 # 28| getBlock: [BraceBlock] { ... } # 28| getParameter: [SimpleParameter] __synth__0__1 # 28| getDefiningAccess: [LocalVariableAccess] __synth__0__1 # 28| getStmt: [AssignExpr] ... = ... # 28| getDesugared: [StmtSequence] ... # 28| getStmt: [AssignExpr] ... = ... -# 28| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0__1 +# 28| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__2__1 # 28| getAnOperand/getRightOperand: [SplatExpr] * ... # 28| getAnOperand/getOperand/getReceiver: [LocalVariableAccess] __synth__0__1 # 28| getStmt: [AssignExpr] ... = ... # 28| getAnOperand/getLeftOperand: [LocalVariableAccess] key # 28| getAnOperand/getRightOperand: [MethodCall] call to [] -# 28| getReceiver: [LocalVariableAccess] __synth__0__1 +# 28| getReceiver: [LocalVariableAccess] __synth__2__1 # 28| getArgument: [IntegerLiteral] 0 # 28| getStmt: [AssignExpr] ... = ... # 28| getAnOperand/getLeftOperand: [LocalVariableAccess] value # 28| getAnOperand/getRightOperand: [MethodCall] call to [] -# 28| getReceiver: [LocalVariableAccess] __synth__0__1 +# 28| getReceiver: [LocalVariableAccess] __synth__2__1 # 28| getArgument: [IntegerLiteral] 1 # 28| getAnOperand/getLeftOperand: [DestructuredLhsExpr] (..., ...) # 29| getStmt: [AssignAddExpr] ... += ... @@ -704,17 +727,6 @@ control/loops.rb: # 30| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] foo # 30| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] value # 31| getStmt: [BreakStmt] break -# 28| getReceiver: [HashLiteral] {...} -# 28| getDesugared: [MethodCall] call to [] -# 28| getReceiver: [ConstantReadAccess] Hash -# 28| getArgument: [Pair] Pair -# 28| getKey: [SymbolLiteral] :foo -# 28| getComponent: [StringTextComponent] foo -# 28| getValue: [IntegerLiteral] 0 -# 28| getArgument: [Pair] Pair -# 28| getKey: [SymbolLiteral] :bar -# 28| getComponent: [StringTextComponent] bar -# 28| getValue: [IntegerLiteral] 1 # 36| [AssignAddExpr] ... += ... # 36| getDesugared: [AssignExpr] ... = ... # 36| getAnOperand/getLeftOperand: [LocalVariableAccess] x @@ -904,8 +916,8 @@ operations/operations.rb: # 101| [AssignLogicalOrExpr] ... ||= ... # 101| getDesugared: [StmtSequence] ... # 101| getStmt: [AssignExpr] ... = ... -# 101| getAnOperand/getRightOperand: [ConstantReadAccess] Foo # 101| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 +# 101| getAnOperand/getRightOperand: [ConstantReadAccess] Foo # 101| getStmt: [AssignExpr] ... = ... # 101| getAnOperand/getLeftOperand: [ConstantAssignment] MemberConstant # 101| getScopeExpr: [LocalVariableAccess] __synth__0 @@ -916,11 +928,11 @@ operations/operations.rb: # 102| [AssignLogicalOrExpr] ... ||= ... # 102| getDesugared: [StmtSequence] ... # 102| getStmt: [AssignExpr] ... = ... +# 102| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 102| getAnOperand/getRightOperand: [MethodCall] call to bar # 102| getReceiver: [MethodCall] call to foo # 102| getReceiver: [SelfVariableAccess] self # 102| getArgument: [IntegerLiteral] 1 -# 102| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 102| getStmt: [AssignExpr] ... = ... # 102| getAnOperand/getLeftOperand: [ConstantAssignment] OtherConstant # 102| getScopeExpr: [LocalVariableAccess] __synth__0 @@ -934,6 +946,36 @@ operations/operations.rb: # 103| getAnOperand/getRightOperand: [LogicalOrExpr] ... || ... # 103| getAnOperand/getLeftOperand/getReceiver: [ConstantReadAccess] CONSTANT4 # 103| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 7 +# 104| [AssignExpr] ... = ... +# 104| getDesugared: [StmtSequence] ... +# 104| getStmt: [AssignExpr] ... = ... +# 104| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__2 +# 104| getAnOperand/getRightOperand: [LocalVariableAccess] foo +# 104| getStmt: [AssignExpr] ... = ... +# 104| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__3 +# 104| getAnOperand/getRightOperand: [SplatExpr] * ... +# 104| getAnOperand/getOperand/getReceiver: [ArrayLiteral] [...] +# 104| getDesugared: [MethodCall] call to [] +# 104| getReceiver: [ConstantReadAccess] Array +# 104| getArgument: [IntegerLiteral] 1 +# 104| getArgument: [IntegerLiteral] 2 +# 104| getArgument: [IntegerLiteral] 3 +# 104| getStmt: [AssignExpr] ... = ... +# 104| getAnOperand/getLeftOperand: [ConstantAssignment] FOO +# 104| getAnOperand/getRightOperand: [MethodCall] call to [] +# 104| getReceiver: [LocalVariableAccess] __synth__3 +# 104| getArgument: [IntegerLiteral] 0 +# 104| getStmt: [AssignExpr] ... = ... +# 104| getAnOperand/getLeftOperand: [ConstantAssignment] BAR +# 104| getAnOperand/getRightOperand: [MethodCall] call to [] +# 104| getReceiver: [LocalVariableAccess] __synth__3 +# 104| getArgument: [IntegerLiteral] 1 +# 104| getStmt: [AssignExpr] ... = ... +# 104| getAnOperand/getLeftOperand: [ConstantAssignment] FOO +# 104| getScopeExpr: [LocalVariableAccess] __synth__2 +# 104| getAnOperand/getRightOperand: [MethodCall] call to [] +# 104| getReceiver: [LocalVariableAccess] __synth__3 +# 104| getArgument: [IntegerLiteral] 2 params/params.rb: # 8| [HashLiteral] {...} # 8| getDesugared: [MethodCall] call to [] @@ -944,19 +986,6 @@ params/params.rb: erb/template.html.erb: # 27| [ForExpr] for ... in ... # 27| getDesugared: [MethodCall] call to each -# 27| getBlock: [BraceBlock] { ... } -# 27| getParameter: [SimpleParameter] __synth__0__1 -# 27| getDefiningAccess: [LocalVariableAccess] __synth__0__1 -# 27| getStmt: [AssignExpr] ... = ... -# 27| getAnOperand/getRightOperand: [LocalVariableAccess] __synth__0__1 -# 27| getAnOperand/getLeftOperand: [LocalVariableAccess] x -# 28| getStmt: [AssignAddExpr] ... += ... -# 28| getDesugared: [AssignExpr] ... = ... -# 28| getAnOperand/getLeftOperand: [LocalVariableAccess] xs -# 28| getAnOperand/getRightOperand: [AddExpr] ... + ... -# 28| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] xs -# 28| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] x -# 29| getStmt: [LocalVariableAccess] xs # 27| getReceiver: [ArrayLiteral] [...] # 27| getDesugared: [MethodCall] call to [] # 27| getReceiver: [ConstantReadAccess] Array @@ -966,82 +995,95 @@ erb/template.html.erb: # 27| getComponent: [StringTextComponent] bar # 27| getArgument: [StringLiteral] "baz" # 27| getComponent: [StringTextComponent] baz +# 27| getBlock: [BraceBlock] { ... } +# 27| getParameter: [SimpleParameter] __synth__0__1 +# 27| getDefiningAccess: [LocalVariableAccess] __synth__0__1 +# 27| getStmt: [AssignExpr] ... = ... +# 27| getAnOperand/getLeftOperand: [LocalVariableAccess] x +# 27| getAnOperand/getRightOperand: [LocalVariableAccess] __synth__0__1 +# 28| getStmt: [AssignAddExpr] ... += ... +# 28| getDesugared: [AssignExpr] ... = ... +# 28| getAnOperand/getLeftOperand: [LocalVariableAccess] xs +# 28| getAnOperand/getRightOperand: [AddExpr] ... + ... +# 28| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] xs +# 28| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] x +# 29| getStmt: [LocalVariableAccess] xs gems/test.gemspec: # 2| [AssignExpr] ... = ... # 2| getDesugared: [StmtSequence] ... # 2| getStmt: [SetterMethodCall] call to name= # 2| getReceiver: [LocalVariableAccess] s # 2| getArgument: [AssignExpr] ... = ... +# 2| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 2| getAnOperand/getRightOperand: [StringLiteral] "test" # 2| getComponent: [StringTextComponent] test -# 2| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 2| getStmt: [LocalVariableAccess] __synth__0 # 3| [AssignExpr] ... = ... # 3| getDesugared: [StmtSequence] ... # 3| getStmt: [SetterMethodCall] call to version= # 3| getReceiver: [LocalVariableAccess] s # 3| getArgument: [AssignExpr] ... = ... +# 3| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 3| getAnOperand/getRightOperand: [StringLiteral] "0.0.0" # 3| getComponent: [StringTextComponent] 0.0.0 -# 3| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 3| getStmt: [LocalVariableAccess] __synth__0 # 4| [AssignExpr] ... = ... # 4| getDesugared: [StmtSequence] ... # 4| getStmt: [SetterMethodCall] call to summary= # 4| getReceiver: [LocalVariableAccess] s # 4| getArgument: [AssignExpr] ... = ... +# 4| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 4| getAnOperand/getRightOperand: [StringLiteral] "foo!" # 4| getComponent: [StringTextComponent] foo! -# 4| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 4| getStmt: [LocalVariableAccess] __synth__0 # 5| [AssignExpr] ... = ... # 5| getDesugared: [StmtSequence] ... # 5| getStmt: [SetterMethodCall] call to description= # 5| getReceiver: [LocalVariableAccess] s # 5| getArgument: [AssignExpr] ... = ... +# 5| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 5| getAnOperand/getRightOperand: [StringLiteral] "A test" # 5| getComponent: [StringTextComponent] A test -# 5| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 5| getStmt: [LocalVariableAccess] __synth__0 # 6| [AssignExpr] ... = ... # 6| getDesugared: [StmtSequence] ... # 6| getStmt: [SetterMethodCall] call to authors= # 6| getReceiver: [LocalVariableAccess] s # 6| getArgument: [AssignExpr] ... = ... +# 6| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 6| getAnOperand/getRightOperand: [ArrayLiteral] [...] # 6| getDesugared: [MethodCall] call to [] # 6| getReceiver: [ConstantReadAccess] Array # 6| getArgument: [StringLiteral] "Mona Lisa" # 6| getComponent: [StringTextComponent] Mona Lisa -# 6| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 6| getStmt: [LocalVariableAccess] __synth__0 # 7| [AssignExpr] ... = ... # 7| getDesugared: [StmtSequence] ... # 7| getStmt: [SetterMethodCall] call to email= # 7| getReceiver: [LocalVariableAccess] s # 7| getArgument: [AssignExpr] ... = ... +# 7| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 7| getAnOperand/getRightOperand: [StringLiteral] "mona@example.com" # 7| getComponent: [StringTextComponent] mona@example.com -# 7| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 7| getStmt: [LocalVariableAccess] __synth__0 # 8| [AssignExpr] ... = ... # 8| getDesugared: [StmtSequence] ... # 8| getStmt: [SetterMethodCall] call to files= # 8| getReceiver: [LocalVariableAccess] s # 8| getArgument: [AssignExpr] ... = ... +# 8| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 8| getAnOperand/getRightOperand: [ArrayLiteral] [...] # 8| getDesugared: [MethodCall] call to [] # 8| getReceiver: [ConstantReadAccess] Array # 8| getArgument: [StringLiteral] "lib/test.rb" # 8| getComponent: [StringTextComponent] lib/test.rb -# 8| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 8| getStmt: [LocalVariableAccess] __synth__0 # 9| [AssignExpr] ... = ... # 9| getDesugared: [StmtSequence] ... # 9| getStmt: [SetterMethodCall] call to homepage= # 9| getReceiver: [LocalVariableAccess] s # 9| getArgument: [AssignExpr] ... = ... +# 9| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 9| getAnOperand/getRightOperand: [StringLiteral] "https://github.com/github/cod..." # 9| getComponent: [StringTextComponent] https://github.com/github/codeql-ruby -# 9| getAnOperand/getLeftOperand: [LocalVariableAccess] __synth__0 # 9| getStmt: [LocalVariableAccess] __synth__0 diff --git a/ruby/ql/test/library-tests/ast/TreeSitter.expected b/ruby/ql/test/library-tests/ast/TreeSitter.expected index e8cf91b46e3..d62d635b0b3 100644 --- a/ruby/ql/test/library-tests/ast/TreeSitter.expected +++ b/ruby/ql/test/library-tests/ast/TreeSitter.expected @@ -5615,6 +5615,27 @@ operations/operations.rb: # 103| 1: [Constant] CONSTANT4 # 103| 1: [ReservedWord] ||= # 103| 2: [Integer] 7 +# 104| 72: [Assignment] Assignment +# 104| 0: [LeftAssignmentList] LeftAssignmentList +# 104| 0: [Constant] FOO +# 104| 1: [ReservedWord] , +# 104| 2: [ScopeResolution] ScopeResolution +# 104| 0: [ReservedWord] :: +# 104| 1: [Constant] BAR +# 104| 3: [ReservedWord] , +# 104| 4: [ScopeResolution] ScopeResolution +# 104| 0: [Identifier] foo +# 104| 1: [ReservedWord] :: +# 104| 2: [Constant] FOO +# 104| 1: [ReservedWord] = +# 104| 2: [Array] Array +# 104| 0: [ReservedWord] [ +# 104| 1: [Integer] 1 +# 104| 2: [ReservedWord] , +# 104| 3: [Integer] 2 +# 104| 4: [ReservedWord] , +# 104| 5: [Integer] 3 +# 104| 6: [ReservedWord] ] # 1| [Comment] # Start with assignments to all the identifiers used below, so that they are # 2| [Comment] # interpreted as variables. # 22| [Comment] # Unary operations diff --git a/ruby/ql/test/library-tests/ast/ValueText.expected b/ruby/ql/test/library-tests/ast/ValueText.expected index 3c9254d284a..612b58e41e3 100644 --- a/ruby/ql/test/library-tests/ast/ValueText.expected +++ b/ruby/ql/test/library-tests/ast/ValueText.expected @@ -903,6 +903,12 @@ exprValue | operations/operations.rb:102:5:102:5 | 1 | 1 | int | | operations/operations.rb:102:31:102:31 | 7 | 7 | int | | operations/operations.rb:103:17:103:17 | 7 | 7 | int | +| operations/operations.rb:104:1:104:3 | 0 | 0 | int | +| operations/operations.rb:104:6:104:10 | 1 | 1 | int | +| operations/operations.rb:104:13:104:20 | 2 | 2 | int | +| operations/operations.rb:104:25:104:25 | 1 | 1 | int | +| operations/operations.rb:104:28:104:28 | 2 | 2 | int | +| operations/operations.rb:104:31:104:31 | 3 | 3 | int | | params/params.rb:41:46:41:46 | 7 | 7 | int | | params/params.rb:47:19:47:21 | :bar | :bar | symbol | | params/params.rb:47:24:47:24 | 2 | 2 | int | @@ -1792,6 +1798,12 @@ exprCfgNodeValue | operations/operations.rb:102:5:102:5 | 1 | 1 | int | | operations/operations.rb:102:31:102:31 | 7 | 7 | int | | operations/operations.rb:103:17:103:17 | 7 | 7 | int | +| operations/operations.rb:104:1:104:3 | 0 | 0 | int | +| operations/operations.rb:104:6:104:10 | 1 | 1 | int | +| operations/operations.rb:104:13:104:20 | 2 | 2 | int | +| operations/operations.rb:104:25:104:25 | 1 | 1 | int | +| operations/operations.rb:104:28:104:28 | 2 | 2 | int | +| operations/operations.rb:104:31:104:31 | 3 | 3 | int | | params/params.rb:41:46:41:46 | 7 | 7 | int | | params/params.rb:47:19:47:21 | :bar | :bar | symbol | | params/params.rb:47:24:47:24 | 2 | 2 | int | diff --git a/ruby/ql/test/library-tests/ast/calls/calls.expected b/ruby/ql/test/library-tests/ast/calls/calls.expected index a5d0fe1d272..628b3578994 100644 --- a/ruby/ql/test/library-tests/ast/calls/calls.expected +++ b/ruby/ql/test/library-tests/ast/calls/calls.expected @@ -61,6 +61,7 @@ callsWithArguments | 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 []= | []= | 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 | @@ -70,17 +71,18 @@ callsWithArguments | 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 []= | []= | 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:1:320:10 | call to count= | count= | 0 | calls.rb:320:1:320:10 | __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:1:321:6 | call to []= | []= | 1 | calls.rb:321:1:321:6 | __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 | @@ -91,7 +93,7 @@ callsWithArguments | 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:1:322:32 | call to []= | []= | 3 | calls.rb:322:1:322:32 | __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" | @@ -321,23 +323,27 @@ callsWithReceiver | 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 [] | calls.rb:318:1:318:8 | __synth__3 | | 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:1:318:8 | call to foo | calls.rb:318:1:318:8 | __synth__0 | +| calls.rb:318:1:318:8 | call to foo= | calls.rb:318:1:318:8 | __synth__0 | +| calls.rb:318:12:318:19 | call to [] | calls.rb:318:12:318:19 | __synth__3 | | 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:12:318:19 | call to bar | calls.rb:318:12:318:19 | __synth__1 | +| calls.rb:318:12:318:19 | call to bar= | calls.rb:318:12:318:19 | __synth__1 | | 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:22:318:27 | call to [] | calls.rb:318:22:318:27 | __synth__2 | +| calls.rb:318:22:318:27 | call to [] | calls.rb:318:22:318:27 | __synth__3 | +| calls.rb:318:22:318:27 | call to []= | calls.rb:318:22:318:27 | __synth__2 | | 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:1:319:1 | call to [] | calls.rb:319:1:319:1 | __synth__2 | | 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:5:319:10 | call to [] | calls.rb:319:5:319:10 | __synth__1 | +| calls.rb:319:5:319:10 | call to [] | calls.rb:319:5:319:10 | __synth__2 | +| calls.rb:319:5:319:10 | call to []= | calls.rb:319:5:319:10 | __synth__1 | | 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 | @@ -370,9 +376,9 @@ callsWithReceiver | 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:5:342:5 | call to [] | calls.rb:342:5:342:5 | __synth__3__1 | +| calls.rb:342:8:342:8 | call to [] | calls.rb:342:8:342:8 | __synth__3__1 | +| calls.rb:342:11:342:11 | call to [] | calls.rb:342:11:342:11 | __synth__3__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 | diff --git a/ruby/ql/test/library-tests/ast/operations/assignment.expected b/ruby/ql/test/library-tests/ast/operations/assignment.expected index ef88dc1751a..5349ebf5cef 100644 --- a/ruby/ql/test/library-tests/ast/operations/assignment.expected +++ b/ruby/ql/test/library-tests/ast/operations/assignment.expected @@ -65,6 +65,12 @@ assignments | operations.rb:102:1:102:31 | ... \|\|= ... | \|\|= | operations.rb:102:1:102:25 | OtherConstant | operations.rb:102:31:102:31 | 7 | AssignLogicalOrExpr | | operations.rb:103:1:103:17 | ... = ... | = | operations.rb:103:1:103:11 | CONSTANT4 | operations.rb:103:13:103:15 | ... \|\| ... | AssignExpr | | operations.rb:103:1:103:17 | ... \|\|= ... | \|\|= | operations.rb:103:1:103:11 | CONSTANT4 | operations.rb:103:17:103:17 | 7 | AssignLogicalOrExpr | +| operations.rb:104:1:104:3 | ... = ... | = | operations.rb:104:1:104:3 | FOO | operations.rb:104:1:104:3 | call to [] | AssignExpr | +| operations.rb:104:1:104:32 | ... = ... | = | operations.rb:104:1:104:20 | (..., ...) | operations.rb:104:24:104:32 | [...] | AssignExpr | +| operations.rb:104:6:104:10 | ... = ... | = | operations.rb:104:6:104:10 | BAR | operations.rb:104:6:104:10 | call to [] | AssignExpr | +| operations.rb:104:13:104:15 | ... = ... | = | operations.rb:104:13:104:15 | __synth__2 | operations.rb:104:13:104:15 | foo | AssignExpr | +| operations.rb:104:13:104:20 | ... = ... | = | operations.rb:104:13:104:20 | FOO | operations.rb:104:13:104:20 | call to [] | AssignExpr | +| operations.rb:104:24:104:32 | ... = ... | = | operations.rb:104:24:104:32 | __synth__3 | operations.rb:104:24:104:32 | * ... | AssignExpr | assignOperations | operations.rb:69:1:69:8 | ... += ... | += | operations.rb:69:1:69:1 | x | operations.rb:69:6:69:8 | 128 | AssignAddExpr | | operations.rb:70:1:70:7 | ... -= ... | -= | operations.rb:70:1:70:1 | y | operations.rb:70:6:70:7 | 32 | AssignSubExpr | diff --git a/ruby/ql/test/library-tests/ast/operations/operation.expected b/ruby/ql/test/library-tests/ast/operations/operation.expected index 0f74eb28fb3..91e76d7c366 100644 --- a/ruby/ql/test/library-tests/ast/operations/operation.expected +++ b/ruby/ql/test/library-tests/ast/operations/operation.expected @@ -230,3 +230,16 @@ | operations.rb:103:1:103:17 | ... \|\|= ... | \|\|= | operations.rb:103:17:103:17 | 7 | AssignLogicalOrExpr | | operations.rb:103:13:103:15 | ... \|\| ... | \|\| | operations.rb:103:1:103:11 | CONSTANT4 | LogicalOrExpr | | operations.rb:103:13:103:15 | ... \|\| ... | \|\| | operations.rb:103:17:103:17 | 7 | LogicalOrExpr | +| operations.rb:104:1:104:3 | ... = ... | = | operations.rb:104:1:104:3 | FOO | AssignExpr | +| operations.rb:104:1:104:3 | ... = ... | = | operations.rb:104:1:104:3 | call to [] | AssignExpr | +| operations.rb:104:1:104:32 | ... = ... | = | operations.rb:104:1:104:20 | (..., ...) | AssignExpr | +| operations.rb:104:1:104:32 | ... = ... | = | operations.rb:104:24:104:32 | [...] | AssignExpr | +| operations.rb:104:6:104:10 | ... = ... | = | operations.rb:104:6:104:10 | BAR | AssignExpr | +| operations.rb:104:6:104:10 | ... = ... | = | operations.rb:104:6:104:10 | call to [] | AssignExpr | +| operations.rb:104:13:104:15 | ... = ... | = | operations.rb:104:13:104:15 | __synth__2 | AssignExpr | +| operations.rb:104:13:104:15 | ... = ... | = | operations.rb:104:13:104:15 | foo | AssignExpr | +| operations.rb:104:13:104:20 | ... = ... | = | operations.rb:104:13:104:20 | FOO | AssignExpr | +| operations.rb:104:13:104:20 | ... = ... | = | operations.rb:104:13:104:20 | call to [] | AssignExpr | +| operations.rb:104:24:104:32 | * ... | * | operations.rb:104:24:104:32 | [...] | SplatExpr | +| operations.rb:104:24:104:32 | ... = ... | = | operations.rb:104:24:104:32 | * ... | AssignExpr | +| operations.rb:104:24:104:32 | ... = ... | = | operations.rb:104:24:104:32 | __synth__3 | AssignExpr | diff --git a/ruby/ql/test/library-tests/ast/operations/operations.rb b/ruby/ql/test/library-tests/ast/operations/operations.rb index 86fda3c7457..14fad78bbe3 100644 --- a/ruby/ql/test/library-tests/ast/operations/operations.rb +++ b/ruby/ql/test/library-tests/ast/operations/operations.rb @@ -101,3 +101,4 @@ CONSTANT3 ||= 7 Foo::MemberConstant ||= 8 foo(1).bar::OtherConstant ||= 7 ::CONSTANT4 ||= 7 +FOO, ::BAR, foo::FOO = [1, 2, 3] diff --git a/ruby/ql/test/library-tests/ast/operations/unary.expected b/ruby/ql/test/library-tests/ast/operations/unary.expected index 0190e9bcf56..43c23fff031 100644 --- a/ruby/ql/test/library-tests/ast/operations/unary.expected +++ b/ruby/ql/test/library-tests/ast/operations/unary.expected @@ -7,6 +7,7 @@ unaryOperations | operations.rb:28:1:28:12 | defined? ... | defined? | operations.rb:28:10:28:12 | foo | DefinedExpr | | operations.rb:29:20:29:23 | * ... | * | operations.rb:29:21:29:23 | [...] | SplatExpr | | operations.rb:29:31:29:42 | ** ... | ** | operations.rb:29:33:29:42 | {...} | HashSplatExpr | +| operations.rb:104:24:104:32 | * ... | * | operations.rb:104:24:104:32 | [...] | SplatExpr | unaryLogicalOperations | operations.rb:23:1:23:2 | ! ... | ! | operations.rb:23:2:23:2 | a | NotExpr | | operations.rb:24:1:24:5 | not ... | not | operations.rb:24:5:24:5 | b | NotExpr | diff --git a/ruby/ql/test/library-tests/controlflow/graph/Cfg.expected b/ruby/ql/test/library-tests/controlflow/graph/Cfg.expected index bb43be4a082..071f118db84 100644 --- a/ruby/ql/test/library-tests/controlflow/graph/Cfg.expected +++ b/ruby/ql/test/library-tests/controlflow/graph/Cfg.expected @@ -2083,7 +2083,7 @@ cfg.rb: #-----| -> constant # 61| ... = ... -#-----| -> __synth__0 +#-----| -> __synth__2 # 61| "constant" #-----| -> ... = ... @@ -2095,19 +2095,19 @@ cfg.rb: #-----| -> pattern # 62| ... = ... -#-----| -> __synth__0__1 +#-----| -> __synth__2__1 # 62| 0 #-----| -> call to [] -# 62| __synth__0 +# 62| __synth__2 #-----| -> 0 # 62| call to [] #-----| -> ... = ... # 62| x -#-----| -> __synth__0 +#-----| -> __synth__2 # 62| * ... #-----| -> ... = ... @@ -2121,11 +2121,11 @@ cfg.rb: # 62| 1 #-----| -> call to [] -# 62| __synth__0 +# 62| __synth__2 #-----| -> 1 -# 62| __synth__0__1 -#-----| -> __synth__0 +# 62| __synth__2__1 +#-----| -> __synth__2 # 62| call to [] #-----| -> * ... @@ -2136,14 +2136,14 @@ cfg.rb: # 62| 0 #-----| -> call to [] -# 62| __synth__0__1 +# 62| __synth__2__1 #-----| -> 0 # 62| call to [] #-----| -> ... = ... # 62| y -#-----| -> __synth__0__1 +#-----| -> __synth__2__1 # 62| ... = ... #-----| -> ... @@ -2151,14 +2151,14 @@ cfg.rb: # 62| 1 #-----| -> call to [] -# 62| __synth__0__1 +# 62| __synth__2__1 #-----| -> 1 # 62| call to [] #-----| -> ... = ... # 62| z -#-----| -> __synth__0__1 +#-----| -> __synth__2__1 # 62| * ... #-----| -> ... = ... @@ -2169,7 +2169,7 @@ cfg.rb: # 62| Array #-----| -> 1 -# 62| __synth__0 +# 62| __synth__2 #-----| -> Array # 62| call to [] @@ -2918,7 +2918,7 @@ cfg.rb: #-----| raise -> self # 136| ... rescue ... -#-----| -> __synth__0 +#-----| -> __synth__2 # 136| 0 #-----| -> ... / ... @@ -2950,14 +2950,14 @@ cfg.rb: # 138| _ .. _ #-----| -> call to [] -# 138| __synth__0 +# 138| __synth__2 #-----| -> 0 # 138| call to [] #-----| -> ... = ... # 138| init -#-----| -> __synth__0 +#-----| -> __synth__2 # 138| -1 #-----| -> call to [] @@ -2965,14 +2965,14 @@ cfg.rb: # 138| ... = ... #-----| -> ... -# 138| __synth__0 +# 138| __synth__2 #-----| -> -1 # 138| call to [] #-----| -> ... = ... # 138| last -#-----| -> __synth__0 +#-----| -> __synth__2 # 138| 1 #-----| -> 2 @@ -2986,7 +2986,7 @@ cfg.rb: # 138| ..., ... #-----| -> * ... -# 138| __synth__0 +# 138| __synth__2 #-----| -> 1 # 138| 2 @@ -4004,6 +4004,9 @@ desugar.rb: # 14| call to foo #-----| -> ... = ... +# 14| __synth__1 +#-----| -> call to count= + # 14| call to count #-----| -> 1 @@ -4025,9 +4028,6 @@ desugar.rb: # 14| __synth__1 #-----| -> __synth__0 -# 14| __synth__1 -#-----| -> call to count= - # 14| 1 #-----| -> ... + ... @@ -4066,6 +4066,9 @@ desugar.rb: # 18| call to foo #-----| -> ... = ... +# 18| __synth__4 +#-----| -> call to []= + # 18| call to [] #-----| -> 1 @@ -4144,14 +4147,11 @@ desugar.rb: # 18| __synth__4 #-----| -> __synth__0 -# 18| __synth__4 -#-----| -> call to []= - # 18| 1 #-----| -> ... + ... # 21| enter m6 -#-----| -> __synth__0 +#-----| -> __synth__2 # 21| exit m6 @@ -4167,14 +4167,14 @@ desugar.rb: # 22| 0 #-----| -> call to [] -# 22| __synth__0 +# 22| __synth__3 #-----| -> 0 # 22| call to [] #-----| -> ... = ... # 22| x -#-----| -> __synth__0 +#-----| -> __synth__3 # 22| ... #-----| -> exit m6 (normal) @@ -4183,7 +4183,7 @@ desugar.rb: #-----| -> _ .. _ # 22| ... = ... -#-----| -> self +#-----| -> __synth__2 # 22| 1 #-----| -> -2 @@ -4191,17 +4191,23 @@ desugar.rb: # 22| _ .. _ #-----| -> call to [] -# 22| __synth__0 +# 22| __synth__3 #-----| -> 1 # 22| call to [] #-----| -> ... = ... # 22| y -#-----| -> __synth__0 +#-----| -> __synth__3 + +# 22| ... = ... +#-----| -> __synth__3 + +# 22| __synth__2 +#-----| -> self # 22| call to z -#-----| -> __synth__0__1 +#-----| -> ... = ... # 22| self #-----| -> call to z @@ -4215,14 +4221,17 @@ desugar.rb: # 22| ... = ... #-----| -> call to bar= -# 22| __synth__0 -#-----| -> -1 - # 22| __synth__0__1 #-----| -> ... # 22| __synth__0__1 -#-----| -> __synth__0 +#-----| -> __synth__3 + +# 22| __synth__2 +#-----| -> __synth__0__1 + +# 22| __synth__3 +#-----| -> -1 # 22| call to [] #-----| -> ... = ... @@ -4239,7 +4248,7 @@ desugar.rb: # 22| Array #-----| -> 1 -# 22| __synth__0 +# 22| __synth__3 #-----| -> Array # 22| call to [] @@ -4258,7 +4267,7 @@ desugar.rb: #-----| -> call to [] # 25| enter m7 -#-----| -> __synth__0 +#-----| -> __synth__2 # 25| exit m7 @@ -4269,19 +4278,19 @@ desugar.rb: #-----| -> X # 26| ... = ... -#-----| -> __synth__0__1 +#-----| -> __synth__2__1 # 26| 0 #-----| -> call to [] -# 26| __synth__0 +# 26| __synth__2 #-----| -> 0 # 26| call to [] #-----| -> ... = ... # 26| x -#-----| -> __synth__0 +#-----| -> __synth__2 # 26| ... #-----| -> exit m7 (normal) @@ -4298,11 +4307,11 @@ desugar.rb: # 26| 1 #-----| -> call to [] -# 26| __synth__0 +# 26| __synth__2 #-----| -> 1 -# 26| __synth__0__1 -#-----| -> __synth__0 +# 26| __synth__2__1 +#-----| -> __synth__2 # 26| call to [] #-----| -> * ... @@ -4313,14 +4322,14 @@ desugar.rb: # 26| 0 #-----| -> call to [] -# 26| __synth__0__1 +# 26| __synth__2__1 #-----| -> 0 # 26| call to [] #-----| -> ... = ... # 26| y -#-----| -> __synth__0__1 +#-----| -> __synth__2__1 # 26| ... = ... #-----| -> ... @@ -4328,14 +4337,14 @@ desugar.rb: # 26| 1 #-----| -> call to [] -# 26| __synth__0__1 +# 26| __synth__2__1 #-----| -> 1 # 26| call to [] #-----| -> ... = ... # 26| z -#-----| -> __synth__0__1 +#-----| -> __synth__2__1 # 26| * ... #-----| -> ... = ... @@ -4346,7 +4355,7 @@ desugar.rb: # 26| Array #-----| -> 1 -# 26| __synth__0 +# 26| __synth__2 #-----| -> Array # 26| call to [] diff --git a/ruby/ql/test/library-tests/controlflow/graph/Nodes.expected b/ruby/ql/test/library-tests/controlflow/graph/Nodes.expected index f41b6e34a4d..0e39e2924bd 100644 --- a/ruby/ql/test/library-tests/controlflow/graph/Nodes.expected +++ b/ruby/ql/test/library-tests/controlflow/graph/Nodes.expected @@ -219,15 +219,15 @@ positionalArguments | desugar.rb:6:3:6:13 | call to count= | desugar.rb:6:17:6:17 | ... = ... | | desugar.rb:10:3:10:10 | call to []= | desugar.rb:10:9:10:9 | 0 | | desugar.rb:10:3:10:10 | call to []= | desugar.rb:10:14:10:14 | ... = ... | -| desugar.rb:14:3:14:13 | call to count= | desugar.rb:14:15:14:16 | __synth__1 | +| desugar.rb:14:3:14:13 | call to count= | desugar.rb:14:3:14:13 | __synth__1 | | desugar.rb:14:15:14:16 | ... + ... | desugar.rb:14:18:14:18 | 1 | | desugar.rb:18:3:18:28 | call to [] | desugar.rb:18:9:18:9 | __synth__1 | | desugar.rb:18:3:18:28 | call to [] | desugar.rb:18:12:18:16 | __synth__2 | | desugar.rb:18:3:18:28 | call to [] | desugar.rb:18:19:18:27 | __synth__3 | +| desugar.rb:18:3:18:28 | call to []= | desugar.rb:18:3:18:28 | __synth__4 | | desugar.rb:18:3:18:28 | call to []= | desugar.rb:18:9:18:9 | __synth__1 | | desugar.rb:18:3:18:28 | call to []= | desugar.rb:18:12:18:16 | __synth__2 | | desugar.rb:18:3:18:28 | call to []= | desugar.rb:18:19:18:27 | __synth__3 | -| desugar.rb:18:3:18:28 | call to []= | desugar.rb:18:30:18:31 | __synth__4 | | desugar.rb:18:19:18:27 | ... + ... | desugar.rb:18:27:18:27 | 3 | | desugar.rb:18:30:18:31 | ... + ... | desugar.rb:18:33:18:33 | 1 | | desugar.rb:22:3:22:3 | call to [] | desugar.rb:22:3:22:3 | 0 | diff --git a/ruby/ql/test/library-tests/dataflow/array-flow/array-flow.expected b/ruby/ql/test/library-tests/dataflow/array-flow/array-flow.expected index 399a65de525..35bbaabef87 100644 --- a/ruby/ql/test/library-tests/dataflow/array-flow/array-flow.expected +++ b/ruby/ql/test/library-tests/dataflow/array-flow/array-flow.expected @@ -1,103 +1,135 @@ failures edges -| array_flow.rb:2:9:2:20 | * ... [element 0] : | array_flow.rb:3:10:3:10 | a [element 0] : | -| array_flow.rb:2:9:2:20 | * ... [element 0] : | array_flow.rb:3:10:3:10 | a [element 0] : | -| array_flow.rb:2:9:2:20 | * ... [element 0] : | array_flow.rb:5:10:5:10 | a [element 0] : | -| array_flow.rb:2:9:2:20 | * ... [element 0] : | array_flow.rb:5:10:5:10 | a [element 0] : | +| array_flow.rb:2:5:2:5 | a [element 0] : | array_flow.rb:3:10:3:10 | a [element 0] : | +| array_flow.rb:2:5:2:5 | a [element 0] : | array_flow.rb:3:10:3:10 | a [element 0] : | +| array_flow.rb:2:5:2:5 | a [element 0] : | array_flow.rb:5:10:5:10 | a [element 0] : | +| array_flow.rb:2:5:2:5 | a [element 0] : | array_flow.rb:5:10:5:10 | a [element 0] : | +| array_flow.rb:2:9:2:20 | * ... [element 0] : | array_flow.rb:2:5:2:5 | a [element 0] : | +| array_flow.rb:2:9:2:20 | * ... [element 0] : | array_flow.rb:2:5:2:5 | a [element 0] : | | array_flow.rb:2:10:2:20 | call to source : | array_flow.rb:2:9:2:20 | * ... [element 0] : | | array_flow.rb:2:10:2:20 | call to source : | array_flow.rb:2:9:2:20 | * ... [element 0] : | | array_flow.rb:3:10:3:10 | a [element 0] : | array_flow.rb:3:10:3:13 | ...[...] | | array_flow.rb:3:10:3:10 | a [element 0] : | array_flow.rb:3:10:3:13 | ...[...] | | array_flow.rb:5:10:5:10 | a [element 0] : | array_flow.rb:5:10:5:13 | ...[...] | | array_flow.rb:5:10:5:10 | a [element 0] : | array_flow.rb:5:10:5:13 | ...[...] | -| array_flow.rb:9:13:9:21 | call to source : | array_flow.rb:11:10:11:10 | a [element 1] : | -| array_flow.rb:9:13:9:21 | call to source : | array_flow.rb:11:10:11:10 | a [element 1] : | -| array_flow.rb:9:13:9:21 | call to source : | array_flow.rb:13:10:13:10 | a [element 1] : | -| array_flow.rb:9:13:9:21 | call to source : | array_flow.rb:13:10:13:10 | a [element 1] : | +| array_flow.rb:9:5:9:5 | a [element 1] : | array_flow.rb:11:10:11:10 | a [element 1] : | +| array_flow.rb:9:5:9:5 | a [element 1] : | array_flow.rb:11:10:11:10 | a [element 1] : | +| array_flow.rb:9:5:9:5 | a [element 1] : | array_flow.rb:13:10:13:10 | a [element 1] : | +| array_flow.rb:9:5:9:5 | a [element 1] : | array_flow.rb:13:10:13:10 | a [element 1] : | +| array_flow.rb:9:13:9:21 | call to source : | array_flow.rb:9:5:9:5 | a [element 1] : | +| array_flow.rb:9:13:9:21 | call to source : | array_flow.rb:9:5:9:5 | a [element 1] : | | array_flow.rb:11:10:11:10 | a [element 1] : | array_flow.rb:11:10:11:13 | ...[...] | | array_flow.rb:11:10:11:10 | a [element 1] : | array_flow.rb:11:10:11:13 | ...[...] | | array_flow.rb:13:10:13:10 | a [element 1] : | array_flow.rb:13:10:13:13 | ...[...] | | array_flow.rb:13:10:13:10 | a [element 1] : | array_flow.rb:13:10:13:13 | ...[...] | -| array_flow.rb:17:9:17:33 | call to new [element] : | array_flow.rb:18:10:18:10 | a [element] : | -| array_flow.rb:17:9:17:33 | call to new [element] : | array_flow.rb:18:10:18:10 | a [element] : | -| array_flow.rb:17:9:17:33 | call to new [element] : | array_flow.rb:19:10:19:10 | a [element] : | -| array_flow.rb:17:9:17:33 | call to new [element] : | array_flow.rb:19:10:19:10 | a [element] : | -| array_flow.rb:17:9:17:33 | call to new [element] : | array_flow.rb:21:19:21:19 | a [element] : | -| array_flow.rb:17:9:17:33 | call to new [element] : | array_flow.rb:21:19:21:19 | a [element] : | +| array_flow.rb:17:5:17:5 | a [element] : | array_flow.rb:18:10:18:10 | a [element] : | +| array_flow.rb:17:5:17:5 | a [element] : | array_flow.rb:18:10:18:10 | a [element] : | +| array_flow.rb:17:5:17:5 | a [element] : | array_flow.rb:19:10:19:10 | a [element] : | +| array_flow.rb:17:5:17:5 | a [element] : | array_flow.rb:19:10:19:10 | a [element] : | +| array_flow.rb:17:5:17:5 | a [element] : | array_flow.rb:21:19:21:19 | a [element] : | +| array_flow.rb:17:5:17:5 | a [element] : | array_flow.rb:21:19:21:19 | a [element] : | +| array_flow.rb:17:9:17:33 | call to new [element] : | array_flow.rb:17:5:17:5 | a [element] : | +| array_flow.rb:17:9:17:33 | call to new [element] : | array_flow.rb:17:5:17:5 | a [element] : | | array_flow.rb:17:22:17:32 | call to source : | array_flow.rb:17:9:17:33 | call to new [element] : | | array_flow.rb:17:22:17:32 | call to source : | array_flow.rb:17:9:17:33 | call to new [element] : | | array_flow.rb:18:10:18:10 | a [element] : | array_flow.rb:18:10:18:13 | ...[...] | | array_flow.rb:18:10:18:10 | a [element] : | array_flow.rb:18:10:18:13 | ...[...] | | array_flow.rb:19:10:19:10 | a [element] : | array_flow.rb:19:10:19:13 | ...[...] | | array_flow.rb:19:10:19:10 | a [element] : | array_flow.rb:19:10:19:13 | ...[...] | -| array_flow.rb:21:9:21:20 | call to new [element] : | array_flow.rb:22:10:22:10 | b [element] : | -| array_flow.rb:21:9:21:20 | call to new [element] : | array_flow.rb:22:10:22:10 | b [element] : | -| array_flow.rb:21:9:21:20 | call to new [element] : | array_flow.rb:23:10:23:10 | b [element] : | -| array_flow.rb:21:9:21:20 | call to new [element] : | array_flow.rb:23:10:23:10 | b [element] : | +| array_flow.rb:21:5:21:5 | b [element] : | array_flow.rb:22:10:22:10 | b [element] : | +| array_flow.rb:21:5:21:5 | b [element] : | array_flow.rb:22:10:22:10 | b [element] : | +| array_flow.rb:21:5:21:5 | b [element] : | array_flow.rb:23:10:23:10 | b [element] : | +| array_flow.rb:21:5:21:5 | b [element] : | array_flow.rb:23:10:23:10 | b [element] : | +| array_flow.rb:21:9:21:20 | call to new [element] : | array_flow.rb:21:5:21:5 | b [element] : | +| array_flow.rb:21:9:21:20 | call to new [element] : | array_flow.rb:21:5:21:5 | b [element] : | | array_flow.rb:21:19:21:19 | a [element] : | array_flow.rb:21:9:21:20 | call to new [element] : | | array_flow.rb:21:19:21:19 | a [element] : | array_flow.rb:21:9:21:20 | call to new [element] : | | array_flow.rb:22:10:22:10 | b [element] : | array_flow.rb:22:10:22:13 | ...[...] | | array_flow.rb:22:10:22:10 | b [element] : | array_flow.rb:22:10:22:13 | ...[...] | | array_flow.rb:23:10:23:10 | b [element] : | array_flow.rb:23:10:23:13 | ...[...] | | array_flow.rb:23:10:23:10 | b [element] : | array_flow.rb:23:10:23:13 | ...[...] | -| array_flow.rb:25:9:27:7 | call to new [element] : | array_flow.rb:28:10:28:10 | c [element] : | -| array_flow.rb:25:9:27:7 | call to new [element] : | array_flow.rb:28:10:28:10 | c [element] : | -| array_flow.rb:25:9:27:7 | call to new [element] : | array_flow.rb:29:10:29:10 | c [element] : | -| array_flow.rb:25:9:27:7 | call to new [element] : | array_flow.rb:29:10:29:10 | c [element] : | +| array_flow.rb:25:5:25:5 | c [element] : | array_flow.rb:28:10:28:10 | c [element] : | +| array_flow.rb:25:5:25:5 | c [element] : | array_flow.rb:28:10:28:10 | c [element] : | +| array_flow.rb:25:5:25:5 | c [element] : | array_flow.rb:29:10:29:10 | c [element] : | +| array_flow.rb:25:5:25:5 | c [element] : | array_flow.rb:29:10:29:10 | c [element] : | +| array_flow.rb:25:9:27:7 | call to new [element] : | array_flow.rb:25:5:25:5 | c [element] : | +| array_flow.rb:25:9:27:7 | call to new [element] : | array_flow.rb:25:5:25:5 | c [element] : | | array_flow.rb:26:9:26:19 | call to source : | array_flow.rb:25:9:27:7 | call to new [element] : | | array_flow.rb:26:9:26:19 | call to source : | array_flow.rb:25:9:27:7 | call to new [element] : | | array_flow.rb:28:10:28:10 | c [element] : | array_flow.rb:28:10:28:13 | ...[...] | | array_flow.rb:28:10:28:10 | c [element] : | array_flow.rb:28:10:28:13 | ...[...] | | array_flow.rb:29:10:29:10 | c [element] : | array_flow.rb:29:10:29:13 | ...[...] | | array_flow.rb:29:10:29:10 | c [element] : | array_flow.rb:29:10:29:13 | ...[...] | -| array_flow.rb:33:10:33:18 | call to source : | array_flow.rb:34:27:34:27 | a [element 0] : | -| array_flow.rb:33:10:33:18 | call to source : | array_flow.rb:34:27:34:27 | a [element 0] : | -| array_flow.rb:34:9:34:28 | call to try_convert [element 0] : | array_flow.rb:35:10:35:10 | b [element 0] : | -| array_flow.rb:34:9:34:28 | call to try_convert [element 0] : | array_flow.rb:35:10:35:10 | b [element 0] : | +| array_flow.rb:33:5:33:5 | a [element 0] : | array_flow.rb:34:27:34:27 | a [element 0] : | +| array_flow.rb:33:5:33:5 | a [element 0] : | array_flow.rb:34:27:34:27 | a [element 0] : | +| array_flow.rb:33:10:33:18 | call to source : | array_flow.rb:33:5:33:5 | a [element 0] : | +| array_flow.rb:33:10:33:18 | call to source : | array_flow.rb:33:5:33:5 | a [element 0] : | +| array_flow.rb:34:5:34:5 | b [element 0] : | array_flow.rb:35:10:35:10 | b [element 0] : | +| array_flow.rb:34:5:34:5 | b [element 0] : | array_flow.rb:35:10:35:10 | b [element 0] : | +| array_flow.rb:34:9:34:28 | call to try_convert [element 0] : | array_flow.rb:34:5:34:5 | b [element 0] : | +| array_flow.rb:34:9:34:28 | call to try_convert [element 0] : | array_flow.rb:34:5:34:5 | b [element 0] : | | array_flow.rb:34:27:34:27 | a [element 0] : | array_flow.rb:34:9:34:28 | call to try_convert [element 0] : | | array_flow.rb:34:27:34:27 | a [element 0] : | array_flow.rb:34:9:34:28 | call to try_convert [element 0] : | | array_flow.rb:35:10:35:10 | b [element 0] : | array_flow.rb:35:10:35:13 | ...[...] | | array_flow.rb:35:10:35:10 | b [element 0] : | array_flow.rb:35:10:35:13 | ...[...] | -| array_flow.rb:40:10:40:20 | call to source : | array_flow.rb:42:9:42:9 | a [element 0] : | -| array_flow.rb:40:10:40:20 | call to source : | array_flow.rb:42:9:42:9 | a [element 0] : | -| array_flow.rb:41:16:41:26 | call to source : | array_flow.rb:42:13:42:13 | b [element 2] : | -| array_flow.rb:41:16:41:26 | call to source : | array_flow.rb:42:13:42:13 | b [element 2] : | +| array_flow.rb:40:5:40:5 | a [element 0] : | array_flow.rb:42:9:42:9 | a [element 0] : | +| array_flow.rb:40:5:40:5 | a [element 0] : | array_flow.rb:42:9:42:9 | a [element 0] : | +| array_flow.rb:40:10:40:20 | call to source : | array_flow.rb:40:5:40:5 | a [element 0] : | +| array_flow.rb:40:10:40:20 | call to source : | array_flow.rb:40:5:40:5 | a [element 0] : | +| array_flow.rb:41:5:41:5 | b [element 2] : | array_flow.rb:42:13:42:13 | b [element 2] : | +| array_flow.rb:41:5:41:5 | b [element 2] : | array_flow.rb:42:13:42:13 | b [element 2] : | +| array_flow.rb:41:16:41:26 | call to source : | array_flow.rb:41:5:41:5 | b [element 2] : | +| array_flow.rb:41:16:41:26 | call to source : | array_flow.rb:41:5:41:5 | b [element 2] : | +| array_flow.rb:42:5:42:5 | c [element] : | array_flow.rb:43:10:43:10 | c [element] : | +| array_flow.rb:42:5:42:5 | c [element] : | array_flow.rb:43:10:43:10 | c [element] : | +| array_flow.rb:42:5:42:5 | c [element] : | array_flow.rb:44:10:44:10 | c [element] : | +| array_flow.rb:42:5:42:5 | c [element] : | array_flow.rb:44:10:44:10 | c [element] : | | array_flow.rb:42:9:42:9 | a [element 0] : | array_flow.rb:42:9:42:13 | ... & ... [element] : | | array_flow.rb:42:9:42:9 | a [element 0] : | array_flow.rb:42:9:42:13 | ... & ... [element] : | -| array_flow.rb:42:9:42:13 | ... & ... [element] : | array_flow.rb:43:10:43:10 | c [element] : | -| array_flow.rb:42:9:42:13 | ... & ... [element] : | array_flow.rb:43:10:43:10 | c [element] : | -| array_flow.rb:42:9:42:13 | ... & ... [element] : | array_flow.rb:44:10:44:10 | c [element] : | -| array_flow.rb:42:9:42:13 | ... & ... [element] : | array_flow.rb:44:10:44:10 | c [element] : | +| array_flow.rb:42:9:42:13 | ... & ... [element] : | array_flow.rb:42:5:42:5 | c [element] : | +| array_flow.rb:42:9:42:13 | ... & ... [element] : | array_flow.rb:42:5:42:5 | c [element] : | | array_flow.rb:42:13:42:13 | b [element 2] : | array_flow.rb:42:9:42:13 | ... & ... [element] : | | array_flow.rb:42:13:42:13 | b [element 2] : | array_flow.rb:42:9:42:13 | ... & ... [element] : | | array_flow.rb:43:10:43:10 | c [element] : | array_flow.rb:43:10:43:13 | ...[...] | | array_flow.rb:43:10:43:10 | c [element] : | array_flow.rb:43:10:43:13 | ...[...] | | array_flow.rb:44:10:44:10 | c [element] : | array_flow.rb:44:10:44:13 | ...[...] | | array_flow.rb:44:10:44:10 | c [element] : | array_flow.rb:44:10:44:13 | ...[...] | -| array_flow.rb:48:10:48:18 | call to source : | array_flow.rb:49:9:49:9 | a [element 0] : | -| array_flow.rb:48:10:48:18 | call to source : | array_flow.rb:49:9:49:9 | a [element 0] : | +| array_flow.rb:48:5:48:5 | a [element 0] : | array_flow.rb:49:9:49:9 | a [element 0] : | +| array_flow.rb:48:5:48:5 | a [element 0] : | array_flow.rb:49:9:49:9 | a [element 0] : | +| array_flow.rb:48:10:48:18 | call to source : | array_flow.rb:48:5:48:5 | a [element 0] : | +| array_flow.rb:48:10:48:18 | call to source : | array_flow.rb:48:5:48:5 | a [element 0] : | +| array_flow.rb:49:5:49:5 | b [element] : | array_flow.rb:50:10:50:10 | b [element] : | +| array_flow.rb:49:5:49:5 | b [element] : | array_flow.rb:50:10:50:10 | b [element] : | +| array_flow.rb:49:5:49:5 | b [element] : | array_flow.rb:51:10:51:10 | b [element] : | +| array_flow.rb:49:5:49:5 | b [element] : | array_flow.rb:51:10:51:10 | b [element] : | | array_flow.rb:49:9:49:9 | a [element 0] : | array_flow.rb:49:9:49:13 | ... * ... [element] : | | array_flow.rb:49:9:49:9 | a [element 0] : | array_flow.rb:49:9:49:13 | ... * ... [element] : | -| array_flow.rb:49:9:49:13 | ... * ... [element] : | array_flow.rb:50:10:50:10 | b [element] : | -| array_flow.rb:49:9:49:13 | ... * ... [element] : | array_flow.rb:50:10:50:10 | b [element] : | -| array_flow.rb:49:9:49:13 | ... * ... [element] : | array_flow.rb:51:10:51:10 | b [element] : | -| array_flow.rb:49:9:49:13 | ... * ... [element] : | array_flow.rb:51:10:51:10 | b [element] : | +| array_flow.rb:49:9:49:13 | ... * ... [element] : | array_flow.rb:49:5:49:5 | b [element] : | +| array_flow.rb:49:9:49:13 | ... * ... [element] : | array_flow.rb:49:5:49:5 | b [element] : | | array_flow.rb:50:10:50:10 | b [element] : | array_flow.rb:50:10:50:13 | ...[...] | | array_flow.rb:50:10:50:10 | b [element] : | array_flow.rb:50:10:50:13 | ...[...] | | array_flow.rb:51:10:51:10 | b [element] : | array_flow.rb:51:10:51:13 | ...[...] | | array_flow.rb:51:10:51:10 | b [element] : | array_flow.rb:51:10:51:13 | ...[...] | -| array_flow.rb:55:10:55:20 | call to source : | array_flow.rb:57:9:57:9 | a [element 0] : | -| array_flow.rb:55:10:55:20 | call to source : | array_flow.rb:57:9:57:9 | a [element 0] : | -| array_flow.rb:56:13:56:23 | call to source : | array_flow.rb:57:13:57:13 | b [element 1] : | -| array_flow.rb:56:13:56:23 | call to source : | array_flow.rb:57:13:57:13 | b [element 1] : | +| array_flow.rb:55:5:55:5 | a [element 0] : | array_flow.rb:57:9:57:9 | a [element 0] : | +| array_flow.rb:55:5:55:5 | a [element 0] : | array_flow.rb:57:9:57:9 | a [element 0] : | +| array_flow.rb:55:10:55:20 | call to source : | array_flow.rb:55:5:55:5 | a [element 0] : | +| array_flow.rb:55:10:55:20 | call to source : | array_flow.rb:55:5:55:5 | a [element 0] : | +| array_flow.rb:56:5:56:5 | b [element 1] : | array_flow.rb:57:13:57:13 | b [element 1] : | +| array_flow.rb:56:5:56:5 | b [element 1] : | array_flow.rb:57:13:57:13 | b [element 1] : | +| array_flow.rb:56:13:56:23 | call to source : | array_flow.rb:56:5:56:5 | b [element 1] : | +| array_flow.rb:56:13:56:23 | call to source : | array_flow.rb:56:5:56:5 | b [element 1] : | +| array_flow.rb:57:5:57:5 | c [element 0] : | array_flow.rb:58:10:58:10 | c [element 0] : | +| array_flow.rb:57:5:57:5 | c [element 0] : | array_flow.rb:58:10:58:10 | c [element 0] : | +| array_flow.rb:57:5:57:5 | c [element] : | array_flow.rb:58:10:58:10 | c [element] : | +| array_flow.rb:57:5:57:5 | c [element] : | array_flow.rb:58:10:58:10 | c [element] : | +| array_flow.rb:57:5:57:5 | c [element] : | array_flow.rb:59:10:59:10 | c [element] : | +| array_flow.rb:57:5:57:5 | c [element] : | array_flow.rb:59:10:59:10 | c [element] : | | array_flow.rb:57:9:57:9 | a [element 0] : | array_flow.rb:57:9:57:13 | ... + ... [element 0] : | | array_flow.rb:57:9:57:9 | a [element 0] : | array_flow.rb:57:9:57:13 | ... + ... [element 0] : | -| array_flow.rb:57:9:57:13 | ... + ... [element 0] : | array_flow.rb:58:10:58:10 | c [element 0] : | -| array_flow.rb:57:9:57:13 | ... + ... [element 0] : | array_flow.rb:58:10:58:10 | c [element 0] : | -| array_flow.rb:57:9:57:13 | ... + ... [element] : | array_flow.rb:58:10:58:10 | c [element] : | -| array_flow.rb:57:9:57:13 | ... + ... [element] : | array_flow.rb:58:10:58:10 | c [element] : | -| array_flow.rb:57:9:57:13 | ... + ... [element] : | array_flow.rb:59:10:59:10 | c [element] : | -| array_flow.rb:57:9:57:13 | ... + ... [element] : | array_flow.rb:59:10:59:10 | c [element] : | +| array_flow.rb:57:9:57:13 | ... + ... [element 0] : | array_flow.rb:57:5:57:5 | c [element 0] : | +| array_flow.rb:57:9:57:13 | ... + ... [element 0] : | array_flow.rb:57:5:57:5 | c [element 0] : | +| array_flow.rb:57:9:57:13 | ... + ... [element] : | array_flow.rb:57:5:57:5 | c [element] : | +| array_flow.rb:57:9:57:13 | ... + ... [element] : | array_flow.rb:57:5:57:5 | c [element] : | | array_flow.rb:57:13:57:13 | b [element 1] : | array_flow.rb:57:9:57:13 | ... + ... [element] : | | array_flow.rb:57:13:57:13 | b [element 1] : | array_flow.rb:57:9:57:13 | ... + ... [element] : | | array_flow.rb:58:10:58:10 | c [element 0] : | array_flow.rb:58:10:58:13 | ...[...] | @@ -106,40 +138,51 @@ edges | array_flow.rb:58:10:58:10 | c [element] : | array_flow.rb:58:10:58:13 | ...[...] | | array_flow.rb:59:10:59:10 | c [element] : | array_flow.rb:59:10:59:13 | ...[...] | | array_flow.rb:59:10:59:10 | c [element] : | array_flow.rb:59:10:59:13 | ...[...] | -| array_flow.rb:63:10:63:20 | call to source : | array_flow.rb:65:9:65:9 | a [element 0] : | -| array_flow.rb:63:10:63:20 | call to source : | array_flow.rb:65:9:65:9 | a [element 0] : | +| array_flow.rb:63:5:63:5 | a [element 0] : | array_flow.rb:65:9:65:9 | a [element 0] : | +| array_flow.rb:63:5:63:5 | a [element 0] : | array_flow.rb:65:9:65:9 | a [element 0] : | +| array_flow.rb:63:10:63:20 | call to source : | array_flow.rb:63:5:63:5 | a [element 0] : | +| array_flow.rb:63:10:63:20 | call to source : | array_flow.rb:63:5:63:5 | a [element 0] : | +| array_flow.rb:65:5:65:5 | c [element] : | array_flow.rb:66:10:66:10 | c [element] : | +| array_flow.rb:65:5:65:5 | c [element] : | array_flow.rb:66:10:66:10 | c [element] : | +| array_flow.rb:65:5:65:5 | c [element] : | array_flow.rb:67:10:67:10 | c [element] : | +| array_flow.rb:65:5:65:5 | c [element] : | array_flow.rb:67:10:67:10 | c [element] : | | array_flow.rb:65:9:65:9 | a [element 0] : | array_flow.rb:65:9:65:13 | ... - ... [element] : | | array_flow.rb:65:9:65:9 | a [element 0] : | array_flow.rb:65:9:65:13 | ... - ... [element] : | -| array_flow.rb:65:9:65:13 | ... - ... [element] : | array_flow.rb:66:10:66:10 | c [element] : | -| array_flow.rb:65:9:65:13 | ... - ... [element] : | array_flow.rb:66:10:66:10 | c [element] : | -| array_flow.rb:65:9:65:13 | ... - ... [element] : | array_flow.rb:67:10:67:10 | c [element] : | -| array_flow.rb:65:9:65:13 | ... - ... [element] : | array_flow.rb:67:10:67:10 | c [element] : | +| array_flow.rb:65:9:65:13 | ... - ... [element] : | array_flow.rb:65:5:65:5 | c [element] : | +| array_flow.rb:65:9:65:13 | ... - ... [element] : | array_flow.rb:65:5:65:5 | c [element] : | | array_flow.rb:66:10:66:10 | c [element] : | array_flow.rb:66:10:66:13 | ...[...] | | array_flow.rb:66:10:66:10 | c [element] : | array_flow.rb:66:10:66:13 | ...[...] | | array_flow.rb:67:10:67:10 | c [element] : | array_flow.rb:67:10:67:13 | ...[...] | | array_flow.rb:67:10:67:10 | c [element] : | array_flow.rb:67:10:67:13 | ...[...] | -| array_flow.rb:71:10:71:20 | call to source : | array_flow.rb:72:9:72:9 | a [element 0] : | -| array_flow.rb:71:10:71:20 | call to source : | array_flow.rb:72:9:72:9 | a [element 0] : | -| array_flow.rb:71:10:71:20 | call to source : | array_flow.rb:73:10:73:10 | a [element 0] : | -| array_flow.rb:71:10:71:20 | call to source : | array_flow.rb:73:10:73:10 | a [element 0] : | +| array_flow.rb:71:5:71:5 | a [element 0] : | array_flow.rb:72:9:72:9 | a [element 0] : | +| array_flow.rb:71:5:71:5 | a [element 0] : | array_flow.rb:72:9:72:9 | a [element 0] : | +| array_flow.rb:71:5:71:5 | a [element 0] : | array_flow.rb:73:10:73:10 | a [element 0] : | +| array_flow.rb:71:5:71:5 | a [element 0] : | array_flow.rb:73:10:73:10 | a [element 0] : | +| array_flow.rb:71:10:71:20 | call to source : | array_flow.rb:71:5:71:5 | a [element 0] : | +| array_flow.rb:71:10:71:20 | call to source : | array_flow.rb:71:5:71:5 | a [element 0] : | +| array_flow.rb:72:5:72:5 | b : | array_flow.rb:75:10:75:10 | b : | +| array_flow.rb:72:5:72:5 | b : | array_flow.rb:76:10:76:10 | b : | +| array_flow.rb:72:5:72:5 | b [element 0] : | array_flow.rb:75:10:75:10 | b [element 0] : | +| array_flow.rb:72:5:72:5 | b [element 0] : | array_flow.rb:75:10:75:10 | b [element 0] : | +| array_flow.rb:72:5:72:5 | b [element] : | array_flow.rb:75:10:75:10 | b [element] : | +| array_flow.rb:72:5:72:5 | b [element] : | array_flow.rb:75:10:75:10 | b [element] : | +| array_flow.rb:72:5:72:5 | b [element] : | array_flow.rb:76:10:76:10 | b [element] : | +| array_flow.rb:72:5:72:5 | b [element] : | array_flow.rb:76:10:76:10 | b [element] : | | array_flow.rb:72:9:72:9 | [post] a [element] : | array_flow.rb:73:10:73:10 | a [element] : | | array_flow.rb:72:9:72:9 | [post] a [element] : | array_flow.rb:73:10:73:10 | a [element] : | | array_flow.rb:72:9:72:9 | [post] a [element] : | array_flow.rb:74:10:74:10 | a [element] : | | array_flow.rb:72:9:72:9 | [post] a [element] : | array_flow.rb:74:10:74:10 | a [element] : | | array_flow.rb:72:9:72:9 | a [element 0] : | array_flow.rb:72:9:72:24 | ... << ... [element 0] : | | array_flow.rb:72:9:72:9 | a [element 0] : | array_flow.rb:72:9:72:24 | ... << ... [element 0] : | -| array_flow.rb:72:9:72:24 | ... << ... [element 0] : | array_flow.rb:75:10:75:10 | b [element 0] : | -| array_flow.rb:72:9:72:24 | ... << ... [element 0] : | array_flow.rb:75:10:75:10 | b [element 0] : | -| array_flow.rb:72:9:72:24 | ... << ... [element] : | array_flow.rb:75:10:75:10 | b [element] : | -| array_flow.rb:72:9:72:24 | ... << ... [element] : | array_flow.rb:75:10:75:10 | b [element] : | -| array_flow.rb:72:9:72:24 | ... << ... [element] : | array_flow.rb:76:10:76:10 | b [element] : | -| array_flow.rb:72:9:72:24 | ... << ... [element] : | array_flow.rb:76:10:76:10 | b [element] : | +| array_flow.rb:72:9:72:24 | ... << ... [element 0] : | array_flow.rb:72:5:72:5 | b [element 0] : | +| array_flow.rb:72:9:72:24 | ... << ... [element 0] : | array_flow.rb:72:5:72:5 | b [element 0] : | +| array_flow.rb:72:9:72:24 | ... << ... [element] : | array_flow.rb:72:5:72:5 | b [element] : | +| array_flow.rb:72:9:72:24 | ... << ... [element] : | array_flow.rb:72:5:72:5 | b [element] : | +| array_flow.rb:72:14:72:24 | call to source : | array_flow.rb:72:5:72:5 | b : | | array_flow.rb:72:14:72:24 | call to source : | array_flow.rb:72:9:72:9 | [post] a [element] : | | array_flow.rb:72:14:72:24 | call to source : | array_flow.rb:72:9:72:9 | [post] a [element] : | | array_flow.rb:72:14:72:24 | call to source : | array_flow.rb:72:9:72:24 | ... << ... [element] : | | array_flow.rb:72:14:72:24 | call to source : | array_flow.rb:72:9:72:24 | ... << ... [element] : | -| array_flow.rb:72:14:72:24 | call to source : | array_flow.rb:75:10:75:10 | b : | -| array_flow.rb:72:14:72:24 | call to source : | array_flow.rb:76:10:76:10 | b : | | array_flow.rb:73:10:73:10 | a [element 0] : | array_flow.rb:73:10:73:13 | ...[...] | | array_flow.rb:73:10:73:10 | a [element 0] : | array_flow.rb:73:10:73:13 | ...[...] | | array_flow.rb:73:10:73:10 | a [element] : | array_flow.rb:73:10:73:13 | ...[...] | @@ -154,70 +197,96 @@ edges | array_flow.rb:76:10:76:10 | b : | array_flow.rb:76:10:76:13 | ...[...] | | array_flow.rb:76:10:76:10 | b [element] : | array_flow.rb:76:10:76:13 | ...[...] | | array_flow.rb:76:10:76:10 | b [element] : | array_flow.rb:76:10:76:13 | ...[...] | -| array_flow.rb:80:13:80:21 | call to source : | array_flow.rb:81:15:81:15 | a [element 1] : | -| array_flow.rb:80:13:80:21 | call to source : | array_flow.rb:81:15:81:15 | a [element 1] : | -| array_flow.rb:81:15:81:15 | a [element 1] : | array_flow.rb:83:10:83:10 | c | -| array_flow.rb:81:15:81:15 | a [element 1] : | array_flow.rb:83:10:83:10 | c | -| array_flow.rb:88:13:88:22 | call to source : | array_flow.rb:89:9:89:9 | a [element 1] : | -| array_flow.rb:88:13:88:22 | call to source : | array_flow.rb:89:9:89:9 | a [element 1] : | +| array_flow.rb:80:5:80:5 | a [element 1] : | array_flow.rb:81:15:81:15 | a [element 1] : | +| array_flow.rb:80:5:80:5 | a [element 1] : | array_flow.rb:81:15:81:15 | a [element 1] : | +| array_flow.rb:80:13:80:21 | call to source : | array_flow.rb:80:5:80:5 | a [element 1] : | +| array_flow.rb:80:13:80:21 | call to source : | array_flow.rb:80:5:80:5 | a [element 1] : | +| array_flow.rb:81:8:81:8 | c : | array_flow.rb:83:10:83:10 | c | +| array_flow.rb:81:8:81:8 | c : | array_flow.rb:83:10:83:10 | c | +| array_flow.rb:81:15:81:15 | __synth__3 [element 1] : | array_flow.rb:81:8:81:8 | c : | +| array_flow.rb:81:15:81:15 | __synth__3 [element 1] : | array_flow.rb:81:8:81:8 | c : | +| array_flow.rb:81:15:81:15 | a [element 1] : | array_flow.rb:81:15:81:15 | __synth__3 [element 1] : | +| array_flow.rb:81:15:81:15 | a [element 1] : | array_flow.rb:81:15:81:15 | __synth__3 [element 1] : | +| array_flow.rb:88:5:88:5 | a [element 1] : | array_flow.rb:89:9:89:9 | a [element 1] : | +| array_flow.rb:88:5:88:5 | a [element 1] : | array_flow.rb:89:9:89:9 | a [element 1] : | +| array_flow.rb:88:13:88:22 | call to source : | array_flow.rb:88:5:88:5 | a [element 1] : | +| array_flow.rb:88:13:88:22 | call to source : | array_flow.rb:88:5:88:5 | a [element 1] : | +| array_flow.rb:89:5:89:5 | b [element 1] : | array_flow.rb:91:10:91:10 | b [element 1] : | +| array_flow.rb:89:5:89:5 | b [element 1] : | array_flow.rb:91:10:91:10 | b [element 1] : | +| array_flow.rb:89:5:89:5 | b [element 1] : | array_flow.rb:92:10:92:10 | b [element 1] : | +| array_flow.rb:89:5:89:5 | b [element 1] : | array_flow.rb:92:10:92:10 | b [element 1] : | | array_flow.rb:89:9:89:9 | a [element 1] : | array_flow.rb:89:9:89:15 | ...[...] [element 1] : | | array_flow.rb:89:9:89:9 | a [element 1] : | array_flow.rb:89:9:89:15 | ...[...] [element 1] : | -| array_flow.rb:89:9:89:15 | ...[...] [element 1] : | array_flow.rb:91:10:91:10 | b [element 1] : | -| array_flow.rb:89:9:89:15 | ...[...] [element 1] : | array_flow.rb:91:10:91:10 | b [element 1] : | -| array_flow.rb:89:9:89:15 | ...[...] [element 1] : | array_flow.rb:92:10:92:10 | b [element 1] : | -| array_flow.rb:89:9:89:15 | ...[...] [element 1] : | array_flow.rb:92:10:92:10 | b [element 1] : | +| array_flow.rb:89:9:89:15 | ...[...] [element 1] : | array_flow.rb:89:5:89:5 | b [element 1] : | +| array_flow.rb:89:9:89:15 | ...[...] [element 1] : | array_flow.rb:89:5:89:5 | b [element 1] : | | array_flow.rb:91:10:91:10 | b [element 1] : | array_flow.rb:91:10:91:13 | ...[...] | | array_flow.rb:91:10:91:10 | b [element 1] : | array_flow.rb:91:10:91:13 | ...[...] | | array_flow.rb:92:10:92:10 | b [element 1] : | array_flow.rb:92:10:92:13 | ...[...] | | array_flow.rb:92:10:92:10 | b [element 1] : | array_flow.rb:92:10:92:13 | ...[...] | -| array_flow.rb:96:13:96:22 | call to source : | array_flow.rb:97:9:97:9 | a [element 1] : | -| array_flow.rb:96:13:96:22 | call to source : | array_flow.rb:97:9:97:9 | a [element 1] : | +| array_flow.rb:96:5:96:5 | a [element 1] : | array_flow.rb:97:9:97:9 | a [element 1] : | +| array_flow.rb:96:5:96:5 | a [element 1] : | array_flow.rb:97:9:97:9 | a [element 1] : | +| array_flow.rb:96:13:96:22 | call to source : | array_flow.rb:96:5:96:5 | a [element 1] : | +| array_flow.rb:96:13:96:22 | call to source : | array_flow.rb:96:5:96:5 | a [element 1] : | +| array_flow.rb:97:5:97:5 | b [element 1] : | array_flow.rb:99:10:99:10 | b [element 1] : | +| array_flow.rb:97:5:97:5 | b [element 1] : | array_flow.rb:99:10:99:10 | b [element 1] : | +| array_flow.rb:97:5:97:5 | b [element 1] : | array_flow.rb:101:10:101:10 | b [element 1] : | +| array_flow.rb:97:5:97:5 | b [element 1] : | array_flow.rb:101:10:101:10 | b [element 1] : | | array_flow.rb:97:9:97:9 | a [element 1] : | array_flow.rb:97:9:97:15 | ...[...] [element 1] : | | array_flow.rb:97:9:97:9 | a [element 1] : | array_flow.rb:97:9:97:15 | ...[...] [element 1] : | -| array_flow.rb:97:9:97:15 | ...[...] [element 1] : | array_flow.rb:99:10:99:10 | b [element 1] : | -| array_flow.rb:97:9:97:15 | ...[...] [element 1] : | array_flow.rb:99:10:99:10 | b [element 1] : | -| array_flow.rb:97:9:97:15 | ...[...] [element 1] : | array_flow.rb:101:10:101:10 | b [element 1] : | -| array_flow.rb:97:9:97:15 | ...[...] [element 1] : | array_flow.rb:101:10:101:10 | b [element 1] : | +| array_flow.rb:97:9:97:15 | ...[...] [element 1] : | array_flow.rb:97:5:97:5 | b [element 1] : | +| array_flow.rb:97:9:97:15 | ...[...] [element 1] : | array_flow.rb:97:5:97:5 | b [element 1] : | | array_flow.rb:99:10:99:10 | b [element 1] : | array_flow.rb:99:10:99:13 | ...[...] | | array_flow.rb:99:10:99:10 | b [element 1] : | array_flow.rb:99:10:99:13 | ...[...] | | array_flow.rb:101:10:101:10 | b [element 1] : | array_flow.rb:101:10:101:13 | ...[...] | | array_flow.rb:101:10:101:10 | b [element 1] : | array_flow.rb:101:10:101:13 | ...[...] | -| array_flow.rb:103:13:103:24 | call to source : | array_flow.rb:104:9:104:9 | a [element 1] : | -| array_flow.rb:103:13:103:24 | call to source : | array_flow.rb:104:9:104:9 | a [element 1] : | +| array_flow.rb:103:5:103:5 | a [element 1] : | array_flow.rb:104:9:104:9 | a [element 1] : | +| array_flow.rb:103:5:103:5 | a [element 1] : | array_flow.rb:104:9:104:9 | a [element 1] : | +| array_flow.rb:103:13:103:24 | call to source : | array_flow.rb:103:5:103:5 | a [element 1] : | +| array_flow.rb:103:13:103:24 | call to source : | array_flow.rb:103:5:103:5 | a [element 1] : | +| array_flow.rb:104:5:104:5 | b [element 1] : | array_flow.rb:106:10:106:10 | b [element 1] : | +| array_flow.rb:104:5:104:5 | b [element 1] : | array_flow.rb:106:10:106:10 | b [element 1] : | | array_flow.rb:104:9:104:9 | a [element 1] : | array_flow.rb:104:9:104:16 | ...[...] [element 1] : | | array_flow.rb:104:9:104:9 | a [element 1] : | array_flow.rb:104:9:104:16 | ...[...] [element 1] : | -| array_flow.rb:104:9:104:16 | ...[...] [element 1] : | array_flow.rb:106:10:106:10 | b [element 1] : | -| array_flow.rb:104:9:104:16 | ...[...] [element 1] : | array_flow.rb:106:10:106:10 | b [element 1] : | +| array_flow.rb:104:9:104:16 | ...[...] [element 1] : | array_flow.rb:104:5:104:5 | b [element 1] : | +| array_flow.rb:104:9:104:16 | ...[...] [element 1] : | array_flow.rb:104:5:104:5 | b [element 1] : | | array_flow.rb:106:10:106:10 | b [element 1] : | array_flow.rb:106:10:106:13 | ...[...] | | array_flow.rb:106:10:106:10 | b [element 1] : | array_flow.rb:106:10:106:13 | ...[...] | -| array_flow.rb:109:13:109:24 | call to source : | array_flow.rb:110:9:110:9 | a [element 1] : | -| array_flow.rb:109:13:109:24 | call to source : | array_flow.rb:110:9:110:9 | a [element 1] : | -| array_flow.rb:109:13:109:24 | call to source : | array_flow.rb:114:9:114:9 | a [element 1] : | -| array_flow.rb:109:13:109:24 | call to source : | array_flow.rb:114:9:114:9 | a [element 1] : | -| array_flow.rb:109:30:109:41 | call to source : | array_flow.rb:110:9:110:9 | a [element 3] : | -| array_flow.rb:109:30:109:41 | call to source : | array_flow.rb:110:9:110:9 | a [element 3] : | -| array_flow.rb:109:30:109:41 | call to source : | array_flow.rb:114:9:114:9 | a [element 3] : | -| array_flow.rb:109:30:109:41 | call to source : | array_flow.rb:114:9:114:9 | a [element 3] : | +| array_flow.rb:109:5:109:5 | a [element 1] : | array_flow.rb:110:9:110:9 | a [element 1] : | +| array_flow.rb:109:5:109:5 | a [element 1] : | array_flow.rb:110:9:110:9 | a [element 1] : | +| array_flow.rb:109:5:109:5 | a [element 1] : | array_flow.rb:114:9:114:9 | a [element 1] : | +| array_flow.rb:109:5:109:5 | a [element 1] : | array_flow.rb:114:9:114:9 | a [element 1] : | +| array_flow.rb:109:5:109:5 | a [element 3] : | array_flow.rb:110:9:110:9 | a [element 3] : | +| array_flow.rb:109:5:109:5 | a [element 3] : | array_flow.rb:110:9:110:9 | a [element 3] : | +| array_flow.rb:109:5:109:5 | a [element 3] : | array_flow.rb:114:9:114:9 | a [element 3] : | +| array_flow.rb:109:5:109:5 | a [element 3] : | array_flow.rb:114:9:114:9 | a [element 3] : | +| array_flow.rb:109:13:109:24 | call to source : | array_flow.rb:109:5:109:5 | a [element 1] : | +| array_flow.rb:109:13:109:24 | call to source : | array_flow.rb:109:5:109:5 | a [element 1] : | +| array_flow.rb:109:30:109:41 | call to source : | array_flow.rb:109:5:109:5 | a [element 3] : | +| array_flow.rb:109:30:109:41 | call to source : | array_flow.rb:109:5:109:5 | a [element 3] : | +| array_flow.rb:110:5:110:5 | b [element] : | array_flow.rb:111:10:111:10 | b [element] : | +| array_flow.rb:110:5:110:5 | b [element] : | array_flow.rb:111:10:111:10 | b [element] : | +| array_flow.rb:110:5:110:5 | b [element] : | array_flow.rb:112:10:112:10 | b [element] : | +| array_flow.rb:110:5:110:5 | b [element] : | array_flow.rb:112:10:112:10 | b [element] : | | array_flow.rb:110:9:110:9 | a [element 1] : | array_flow.rb:110:9:110:18 | ...[...] [element] : | | array_flow.rb:110:9:110:9 | a [element 1] : | array_flow.rb:110:9:110:18 | ...[...] [element] : | | array_flow.rb:110:9:110:9 | a [element 3] : | array_flow.rb:110:9:110:18 | ...[...] [element] : | | array_flow.rb:110:9:110:9 | a [element 3] : | array_flow.rb:110:9:110:18 | ...[...] [element] : | -| array_flow.rb:110:9:110:18 | ...[...] [element] : | array_flow.rb:111:10:111:10 | b [element] : | -| array_flow.rb:110:9:110:18 | ...[...] [element] : | array_flow.rb:111:10:111:10 | b [element] : | -| array_flow.rb:110:9:110:18 | ...[...] [element] : | array_flow.rb:112:10:112:10 | b [element] : | -| array_flow.rb:110:9:110:18 | ...[...] [element] : | array_flow.rb:112:10:112:10 | b [element] : | +| array_flow.rb:110:9:110:18 | ...[...] [element] : | array_flow.rb:110:5:110:5 | b [element] : | +| array_flow.rb:110:9:110:18 | ...[...] [element] : | array_flow.rb:110:5:110:5 | b [element] : | | array_flow.rb:111:10:111:10 | b [element] : | array_flow.rb:111:10:111:13 | ...[...] | | array_flow.rb:111:10:111:10 | b [element] : | array_flow.rb:111:10:111:13 | ...[...] | | array_flow.rb:112:10:112:10 | b [element] : | array_flow.rb:112:10:112:13 | ...[...] | | array_flow.rb:112:10:112:10 | b [element] : | array_flow.rb:112:10:112:13 | ...[...] | +| array_flow.rb:114:5:114:5 | b [element] : | array_flow.rb:115:10:115:10 | b [element] : | +| array_flow.rb:114:5:114:5 | b [element] : | array_flow.rb:115:10:115:10 | b [element] : | +| array_flow.rb:114:5:114:5 | b [element] : | array_flow.rb:116:10:116:10 | b [element] : | +| array_flow.rb:114:5:114:5 | b [element] : | array_flow.rb:116:10:116:10 | b [element] : | | array_flow.rb:114:9:114:9 | a [element 1] : | array_flow.rb:114:9:114:19 | ...[...] [element] : | | array_flow.rb:114:9:114:9 | a [element 1] : | array_flow.rb:114:9:114:19 | ...[...] [element] : | | array_flow.rb:114:9:114:9 | a [element 3] : | array_flow.rb:114:9:114:19 | ...[...] [element] : | | array_flow.rb:114:9:114:9 | a [element 3] : | array_flow.rb:114:9:114:19 | ...[...] [element] : | -| array_flow.rb:114:9:114:19 | ...[...] [element] : | array_flow.rb:115:10:115:10 | b [element] : | -| array_flow.rb:114:9:114:19 | ...[...] [element] : | array_flow.rb:115:10:115:10 | b [element] : | -| array_flow.rb:114:9:114:19 | ...[...] [element] : | array_flow.rb:116:10:116:10 | b [element] : | -| array_flow.rb:114:9:114:19 | ...[...] [element] : | array_flow.rb:116:10:116:10 | b [element] : | +| array_flow.rb:114:9:114:19 | ...[...] [element] : | array_flow.rb:114:5:114:5 | b [element] : | +| array_flow.rb:114:9:114:19 | ...[...] [element] : | array_flow.rb:114:5:114:5 | b [element] : | | array_flow.rb:115:10:115:10 | b [element] : | array_flow.rb:115:10:115:13 | ...[...] | | array_flow.rb:115:10:115:10 | b [element] : | array_flow.rb:115:10:115:13 | ...[...] | | array_flow.rb:116:10:116:10 | b [element] : | array_flow.rb:116:10:116:13 | ...[...] | @@ -278,34 +347,44 @@ edges | array_flow.rb:147:10:147:10 | a [element] : | array_flow.rb:147:10:147:13 | ...[...] | | array_flow.rb:148:10:148:10 | a [element] : | array_flow.rb:148:10:148:13 | ...[...] | | array_flow.rb:148:10:148:10 | a [element] : | array_flow.rb:148:10:148:13 | ...[...] | -| array_flow.rb:152:16:152:25 | call to source : | array_flow.rb:153:5:153:5 | a [element 2] : | -| array_flow.rb:152:16:152:25 | call to source : | array_flow.rb:153:5:153:5 | a [element 2] : | +| array_flow.rb:152:5:152:5 | a [element 2] : | array_flow.rb:153:5:153:5 | a [element 2] : | +| array_flow.rb:152:5:152:5 | a [element 2] : | array_flow.rb:153:5:153:5 | a [element 2] : | +| array_flow.rb:152:16:152:25 | call to source : | array_flow.rb:152:5:152:5 | a [element 2] : | +| array_flow.rb:152:16:152:25 | call to source : | array_flow.rb:152:5:152:5 | a [element 2] : | | array_flow.rb:153:5:153:5 | a [element 2] : | array_flow.rb:153:16:153:16 | x : | | array_flow.rb:153:5:153:5 | a [element 2] : | array_flow.rb:153:16:153:16 | x : | | array_flow.rb:153:16:153:16 | x : | array_flow.rb:154:14:154:14 | x | | array_flow.rb:153:16:153:16 | x : | array_flow.rb:154:14:154:14 | x | -| array_flow.rb:159:16:159:25 | call to source : | array_flow.rb:160:5:160:5 | a [element 2] : | -| array_flow.rb:159:16:159:25 | call to source : | array_flow.rb:160:5:160:5 | a [element 2] : | +| array_flow.rb:159:5:159:5 | a [element 2] : | array_flow.rb:160:5:160:5 | a [element 2] : | +| array_flow.rb:159:5:159:5 | a [element 2] : | array_flow.rb:160:5:160:5 | a [element 2] : | +| array_flow.rb:159:16:159:25 | call to source : | array_flow.rb:159:5:159:5 | a [element 2] : | +| array_flow.rb:159:16:159:25 | call to source : | array_flow.rb:159:5:159:5 | a [element 2] : | | array_flow.rb:160:5:160:5 | a [element 2] : | array_flow.rb:160:16:160:16 | x : | | array_flow.rb:160:5:160:5 | a [element 2] : | array_flow.rb:160:16:160:16 | x : | | array_flow.rb:160:16:160:16 | x : | array_flow.rb:161:14:161:14 | x | | array_flow.rb:160:16:160:16 | x : | array_flow.rb:161:14:161:14 | x | -| array_flow.rb:166:10:166:21 | call to source : | array_flow.rb:167:9:167:9 | a [element 0] : | -| array_flow.rb:166:10:166:21 | call to source : | array_flow.rb:167:9:167:9 | a [element 0] : | -| array_flow.rb:166:10:166:21 | call to source : | array_flow.rb:168:10:168:10 | a [element 0] : | -| array_flow.rb:166:10:166:21 | call to source : | array_flow.rb:168:10:168:10 | a [element 0] : | +| array_flow.rb:166:5:166:5 | a [element 0] : | array_flow.rb:167:9:167:9 | a [element 0] : | +| array_flow.rb:166:5:166:5 | a [element 0] : | array_flow.rb:167:9:167:9 | a [element 0] : | +| array_flow.rb:166:5:166:5 | a [element 0] : | array_flow.rb:168:10:168:10 | a [element 0] : | +| array_flow.rb:166:5:166:5 | a [element 0] : | array_flow.rb:168:10:168:10 | a [element 0] : | +| array_flow.rb:166:10:166:21 | call to source : | array_flow.rb:166:5:166:5 | a [element 0] : | +| array_flow.rb:166:10:166:21 | call to source : | array_flow.rb:166:5:166:5 | a [element 0] : | +| array_flow.rb:167:5:167:5 | b [element 0] : | array_flow.rb:170:10:170:10 | b [element 0] : | +| array_flow.rb:167:5:167:5 | b [element 0] : | array_flow.rb:170:10:170:10 | b [element 0] : | +| array_flow.rb:167:5:167:5 | b [element] : | array_flow.rb:170:10:170:10 | b [element] : | +| array_flow.rb:167:5:167:5 | b [element] : | array_flow.rb:170:10:170:10 | b [element] : | +| array_flow.rb:167:5:167:5 | b [element] : | array_flow.rb:171:10:171:10 | b [element] : | +| array_flow.rb:167:5:167:5 | b [element] : | array_flow.rb:171:10:171:10 | b [element] : | | array_flow.rb:167:9:167:9 | [post] a [element] : | array_flow.rb:168:10:168:10 | a [element] : | | array_flow.rb:167:9:167:9 | [post] a [element] : | array_flow.rb:168:10:168:10 | a [element] : | | array_flow.rb:167:9:167:9 | [post] a [element] : | array_flow.rb:169:10:169:10 | a [element] : | | array_flow.rb:167:9:167:9 | [post] a [element] : | array_flow.rb:169:10:169:10 | a [element] : | | array_flow.rb:167:9:167:9 | a [element 0] : | array_flow.rb:167:9:167:44 | call to append [element 0] : | | array_flow.rb:167:9:167:9 | a [element 0] : | array_flow.rb:167:9:167:44 | call to append [element 0] : | -| array_flow.rb:167:9:167:44 | call to append [element 0] : | array_flow.rb:170:10:170:10 | b [element 0] : | -| array_flow.rb:167:9:167:44 | call to append [element 0] : | array_flow.rb:170:10:170:10 | b [element 0] : | -| array_flow.rb:167:9:167:44 | call to append [element] : | array_flow.rb:170:10:170:10 | b [element] : | -| array_flow.rb:167:9:167:44 | call to append [element] : | array_flow.rb:170:10:170:10 | b [element] : | -| array_flow.rb:167:9:167:44 | call to append [element] : | array_flow.rb:171:10:171:10 | b [element] : | -| array_flow.rb:167:9:167:44 | call to append [element] : | array_flow.rb:171:10:171:10 | b [element] : | +| array_flow.rb:167:9:167:44 | call to append [element 0] : | array_flow.rb:167:5:167:5 | b [element 0] : | +| array_flow.rb:167:9:167:44 | call to append [element 0] : | array_flow.rb:167:5:167:5 | b [element 0] : | +| array_flow.rb:167:9:167:44 | call to append [element] : | array_flow.rb:167:5:167:5 | b [element] : | +| array_flow.rb:167:9:167:44 | call to append [element] : | array_flow.rb:167:5:167:5 | b [element] : | | array_flow.rb:167:18:167:29 | call to source : | array_flow.rb:167:9:167:9 | [post] a [element] : | | array_flow.rb:167:18:167:29 | call to source : | array_flow.rb:167:9:167:9 | [post] a [element] : | | array_flow.rb:167:18:167:29 | call to source : | array_flow.rb:167:9:167:44 | call to append [element] : | @@ -326,12 +405,16 @@ edges | array_flow.rb:170:10:170:10 | b [element] : | array_flow.rb:170:10:170:13 | ...[...] | | array_flow.rb:171:10:171:10 | b [element] : | array_flow.rb:171:10:171:13 | ...[...] | | array_flow.rb:171:10:171:10 | b [element] : | array_flow.rb:171:10:171:13 | ...[...] | -| array_flow.rb:177:15:177:24 | call to source : | array_flow.rb:178:16:178:16 | c [element 1] : | -| array_flow.rb:177:15:177:24 | call to source : | array_flow.rb:178:16:178:16 | c [element 1] : | -| array_flow.rb:178:16:178:16 | c [element 1] : | array_flow.rb:179:11:179:11 | d [element 2, element 1] : | -| array_flow.rb:178:16:178:16 | c [element 1] : | array_flow.rb:179:11:179:11 | d [element 2, element 1] : | -| array_flow.rb:178:16:178:16 | c [element 1] : | array_flow.rb:180:11:180:11 | d [element 2, element 1] : | -| array_flow.rb:178:16:178:16 | c [element 1] : | array_flow.rb:180:11:180:11 | d [element 2, element 1] : | +| array_flow.rb:177:5:177:5 | c [element 1] : | array_flow.rb:178:16:178:16 | c [element 1] : | +| array_flow.rb:177:5:177:5 | c [element 1] : | array_flow.rb:178:16:178:16 | c [element 1] : | +| array_flow.rb:177:15:177:24 | call to source : | array_flow.rb:177:5:177:5 | c [element 1] : | +| array_flow.rb:177:15:177:24 | call to source : | array_flow.rb:177:5:177:5 | c [element 1] : | +| array_flow.rb:178:5:178:5 | d [element 2, element 1] : | array_flow.rb:179:11:179:11 | d [element 2, element 1] : | +| array_flow.rb:178:5:178:5 | d [element 2, element 1] : | array_flow.rb:179:11:179:11 | d [element 2, element 1] : | +| array_flow.rb:178:5:178:5 | d [element 2, element 1] : | array_flow.rb:180:11:180:11 | d [element 2, element 1] : | +| array_flow.rb:178:5:178:5 | d [element 2, element 1] : | array_flow.rb:180:11:180:11 | d [element 2, element 1] : | +| array_flow.rb:178:16:178:16 | c [element 1] : | array_flow.rb:178:5:178:5 | d [element 2, element 1] : | +| array_flow.rb:178:16:178:16 | c [element 1] : | array_flow.rb:178:5:178:5 | d [element 2, element 1] : | | array_flow.rb:179:11:179:11 | d [element 2, element 1] : | array_flow.rb:179:11:179:22 | call to assoc [element 1] : | | array_flow.rb:179:11:179:11 | d [element 2, element 1] : | array_flow.rb:179:11:179:22 | call to assoc [element 1] : | | array_flow.rb:179:11:179:22 | call to assoc [element 1] : | array_flow.rb:179:11:179:25 | ...[...] : | @@ -344,40 +427,54 @@ edges | array_flow.rb:180:11:180:22 | call to assoc [element 1] : | array_flow.rb:180:11:180:25 | ...[...] : | | array_flow.rb:180:11:180:25 | ...[...] : | array_flow.rb:180:10:180:26 | ( ... ) | | array_flow.rb:180:11:180:25 | ...[...] : | array_flow.rb:180:10:180:26 | ( ... ) | -| array_flow.rb:184:13:184:22 | call to source : | array_flow.rb:186:10:186:10 | a [element 1] : | -| array_flow.rb:184:13:184:22 | call to source : | array_flow.rb:186:10:186:10 | a [element 1] : | -| array_flow.rb:184:13:184:22 | call to source : | array_flow.rb:188:10:188:10 | a [element 1] : | -| array_flow.rb:184:13:184:22 | call to source : | array_flow.rb:188:10:188:10 | a [element 1] : | +| array_flow.rb:184:5:184:5 | a [element 1] : | array_flow.rb:186:10:186:10 | a [element 1] : | +| array_flow.rb:184:5:184:5 | a [element 1] : | array_flow.rb:186:10:186:10 | a [element 1] : | +| array_flow.rb:184:5:184:5 | a [element 1] : | array_flow.rb:188:10:188:10 | a [element 1] : | +| array_flow.rb:184:5:184:5 | a [element 1] : | array_flow.rb:188:10:188:10 | a [element 1] : | +| array_flow.rb:184:13:184:22 | call to source : | array_flow.rb:184:5:184:5 | a [element 1] : | +| array_flow.rb:184:13:184:22 | call to source : | array_flow.rb:184:5:184:5 | a [element 1] : | | array_flow.rb:186:10:186:10 | a [element 1] : | array_flow.rb:186:10:186:16 | call to at | | array_flow.rb:186:10:186:10 | a [element 1] : | array_flow.rb:186:10:186:16 | call to at | | array_flow.rb:188:10:188:10 | a [element 1] : | array_flow.rb:188:10:188:16 | call to at | | array_flow.rb:188:10:188:10 | a [element 1] : | array_flow.rb:188:10:188:16 | call to at | -| array_flow.rb:192:16:192:25 | call to source : | array_flow.rb:193:9:193:9 | a [element 2] : | -| array_flow.rb:192:16:192:25 | call to source : | array_flow.rb:193:9:193:9 | a [element 2] : | +| array_flow.rb:192:5:192:5 | a [element 2] : | array_flow.rb:193:9:193:9 | a [element 2] : | +| array_flow.rb:192:5:192:5 | a [element 2] : | array_flow.rb:193:9:193:9 | a [element 2] : | +| array_flow.rb:192:16:192:25 | call to source : | array_flow.rb:192:5:192:5 | a [element 2] : | +| array_flow.rb:192:16:192:25 | call to source : | array_flow.rb:192:5:192:5 | a [element 2] : | +| array_flow.rb:193:5:193:5 | b : | array_flow.rb:196:10:196:10 | b | +| array_flow.rb:193:5:193:5 | b : | array_flow.rb:196:10:196:10 | b | | array_flow.rb:193:9:193:9 | a [element 2] : | array_flow.rb:193:9:195:7 | call to bsearch : | | array_flow.rb:193:9:193:9 | a [element 2] : | array_flow.rb:193:9:195:7 | call to bsearch : | | array_flow.rb:193:9:193:9 | a [element 2] : | array_flow.rb:193:23:193:23 | x : | | array_flow.rb:193:9:193:9 | a [element 2] : | array_flow.rb:193:23:193:23 | x : | -| array_flow.rb:193:9:195:7 | call to bsearch : | array_flow.rb:196:10:196:10 | b | -| array_flow.rb:193:9:195:7 | call to bsearch : | array_flow.rb:196:10:196:10 | b | +| array_flow.rb:193:9:195:7 | call to bsearch : | array_flow.rb:193:5:193:5 | b : | +| array_flow.rb:193:9:195:7 | call to bsearch : | array_flow.rb:193:5:193:5 | b : | | array_flow.rb:193:23:193:23 | x : | array_flow.rb:194:14:194:14 | x | | array_flow.rb:193:23:193:23 | x : | array_flow.rb:194:14:194:14 | x | -| array_flow.rb:200:16:200:25 | call to source : | array_flow.rb:201:9:201:9 | a [element 2] : | -| array_flow.rb:200:16:200:25 | call to source : | array_flow.rb:201:9:201:9 | a [element 2] : | +| array_flow.rb:200:5:200:5 | a [element 2] : | array_flow.rb:201:9:201:9 | a [element 2] : | +| array_flow.rb:200:5:200:5 | a [element 2] : | array_flow.rb:201:9:201:9 | a [element 2] : | +| array_flow.rb:200:16:200:25 | call to source : | array_flow.rb:200:5:200:5 | a [element 2] : | +| array_flow.rb:200:16:200:25 | call to source : | array_flow.rb:200:5:200:5 | a [element 2] : | | array_flow.rb:201:9:201:9 | a [element 2] : | array_flow.rb:201:29:201:29 | x : | | array_flow.rb:201:9:201:9 | a [element 2] : | array_flow.rb:201:29:201:29 | x : | | array_flow.rb:201:29:201:29 | x : | array_flow.rb:202:14:202:14 | x | | array_flow.rb:201:29:201:29 | x : | array_flow.rb:202:14:202:14 | x | -| array_flow.rb:208:16:208:25 | call to source : | array_flow.rb:209:5:209:5 | a [element 2] : | -| array_flow.rb:208:16:208:25 | call to source : | array_flow.rb:209:5:209:5 | a [element 2] : | +| array_flow.rb:208:5:208:5 | a [element 2] : | array_flow.rb:209:5:209:5 | a [element 2] : | +| array_flow.rb:208:5:208:5 | a [element 2] : | array_flow.rb:209:5:209:5 | a [element 2] : | +| array_flow.rb:208:16:208:25 | call to source : | array_flow.rb:208:5:208:5 | a [element 2] : | +| array_flow.rb:208:16:208:25 | call to source : | array_flow.rb:208:5:208:5 | a [element 2] : | | array_flow.rb:209:5:209:5 | a [element 2] : | array_flow.rb:209:17:209:17 | x : | | array_flow.rb:209:5:209:5 | a [element 2] : | array_flow.rb:209:17:209:17 | x : | | array_flow.rb:209:17:209:17 | x : | array_flow.rb:210:14:210:14 | x | | array_flow.rb:209:17:209:17 | x : | array_flow.rb:210:14:210:14 | x | -| array_flow.rb:215:16:215:27 | call to source : | array_flow.rb:216:9:216:9 | a [element 2] : | -| array_flow.rb:215:16:215:27 | call to source : | array_flow.rb:216:9:216:9 | a [element 2] : | -| array_flow.rb:215:30:215:41 | call to source : | array_flow.rb:216:9:216:9 | a [element 3] : | -| array_flow.rb:215:30:215:41 | call to source : | array_flow.rb:216:9:216:9 | a [element 3] : | +| array_flow.rb:215:5:215:5 | a [element 2] : | array_flow.rb:216:9:216:9 | a [element 2] : | +| array_flow.rb:215:5:215:5 | a [element 2] : | array_flow.rb:216:9:216:9 | a [element 2] : | +| array_flow.rb:215:5:215:5 | a [element 3] : | array_flow.rb:216:9:216:9 | a [element 3] : | +| array_flow.rb:215:5:215:5 | a [element 3] : | array_flow.rb:216:9:216:9 | a [element 3] : | +| array_flow.rb:215:16:215:27 | call to source : | array_flow.rb:215:5:215:5 | a [element 2] : | +| array_flow.rb:215:16:215:27 | call to source : | array_flow.rb:215:5:215:5 | a [element 2] : | +| array_flow.rb:215:30:215:41 | call to source : | array_flow.rb:215:5:215:5 | a [element 3] : | +| array_flow.rb:215:30:215:41 | call to source : | array_flow.rb:215:5:215:5 | a [element 3] : | | array_flow.rb:216:9:216:9 | a [element 2] : | array_flow.rb:216:27:216:27 | x : | | array_flow.rb:216:9:216:9 | a [element 2] : | array_flow.rb:216:27:216:27 | x : | | array_flow.rb:216:9:216:9 | a [element 2] : | array_flow.rb:216:30:216:30 | y : | @@ -390,26 +487,34 @@ edges | array_flow.rb:216:27:216:27 | x : | array_flow.rb:217:14:217:14 | x | | array_flow.rb:216:30:216:30 | y : | array_flow.rb:218:14:218:14 | y | | array_flow.rb:216:30:216:30 | y : | array_flow.rb:218:14:218:14 | y | -| array_flow.rb:231:16:231:27 | call to source : | array_flow.rb:232:9:232:9 | a [element 2] : | -| array_flow.rb:231:16:231:27 | call to source : | array_flow.rb:232:9:232:9 | a [element 2] : | +| array_flow.rb:231:5:231:5 | a [element 2] : | array_flow.rb:232:9:232:9 | a [element 2] : | +| array_flow.rb:231:5:231:5 | a [element 2] : | array_flow.rb:232:9:232:9 | a [element 2] : | +| array_flow.rb:231:16:231:27 | call to source : | array_flow.rb:231:5:231:5 | a [element 2] : | +| array_flow.rb:231:16:231:27 | call to source : | array_flow.rb:231:5:231:5 | a [element 2] : | +| array_flow.rb:232:5:232:5 | b [element] : | array_flow.rb:236:10:236:10 | b [element] : | +| array_flow.rb:232:5:232:5 | b [element] : | array_flow.rb:236:10:236:10 | b [element] : | | array_flow.rb:232:9:232:9 | a [element 2] : | array_flow.rb:232:23:232:23 | x : | | array_flow.rb:232:9:232:9 | a [element 2] : | array_flow.rb:232:23:232:23 | x : | -| array_flow.rb:232:9:235:7 | call to collect [element] : | array_flow.rb:236:10:236:10 | b [element] : | -| array_flow.rb:232:9:235:7 | call to collect [element] : | array_flow.rb:236:10:236:10 | b [element] : | +| array_flow.rb:232:9:235:7 | call to collect [element] : | array_flow.rb:232:5:232:5 | b [element] : | +| array_flow.rb:232:9:235:7 | call to collect [element] : | array_flow.rb:232:5:232:5 | b [element] : | | array_flow.rb:232:23:232:23 | x : | array_flow.rb:233:14:233:14 | x | | array_flow.rb:232:23:232:23 | x : | array_flow.rb:233:14:233:14 | x | | array_flow.rb:234:9:234:19 | call to source : | array_flow.rb:232:9:235:7 | call to collect [element] : | | array_flow.rb:234:9:234:19 | call to source : | array_flow.rb:232:9:235:7 | call to collect [element] : | | array_flow.rb:236:10:236:10 | b [element] : | array_flow.rb:236:10:236:13 | ...[...] | | array_flow.rb:236:10:236:10 | b [element] : | array_flow.rb:236:10:236:13 | ...[...] | -| array_flow.rb:240:16:240:27 | call to source : | array_flow.rb:241:9:241:9 | a [element 2] : | -| array_flow.rb:240:16:240:27 | call to source : | array_flow.rb:241:9:241:9 | a [element 2] : | +| array_flow.rb:240:5:240:5 | a [element 2] : | array_flow.rb:241:9:241:9 | a [element 2] : | +| array_flow.rb:240:5:240:5 | a [element 2] : | array_flow.rb:241:9:241:9 | a [element 2] : | +| array_flow.rb:240:16:240:27 | call to source : | array_flow.rb:240:5:240:5 | a [element 2] : | +| array_flow.rb:240:16:240:27 | call to source : | array_flow.rb:240:5:240:5 | a [element 2] : | +| array_flow.rb:241:5:241:5 | b [element] : | array_flow.rb:246:10:246:10 | b [element] : | +| array_flow.rb:241:5:241:5 | b [element] : | array_flow.rb:246:10:246:10 | b [element] : | | array_flow.rb:241:9:241:9 | [post] a [element] : | array_flow.rb:245:10:245:10 | a [element] : | | array_flow.rb:241:9:241:9 | [post] a [element] : | array_flow.rb:245:10:245:10 | a [element] : | | array_flow.rb:241:9:241:9 | a [element 2] : | array_flow.rb:241:24:241:24 | x : | | array_flow.rb:241:9:241:9 | a [element 2] : | array_flow.rb:241:24:241:24 | x : | -| array_flow.rb:241:9:244:7 | call to collect! [element] : | array_flow.rb:246:10:246:10 | b [element] : | -| array_flow.rb:241:9:244:7 | call to collect! [element] : | array_flow.rb:246:10:246:10 | b [element] : | +| array_flow.rb:241:9:244:7 | call to collect! [element] : | array_flow.rb:241:5:241:5 | b [element] : | +| array_flow.rb:241:9:244:7 | call to collect! [element] : | array_flow.rb:241:5:241:5 | b [element] : | | array_flow.rb:241:24:241:24 | x : | array_flow.rb:242:14:242:14 | x | | array_flow.rb:241:24:241:24 | x : | array_flow.rb:242:14:242:14 | x | | array_flow.rb:243:9:243:19 | call to source : | array_flow.rb:241:9:241:9 | [post] a [element] : | @@ -420,72 +525,94 @@ edges | array_flow.rb:245:10:245:10 | a [element] : | array_flow.rb:245:10:245:13 | ...[...] | | array_flow.rb:246:10:246:10 | b [element] : | array_flow.rb:246:10:246:13 | ...[...] | | array_flow.rb:246:10:246:10 | b [element] : | array_flow.rb:246:10:246:13 | ...[...] | -| array_flow.rb:250:16:250:27 | call to source : | array_flow.rb:251:9:251:9 | a [element 2] : | -| array_flow.rb:250:16:250:27 | call to source : | array_flow.rb:251:9:251:9 | a [element 2] : | -| array_flow.rb:250:16:250:27 | call to source : | array_flow.rb:256:9:256:9 | a [element 2] : | -| array_flow.rb:250:16:250:27 | call to source : | array_flow.rb:256:9:256:9 | a [element 2] : | +| array_flow.rb:250:5:250:5 | a [element 2] : | array_flow.rb:251:9:251:9 | a [element 2] : | +| array_flow.rb:250:5:250:5 | a [element 2] : | array_flow.rb:251:9:251:9 | a [element 2] : | +| array_flow.rb:250:5:250:5 | a [element 2] : | array_flow.rb:256:9:256:9 | a [element 2] : | +| array_flow.rb:250:5:250:5 | a [element 2] : | array_flow.rb:256:9:256:9 | a [element 2] : | +| array_flow.rb:250:16:250:27 | call to source : | array_flow.rb:250:5:250:5 | a [element 2] : | +| array_flow.rb:250:16:250:27 | call to source : | array_flow.rb:250:5:250:5 | a [element 2] : | +| array_flow.rb:251:5:251:5 | b [element] : | array_flow.rb:255:10:255:10 | b [element] : | +| array_flow.rb:251:5:251:5 | b [element] : | array_flow.rb:255:10:255:10 | b [element] : | | array_flow.rb:251:9:251:9 | a [element 2] : | array_flow.rb:251:9:254:7 | call to collect_concat [element] : | | array_flow.rb:251:9:251:9 | a [element 2] : | array_flow.rb:251:9:254:7 | call to collect_concat [element] : | | array_flow.rb:251:9:251:9 | a [element 2] : | array_flow.rb:251:30:251:30 | x : | | array_flow.rb:251:9:251:9 | a [element 2] : | array_flow.rb:251:30:251:30 | x : | -| array_flow.rb:251:9:254:7 | call to collect_concat [element] : | array_flow.rb:255:10:255:10 | b [element] : | -| array_flow.rb:251:9:254:7 | call to collect_concat [element] : | array_flow.rb:255:10:255:10 | b [element] : | +| array_flow.rb:251:9:254:7 | call to collect_concat [element] : | array_flow.rb:251:5:251:5 | b [element] : | +| array_flow.rb:251:9:254:7 | call to collect_concat [element] : | array_flow.rb:251:5:251:5 | b [element] : | | array_flow.rb:251:30:251:30 | x : | array_flow.rb:252:14:252:14 | x | | array_flow.rb:251:30:251:30 | x : | array_flow.rb:252:14:252:14 | x | | array_flow.rb:253:13:253:24 | call to source : | array_flow.rb:251:9:254:7 | call to collect_concat [element] : | | array_flow.rb:253:13:253:24 | call to source : | array_flow.rb:251:9:254:7 | call to collect_concat [element] : | | array_flow.rb:255:10:255:10 | b [element] : | array_flow.rb:255:10:255:13 | ...[...] | | array_flow.rb:255:10:255:10 | b [element] : | array_flow.rb:255:10:255:13 | ...[...] | +| array_flow.rb:256:5:256:5 | b [element] : | array_flow.rb:260:10:260:10 | b [element] : | +| array_flow.rb:256:5:256:5 | b [element] : | array_flow.rb:260:10:260:10 | b [element] : | | array_flow.rb:256:9:256:9 | a [element 2] : | array_flow.rb:256:30:256:30 | x : | | array_flow.rb:256:9:256:9 | a [element 2] : | array_flow.rb:256:30:256:30 | x : | -| array_flow.rb:256:9:259:7 | call to collect_concat [element] : | array_flow.rb:260:10:260:10 | b [element] : | -| array_flow.rb:256:9:259:7 | call to collect_concat [element] : | array_flow.rb:260:10:260:10 | b [element] : | +| array_flow.rb:256:9:259:7 | call to collect_concat [element] : | array_flow.rb:256:5:256:5 | b [element] : | +| array_flow.rb:256:9:259:7 | call to collect_concat [element] : | array_flow.rb:256:5:256:5 | b [element] : | | array_flow.rb:256:30:256:30 | x : | array_flow.rb:257:14:257:14 | x | | array_flow.rb:256:30:256:30 | x : | array_flow.rb:257:14:257:14 | x | | array_flow.rb:258:9:258:20 | call to source : | array_flow.rb:256:9:259:7 | call to collect_concat [element] : | | array_flow.rb:258:9:258:20 | call to source : | array_flow.rb:256:9:259:7 | call to collect_concat [element] : | | array_flow.rb:260:10:260:10 | b [element] : | array_flow.rb:260:10:260:13 | ...[...] | | array_flow.rb:260:10:260:10 | b [element] : | array_flow.rb:260:10:260:13 | ...[...] | -| array_flow.rb:264:16:264:25 | call to source : | array_flow.rb:265:9:265:9 | a [element 2] : | -| array_flow.rb:264:16:264:25 | call to source : | array_flow.rb:265:9:265:9 | a [element 2] : | +| array_flow.rb:264:5:264:5 | a [element 2] : | array_flow.rb:265:9:265:9 | a [element 2] : | +| array_flow.rb:264:5:264:5 | a [element 2] : | array_flow.rb:265:9:265:9 | a [element 2] : | +| array_flow.rb:264:16:264:25 | call to source : | array_flow.rb:264:5:264:5 | a [element 2] : | +| array_flow.rb:264:16:264:25 | call to source : | array_flow.rb:264:5:264:5 | a [element 2] : | +| array_flow.rb:265:5:265:5 | b [element 2] : | array_flow.rb:269:10:269:10 | b [element 2] : | +| array_flow.rb:265:5:265:5 | b [element 2] : | array_flow.rb:269:10:269:10 | b [element 2] : | | array_flow.rb:265:9:265:9 | a [element 2] : | array_flow.rb:265:9:267:7 | call to combination [element 2] : | | array_flow.rb:265:9:265:9 | a [element 2] : | array_flow.rb:265:9:267:7 | call to combination [element 2] : | | array_flow.rb:265:9:265:9 | a [element 2] : | array_flow.rb:265:30:265:30 | x [element] : | | array_flow.rb:265:9:265:9 | a [element 2] : | array_flow.rb:265:30:265:30 | x [element] : | -| array_flow.rb:265:9:267:7 | call to combination [element 2] : | array_flow.rb:269:10:269:10 | b [element 2] : | -| array_flow.rb:265:9:267:7 | call to combination [element 2] : | array_flow.rb:269:10:269:10 | b [element 2] : | +| array_flow.rb:265:9:267:7 | call to combination [element 2] : | array_flow.rb:265:5:265:5 | b [element 2] : | +| array_flow.rb:265:9:267:7 | call to combination [element 2] : | array_flow.rb:265:5:265:5 | b [element 2] : | | array_flow.rb:265:30:265:30 | x [element] : | array_flow.rb:266:14:266:14 | x [element] : | | array_flow.rb:265:30:265:30 | x [element] : | array_flow.rb:266:14:266:14 | x [element] : | | array_flow.rb:266:14:266:14 | x [element] : | array_flow.rb:266:14:266:17 | ...[...] | | array_flow.rb:266:14:266:14 | x [element] : | array_flow.rb:266:14:266:17 | ...[...] | | array_flow.rb:269:10:269:10 | b [element 2] : | array_flow.rb:269:10:269:13 | ...[...] | | array_flow.rb:269:10:269:10 | b [element 2] : | array_flow.rb:269:10:269:13 | ...[...] | -| array_flow.rb:273:16:273:25 | call to source : | array_flow.rb:274:9:274:9 | a [element 2] : | -| array_flow.rb:273:16:273:25 | call to source : | array_flow.rb:274:9:274:9 | a [element 2] : | +| array_flow.rb:273:5:273:5 | a [element 2] : | array_flow.rb:274:9:274:9 | a [element 2] : | +| array_flow.rb:273:5:273:5 | a [element 2] : | array_flow.rb:274:9:274:9 | a [element 2] : | +| array_flow.rb:273:16:273:25 | call to source : | array_flow.rb:273:5:273:5 | a [element 2] : | +| array_flow.rb:273:16:273:25 | call to source : | array_flow.rb:273:5:273:5 | a [element 2] : | +| array_flow.rb:274:5:274:5 | b [element] : | array_flow.rb:275:10:275:10 | b [element] : | +| array_flow.rb:274:5:274:5 | b [element] : | array_flow.rb:275:10:275:10 | b [element] : | | array_flow.rb:274:9:274:9 | a [element 2] : | array_flow.rb:274:9:274:17 | call to compact [element] : | | array_flow.rb:274:9:274:9 | a [element 2] : | array_flow.rb:274:9:274:17 | call to compact [element] : | -| array_flow.rb:274:9:274:17 | call to compact [element] : | array_flow.rb:275:10:275:10 | b [element] : | -| array_flow.rb:274:9:274:17 | call to compact [element] : | array_flow.rb:275:10:275:10 | b [element] : | +| array_flow.rb:274:9:274:17 | call to compact [element] : | array_flow.rb:274:5:274:5 | b [element] : | +| array_flow.rb:274:9:274:17 | call to compact [element] : | array_flow.rb:274:5:274:5 | b [element] : | | array_flow.rb:275:10:275:10 | b [element] : | array_flow.rb:275:10:275:13 | ...[...] | | array_flow.rb:275:10:275:10 | b [element] : | array_flow.rb:275:10:275:13 | ...[...] | -| array_flow.rb:279:16:279:25 | call to source : | array_flow.rb:280:9:280:9 | a [element 2] : | -| array_flow.rb:279:16:279:25 | call to source : | array_flow.rb:280:9:280:9 | a [element 2] : | +| array_flow.rb:279:5:279:5 | a [element 2] : | array_flow.rb:280:9:280:9 | a [element 2] : | +| array_flow.rb:279:5:279:5 | a [element 2] : | array_flow.rb:280:9:280:9 | a [element 2] : | +| array_flow.rb:279:16:279:25 | call to source : | array_flow.rb:279:5:279:5 | a [element 2] : | +| array_flow.rb:279:16:279:25 | call to source : | array_flow.rb:279:5:279:5 | a [element 2] : | +| array_flow.rb:280:5:280:5 | b [element] : | array_flow.rb:282:10:282:10 | b [element] : | +| array_flow.rb:280:5:280:5 | b [element] : | array_flow.rb:282:10:282:10 | b [element] : | | array_flow.rb:280:9:280:9 | [post] a [element] : | array_flow.rb:281:10:281:10 | a [element] : | | array_flow.rb:280:9:280:9 | [post] a [element] : | array_flow.rb:281:10:281:10 | a [element] : | | array_flow.rb:280:9:280:9 | a [element 2] : | array_flow.rb:280:9:280:9 | [post] a [element] : | | array_flow.rb:280:9:280:9 | a [element 2] : | array_flow.rb:280:9:280:9 | [post] a [element] : | | array_flow.rb:280:9:280:9 | a [element 2] : | array_flow.rb:280:9:280:18 | call to compact! [element] : | | array_flow.rb:280:9:280:9 | a [element 2] : | array_flow.rb:280:9:280:18 | call to compact! [element] : | -| array_flow.rb:280:9:280:18 | call to compact! [element] : | array_flow.rb:282:10:282:10 | b [element] : | -| array_flow.rb:280:9:280:18 | call to compact! [element] : | array_flow.rb:282:10:282:10 | b [element] : | +| array_flow.rb:280:9:280:18 | call to compact! [element] : | array_flow.rb:280:5:280:5 | b [element] : | +| array_flow.rb:280:9:280:18 | call to compact! [element] : | array_flow.rb:280:5:280:5 | b [element] : | | array_flow.rb:281:10:281:10 | a [element] : | array_flow.rb:281:10:281:13 | ...[...] | | array_flow.rb:281:10:281:10 | a [element] : | array_flow.rb:281:10:281:13 | ...[...] | | array_flow.rb:282:10:282:10 | b [element] : | array_flow.rb:282:10:282:13 | ...[...] | | array_flow.rb:282:10:282:10 | b [element] : | array_flow.rb:282:10:282:13 | ...[...] | -| array_flow.rb:286:16:286:27 | call to source : | array_flow.rb:290:10:290:10 | a [element 2] : | -| array_flow.rb:286:16:286:27 | call to source : | array_flow.rb:290:10:290:10 | a [element 2] : | -| array_flow.rb:287:16:287:27 | call to source : | array_flow.rb:288:14:288:14 | b [element 2] : | -| array_flow.rb:287:16:287:27 | call to source : | array_flow.rb:288:14:288:14 | b [element 2] : | +| array_flow.rb:286:5:286:5 | a [element 2] : | array_flow.rb:290:10:290:10 | a [element 2] : | +| array_flow.rb:286:5:286:5 | a [element 2] : | array_flow.rb:290:10:290:10 | a [element 2] : | +| array_flow.rb:286:16:286:27 | call to source : | array_flow.rb:286:5:286:5 | a [element 2] : | +| array_flow.rb:286:16:286:27 | call to source : | array_flow.rb:286:5:286:5 | a [element 2] : | +| array_flow.rb:287:5:287:5 | b [element 2] : | array_flow.rb:288:14:288:14 | b [element 2] : | +| array_flow.rb:287:5:287:5 | b [element 2] : | array_flow.rb:288:14:288:14 | b [element 2] : | +| array_flow.rb:287:16:287:27 | call to source : | array_flow.rb:287:5:287:5 | b [element 2] : | +| array_flow.rb:287:16:287:27 | call to source : | array_flow.rb:287:5:287:5 | b [element 2] : | | array_flow.rb:288:5:288:5 | [post] a [element] : | array_flow.rb:289:10:289:10 | a [element] : | | array_flow.rb:288:5:288:5 | [post] a [element] : | array_flow.rb:289:10:289:10 | a [element] : | | array_flow.rb:288:5:288:5 | [post] a [element] : | array_flow.rb:290:10:290:10 | a [element] : | @@ -498,52 +625,76 @@ edges | array_flow.rb:290:10:290:10 | a [element 2] : | array_flow.rb:290:10:290:13 | ...[...] | | array_flow.rb:290:10:290:10 | a [element] : | array_flow.rb:290:10:290:13 | ...[...] | | array_flow.rb:290:10:290:10 | a [element] : | array_flow.rb:290:10:290:13 | ...[...] | -| array_flow.rb:294:16:294:25 | call to source : | array_flow.rb:295:5:295:5 | a [element 2] : | -| array_flow.rb:294:16:294:25 | call to source : | array_flow.rb:295:5:295:5 | a [element 2] : | +| array_flow.rb:294:5:294:5 | a [element 2] : | array_flow.rb:295:5:295:5 | a [element 2] : | +| array_flow.rb:294:5:294:5 | a [element 2] : | array_flow.rb:295:5:295:5 | a [element 2] : | +| array_flow.rb:294:16:294:25 | call to source : | array_flow.rb:294:5:294:5 | a [element 2] : | +| array_flow.rb:294:16:294:25 | call to source : | array_flow.rb:294:5:294:5 | a [element 2] : | | array_flow.rb:295:5:295:5 | a [element 2] : | array_flow.rb:295:17:295:17 | x : | | array_flow.rb:295:5:295:5 | a [element 2] : | array_flow.rb:295:17:295:17 | x : | | array_flow.rb:295:17:295:17 | x : | array_flow.rb:296:14:296:14 | x | | array_flow.rb:295:17:295:17 | x : | array_flow.rb:296:14:296:14 | x | -| array_flow.rb:301:16:301:25 | call to source : | array_flow.rb:302:5:302:5 | a [element 2] : | -| array_flow.rb:301:16:301:25 | call to source : | array_flow.rb:302:5:302:5 | a [element 2] : | +| array_flow.rb:301:5:301:5 | a [element 2] : | array_flow.rb:302:5:302:5 | a [element 2] : | +| array_flow.rb:301:5:301:5 | a [element 2] : | array_flow.rb:302:5:302:5 | a [element 2] : | +| array_flow.rb:301:16:301:25 | call to source : | array_flow.rb:301:5:301:5 | a [element 2] : | +| array_flow.rb:301:16:301:25 | call to source : | array_flow.rb:301:5:301:5 | a [element 2] : | | array_flow.rb:302:5:302:5 | a [element 2] : | array_flow.rb:302:20:302:20 | x : | | array_flow.rb:302:5:302:5 | a [element 2] : | array_flow.rb:302:20:302:20 | x : | | array_flow.rb:302:20:302:20 | x : | array_flow.rb:303:14:303:14 | x | | array_flow.rb:302:20:302:20 | x : | array_flow.rb:303:14:303:14 | x | -| array_flow.rb:308:16:308:25 | call to source : | array_flow.rb:309:9:309:9 | a [element 2] : | -| array_flow.rb:308:16:308:25 | call to source : | array_flow.rb:309:9:309:9 | a [element 2] : | +| array_flow.rb:308:5:308:5 | a [element 2] : | array_flow.rb:309:9:309:9 | a [element 2] : | +| array_flow.rb:308:5:308:5 | a [element 2] : | array_flow.rb:309:9:309:9 | a [element 2] : | +| array_flow.rb:308:16:308:25 | call to source : | array_flow.rb:308:5:308:5 | a [element 2] : | +| array_flow.rb:308:16:308:25 | call to source : | array_flow.rb:308:5:308:5 | a [element 2] : | +| array_flow.rb:309:5:309:5 | b [element 2] : | array_flow.rb:312:10:312:10 | b [element 2] : | +| array_flow.rb:309:5:309:5 | b [element 2] : | array_flow.rb:312:10:312:10 | b [element 2] : | | array_flow.rb:309:9:309:9 | a [element 2] : | array_flow.rb:309:9:309:21 | call to deconstruct [element 2] : | | array_flow.rb:309:9:309:9 | a [element 2] : | array_flow.rb:309:9:309:21 | call to deconstruct [element 2] : | -| array_flow.rb:309:9:309:21 | call to deconstruct [element 2] : | array_flow.rb:312:10:312:10 | b [element 2] : | -| array_flow.rb:309:9:309:21 | call to deconstruct [element 2] : | array_flow.rb:312:10:312:10 | b [element 2] : | +| array_flow.rb:309:9:309:21 | call to deconstruct [element 2] : | array_flow.rb:309:5:309:5 | b [element 2] : | +| array_flow.rb:309:9:309:21 | call to deconstruct [element 2] : | array_flow.rb:309:5:309:5 | b [element 2] : | | array_flow.rb:312:10:312:10 | b [element 2] : | array_flow.rb:312:10:312:13 | ...[...] | | array_flow.rb:312:10:312:10 | b [element 2] : | array_flow.rb:312:10:312:13 | ...[...] | -| array_flow.rb:316:16:316:27 | call to source : | array_flow.rb:317:9:317:9 | a [element 2] : | -| array_flow.rb:316:16:316:27 | call to source : | array_flow.rb:317:9:317:9 | a [element 2] : | +| array_flow.rb:316:5:316:5 | a [element 2] : | array_flow.rb:317:9:317:9 | a [element 2] : | +| array_flow.rb:316:5:316:5 | a [element 2] : | array_flow.rb:317:9:317:9 | a [element 2] : | +| array_flow.rb:316:16:316:27 | call to source : | array_flow.rb:316:5:316:5 | a [element 2] : | +| array_flow.rb:316:16:316:27 | call to source : | array_flow.rb:316:5:316:5 | a [element 2] : | +| array_flow.rb:317:5:317:5 | b : | array_flow.rb:318:10:318:10 | b | +| array_flow.rb:317:5:317:5 | b : | array_flow.rb:318:10:318:10 | b | | array_flow.rb:317:9:317:9 | a [element 2] : | array_flow.rb:317:9:317:36 | call to delete : | | array_flow.rb:317:9:317:9 | a [element 2] : | array_flow.rb:317:9:317:36 | call to delete : | -| array_flow.rb:317:9:317:36 | call to delete : | array_flow.rb:318:10:318:10 | b | -| array_flow.rb:317:9:317:36 | call to delete : | array_flow.rb:318:10:318:10 | b | +| array_flow.rb:317:9:317:36 | call to delete : | array_flow.rb:317:5:317:5 | b : | +| array_flow.rb:317:9:317:36 | call to delete : | array_flow.rb:317:5:317:5 | b : | | array_flow.rb:317:23:317:34 | call to source : | array_flow.rb:317:9:317:36 | call to delete : | | array_flow.rb:317:23:317:34 | call to source : | array_flow.rb:317:9:317:36 | call to delete : | -| array_flow.rb:325:16:325:27 | call to source : | array_flow.rb:326:9:326:9 | a [element 2] : | -| array_flow.rb:325:16:325:27 | call to source : | array_flow.rb:326:9:326:9 | a [element 2] : | -| array_flow.rb:325:30:325:41 | call to source : | array_flow.rb:326:9:326:9 | a [element 3] : | -| array_flow.rb:325:30:325:41 | call to source : | array_flow.rb:326:9:326:9 | a [element 3] : | +| array_flow.rb:325:5:325:5 | a [element 2] : | array_flow.rb:326:9:326:9 | a [element 2] : | +| array_flow.rb:325:5:325:5 | a [element 2] : | array_flow.rb:326:9:326:9 | a [element 2] : | +| array_flow.rb:325:5:325:5 | a [element 3] : | array_flow.rb:326:9:326:9 | a [element 3] : | +| array_flow.rb:325:5:325:5 | a [element 3] : | array_flow.rb:326:9:326:9 | a [element 3] : | +| array_flow.rb:325:16:325:27 | call to source : | array_flow.rb:325:5:325:5 | a [element 2] : | +| array_flow.rb:325:16:325:27 | call to source : | array_flow.rb:325:5:325:5 | a [element 2] : | +| array_flow.rb:325:30:325:41 | call to source : | array_flow.rb:325:5:325:5 | a [element 3] : | +| array_flow.rb:325:30:325:41 | call to source : | array_flow.rb:325:5:325:5 | a [element 3] : | +| array_flow.rb:326:5:326:5 | b : | array_flow.rb:327:10:327:10 | b | +| array_flow.rb:326:5:326:5 | b : | array_flow.rb:327:10:327:10 | b | | array_flow.rb:326:9:326:9 | [post] a [element 2] : | array_flow.rb:328:10:328:10 | a [element 2] : | | array_flow.rb:326:9:326:9 | [post] a [element 2] : | array_flow.rb:328:10:328:10 | a [element 2] : | | array_flow.rb:326:9:326:9 | a [element 2] : | array_flow.rb:326:9:326:22 | call to delete_at : | | array_flow.rb:326:9:326:9 | a [element 2] : | array_flow.rb:326:9:326:22 | call to delete_at : | | array_flow.rb:326:9:326:9 | a [element 3] : | array_flow.rb:326:9:326:9 | [post] a [element 2] : | | array_flow.rb:326:9:326:9 | a [element 3] : | array_flow.rb:326:9:326:9 | [post] a [element 2] : | -| array_flow.rb:326:9:326:22 | call to delete_at : | array_flow.rb:327:10:327:10 | b | -| array_flow.rb:326:9:326:22 | call to delete_at : | array_flow.rb:327:10:327:10 | b | +| array_flow.rb:326:9:326:22 | call to delete_at : | array_flow.rb:326:5:326:5 | b : | +| array_flow.rb:326:9:326:22 | call to delete_at : | array_flow.rb:326:5:326:5 | b : | | array_flow.rb:328:10:328:10 | a [element 2] : | array_flow.rb:328:10:328:13 | ...[...] | | array_flow.rb:328:10:328:10 | a [element 2] : | array_flow.rb:328:10:328:13 | ...[...] | -| array_flow.rb:330:16:330:27 | call to source : | array_flow.rb:331:9:331:9 | a [element 2] : | -| array_flow.rb:330:16:330:27 | call to source : | array_flow.rb:331:9:331:9 | a [element 2] : | -| array_flow.rb:330:30:330:41 | call to source : | array_flow.rb:331:9:331:9 | a [element 3] : | -| array_flow.rb:330:30:330:41 | call to source : | array_flow.rb:331:9:331:9 | a [element 3] : | +| array_flow.rb:330:5:330:5 | a [element 2] : | array_flow.rb:331:9:331:9 | a [element 2] : | +| array_flow.rb:330:5:330:5 | a [element 2] : | array_flow.rb:331:9:331:9 | a [element 2] : | +| array_flow.rb:330:5:330:5 | a [element 3] : | array_flow.rb:331:9:331:9 | a [element 3] : | +| array_flow.rb:330:5:330:5 | a [element 3] : | array_flow.rb:331:9:331:9 | a [element 3] : | +| array_flow.rb:330:16:330:27 | call to source : | array_flow.rb:330:5:330:5 | a [element 2] : | +| array_flow.rb:330:16:330:27 | call to source : | array_flow.rb:330:5:330:5 | a [element 2] : | +| array_flow.rb:330:30:330:41 | call to source : | array_flow.rb:330:5:330:5 | a [element 3] : | +| array_flow.rb:330:30:330:41 | call to source : | array_flow.rb:330:5:330:5 | a [element 3] : | +| array_flow.rb:331:5:331:5 | b : | array_flow.rb:332:10:332:10 | b | +| array_flow.rb:331:5:331:5 | b : | array_flow.rb:332:10:332:10 | b | | array_flow.rb:331:9:331:9 | [post] a [element] : | array_flow.rb:333:10:333:10 | a [element] : | | array_flow.rb:331:9:331:9 | [post] a [element] : | array_flow.rb:333:10:333:10 | a [element] : | | array_flow.rb:331:9:331:9 | [post] a [element] : | array_flow.rb:334:10:334:10 | a [element] : | @@ -556,14 +707,18 @@ edges | array_flow.rb:331:9:331:9 | a [element 3] : | array_flow.rb:331:9:331:9 | [post] a [element] : | | array_flow.rb:331:9:331:9 | a [element 3] : | array_flow.rb:331:9:331:22 | call to delete_at : | | array_flow.rb:331:9:331:9 | a [element 3] : | array_flow.rb:331:9:331:22 | call to delete_at : | -| array_flow.rb:331:9:331:22 | call to delete_at : | array_flow.rb:332:10:332:10 | b | -| array_flow.rb:331:9:331:22 | call to delete_at : | array_flow.rb:332:10:332:10 | b | +| array_flow.rb:331:9:331:22 | call to delete_at : | array_flow.rb:331:5:331:5 | b : | +| array_flow.rb:331:9:331:22 | call to delete_at : | array_flow.rb:331:5:331:5 | b : | | array_flow.rb:333:10:333:10 | a [element] : | array_flow.rb:333:10:333:13 | ...[...] | | array_flow.rb:333:10:333:10 | a [element] : | array_flow.rb:333:10:333:13 | ...[...] | | array_flow.rb:334:10:334:10 | a [element] : | array_flow.rb:334:10:334:13 | ...[...] | | array_flow.rb:334:10:334:10 | a [element] : | array_flow.rb:334:10:334:13 | ...[...] | -| array_flow.rb:338:16:338:25 | call to source : | array_flow.rb:339:9:339:9 | a [element 2] : | -| array_flow.rb:338:16:338:25 | call to source : | array_flow.rb:339:9:339:9 | a [element 2] : | +| array_flow.rb:338:5:338:5 | a [element 2] : | array_flow.rb:339:9:339:9 | a [element 2] : | +| array_flow.rb:338:5:338:5 | a [element 2] : | array_flow.rb:339:9:339:9 | a [element 2] : | +| array_flow.rb:338:16:338:25 | call to source : | array_flow.rb:338:5:338:5 | a [element 2] : | +| array_flow.rb:338:16:338:25 | call to source : | array_flow.rb:338:5:338:5 | a [element 2] : | +| array_flow.rb:339:5:339:5 | b [element] : | array_flow.rb:342:10:342:10 | b [element] : | +| array_flow.rb:339:5:339:5 | b [element] : | array_flow.rb:342:10:342:10 | b [element] : | | array_flow.rb:339:9:339:9 | [post] a [element] : | array_flow.rb:343:10:343:10 | a [element] : | | array_flow.rb:339:9:339:9 | [post] a [element] : | array_flow.rb:343:10:343:10 | a [element] : | | array_flow.rb:339:9:339:9 | [post] a [element] : | array_flow.rb:344:10:344:10 | a [element] : | @@ -576,8 +731,8 @@ edges | array_flow.rb:339:9:339:9 | a [element 2] : | array_flow.rb:339:9:341:7 | call to delete_if [element] : | | array_flow.rb:339:9:339:9 | a [element 2] : | array_flow.rb:339:25:339:25 | x : | | array_flow.rb:339:9:339:9 | a [element 2] : | array_flow.rb:339:25:339:25 | x : | -| array_flow.rb:339:9:341:7 | call to delete_if [element] : | array_flow.rb:342:10:342:10 | b [element] : | -| array_flow.rb:339:9:341:7 | call to delete_if [element] : | array_flow.rb:342:10:342:10 | b [element] : | +| array_flow.rb:339:9:341:7 | call to delete_if [element] : | array_flow.rb:339:5:339:5 | b [element] : | +| array_flow.rb:339:9:341:7 | call to delete_if [element] : | array_flow.rb:339:5:339:5 | b [element] : | | array_flow.rb:339:25:339:25 | x : | array_flow.rb:340:14:340:14 | x | | array_flow.rb:339:25:339:25 | x : | array_flow.rb:340:14:340:14 | x | | array_flow.rb:342:10:342:10 | b [element] : | array_flow.rb:342:10:342:13 | ...[...] | @@ -588,66 +743,88 @@ edges | array_flow.rb:344:10:344:10 | a [element] : | array_flow.rb:344:10:344:13 | ...[...] | | array_flow.rb:345:10:345:10 | a [element] : | array_flow.rb:345:10:345:13 | ...[...] | | array_flow.rb:345:10:345:10 | a [element] : | array_flow.rb:345:10:345:13 | ...[...] | -| array_flow.rb:349:16:349:25 | call to source : | array_flow.rb:350:9:350:9 | a [element 2] : | -| array_flow.rb:349:16:349:25 | call to source : | array_flow.rb:350:9:350:9 | a [element 2] : | +| array_flow.rb:349:5:349:5 | a [element 2] : | array_flow.rb:350:9:350:9 | a [element 2] : | +| array_flow.rb:349:5:349:5 | a [element 2] : | array_flow.rb:350:9:350:9 | a [element 2] : | +| array_flow.rb:349:16:349:25 | call to source : | array_flow.rb:349:5:349:5 | a [element 2] : | +| array_flow.rb:349:16:349:25 | call to source : | array_flow.rb:349:5:349:5 | a [element 2] : | +| array_flow.rb:350:5:350:5 | b [element] : | array_flow.rb:351:10:351:10 | b [element] : | +| array_flow.rb:350:5:350:5 | b [element] : | array_flow.rb:351:10:351:10 | b [element] : | | array_flow.rb:350:9:350:9 | a [element 2] : | array_flow.rb:350:9:350:25 | call to difference [element] : | | array_flow.rb:350:9:350:9 | a [element 2] : | array_flow.rb:350:9:350:25 | call to difference [element] : | -| array_flow.rb:350:9:350:25 | call to difference [element] : | array_flow.rb:351:10:351:10 | b [element] : | -| array_flow.rb:350:9:350:25 | call to difference [element] : | array_flow.rb:351:10:351:10 | b [element] : | +| array_flow.rb:350:9:350:25 | call to difference [element] : | array_flow.rb:350:5:350:5 | b [element] : | +| array_flow.rb:350:9:350:25 | call to difference [element] : | array_flow.rb:350:5:350:5 | b [element] : | | array_flow.rb:351:10:351:10 | b [element] : | array_flow.rb:351:10:351:13 | ...[...] | | array_flow.rb:351:10:351:10 | b [element] : | array_flow.rb:351:10:351:13 | ...[...] | -| array_flow.rb:355:16:355:27 | call to source : | array_flow.rb:357:10:357:10 | a [element 2] : | -| array_flow.rb:355:16:355:27 | call to source : | array_flow.rb:357:10:357:10 | a [element 2] : | -| array_flow.rb:355:16:355:27 | call to source : | array_flow.rb:358:10:358:10 | a [element 2] : | -| array_flow.rb:355:16:355:27 | call to source : | array_flow.rb:358:10:358:10 | a [element 2] : | -| array_flow.rb:355:34:355:45 | call to source : | array_flow.rb:360:10:360:10 | a [element 3, element 1] : | -| array_flow.rb:355:34:355:45 | call to source : | array_flow.rb:360:10:360:10 | a [element 3, element 1] : | +| array_flow.rb:355:5:355:5 | a [element 2] : | array_flow.rb:357:10:357:10 | a [element 2] : | +| array_flow.rb:355:5:355:5 | a [element 2] : | array_flow.rb:357:10:357:10 | a [element 2] : | +| array_flow.rb:355:5:355:5 | a [element 2] : | array_flow.rb:358:10:358:10 | a [element 2] : | +| array_flow.rb:355:5:355:5 | a [element 2] : | array_flow.rb:358:10:358:10 | a [element 2] : | +| array_flow.rb:355:5:355:5 | a [element 3, element 1] : | array_flow.rb:360:10:360:10 | a [element 3, element 1] : | +| array_flow.rb:355:5:355:5 | a [element 3, element 1] : | array_flow.rb:360:10:360:10 | a [element 3, element 1] : | +| array_flow.rb:355:16:355:27 | call to source : | array_flow.rb:355:5:355:5 | a [element 2] : | +| array_flow.rb:355:16:355:27 | call to source : | array_flow.rb:355:5:355:5 | a [element 2] : | +| array_flow.rb:355:34:355:45 | call to source : | array_flow.rb:355:5:355:5 | a [element 3, element 1] : | +| array_flow.rb:355:34:355:45 | call to source : | array_flow.rb:355:5:355:5 | a [element 3, element 1] : | | array_flow.rb:357:10:357:10 | a [element 2] : | array_flow.rb:357:10:357:17 | call to dig | | array_flow.rb:357:10:357:10 | a [element 2] : | array_flow.rb:357:10:357:17 | call to dig | | array_flow.rb:358:10:358:10 | a [element 2] : | array_flow.rb:358:10:358:17 | call to dig | | array_flow.rb:358:10:358:10 | a [element 2] : | array_flow.rb:358:10:358:17 | call to dig | | array_flow.rb:360:10:360:10 | a [element 3, element 1] : | array_flow.rb:360:10:360:19 | call to dig | | array_flow.rb:360:10:360:10 | a [element 3, element 1] : | array_flow.rb:360:10:360:19 | call to dig | -| array_flow.rb:364:16:364:27 | call to source : | array_flow.rb:365:9:365:9 | a [element 2] : | -| array_flow.rb:364:16:364:27 | call to source : | array_flow.rb:365:9:365:9 | a [element 2] : | +| array_flow.rb:364:5:364:5 | a [element 2] : | array_flow.rb:365:9:365:9 | a [element 2] : | +| array_flow.rb:364:5:364:5 | a [element 2] : | array_flow.rb:365:9:365:9 | a [element 2] : | +| array_flow.rb:364:16:364:27 | call to source : | array_flow.rb:364:5:364:5 | a [element 2] : | +| array_flow.rb:364:16:364:27 | call to source : | array_flow.rb:364:5:364:5 | a [element 2] : | +| array_flow.rb:365:5:365:5 | b : | array_flow.rb:368:10:368:10 | b | +| array_flow.rb:365:5:365:5 | b : | array_flow.rb:368:10:368:10 | b | | array_flow.rb:365:9:365:9 | a [element 2] : | array_flow.rb:365:9:367:7 | call to detect : | | array_flow.rb:365:9:365:9 | a [element 2] : | array_flow.rb:365:9:367:7 | call to detect : | | array_flow.rb:365:9:365:9 | a [element 2] : | array_flow.rb:365:43:365:43 | x : | | array_flow.rb:365:9:365:9 | a [element 2] : | array_flow.rb:365:43:365:43 | x : | -| array_flow.rb:365:9:367:7 | call to detect : | array_flow.rb:368:10:368:10 | b | -| array_flow.rb:365:9:367:7 | call to detect : | array_flow.rb:368:10:368:10 | b | +| array_flow.rb:365:9:367:7 | call to detect : | array_flow.rb:365:5:365:5 | b : | +| array_flow.rb:365:9:367:7 | call to detect : | array_flow.rb:365:5:365:5 | b : | | array_flow.rb:365:23:365:34 | call to source : | array_flow.rb:365:9:367:7 | call to detect : | | array_flow.rb:365:23:365:34 | call to source : | array_flow.rb:365:9:367:7 | call to detect : | | array_flow.rb:365:43:365:43 | x : | array_flow.rb:366:14:366:14 | x | | array_flow.rb:365:43:365:43 | x : | array_flow.rb:366:14:366:14 | x | -| array_flow.rb:372:16:372:27 | call to source : | array_flow.rb:373:9:373:9 | a [element 2] : | -| array_flow.rb:372:16:372:27 | call to source : | array_flow.rb:373:9:373:9 | a [element 2] : | -| array_flow.rb:372:16:372:27 | call to source : | array_flow.rb:375:9:375:9 | a [element 2] : | -| array_flow.rb:372:16:372:27 | call to source : | array_flow.rb:375:9:375:9 | a [element 2] : | -| array_flow.rb:372:16:372:27 | call to source : | array_flow.rb:380:9:380:9 | a [element 2] : | -| array_flow.rb:372:16:372:27 | call to source : | array_flow.rb:380:9:380:9 | a [element 2] : | -| array_flow.rb:372:30:372:41 | call to source : | array_flow.rb:373:9:373:9 | a [element 3] : | -| array_flow.rb:372:30:372:41 | call to source : | array_flow.rb:373:9:373:9 | a [element 3] : | -| array_flow.rb:372:30:372:41 | call to source : | array_flow.rb:375:9:375:9 | a [element 3] : | -| array_flow.rb:372:30:372:41 | call to source : | array_flow.rb:375:9:375:9 | a [element 3] : | +| array_flow.rb:372:5:372:5 | a [element 2] : | array_flow.rb:373:9:373:9 | a [element 2] : | +| array_flow.rb:372:5:372:5 | a [element 2] : | array_flow.rb:373:9:373:9 | a [element 2] : | +| array_flow.rb:372:5:372:5 | a [element 2] : | array_flow.rb:375:9:375:9 | a [element 2] : | +| array_flow.rb:372:5:372:5 | a [element 2] : | array_flow.rb:375:9:375:9 | a [element 2] : | +| array_flow.rb:372:5:372:5 | a [element 2] : | array_flow.rb:380:9:380:9 | a [element 2] : | +| array_flow.rb:372:5:372:5 | a [element 2] : | array_flow.rb:380:9:380:9 | a [element 2] : | +| array_flow.rb:372:5:372:5 | a [element 3] : | array_flow.rb:373:9:373:9 | a [element 3] : | +| array_flow.rb:372:5:372:5 | a [element 3] : | array_flow.rb:373:9:373:9 | a [element 3] : | +| array_flow.rb:372:5:372:5 | a [element 3] : | array_flow.rb:375:9:375:9 | a [element 3] : | +| array_flow.rb:372:5:372:5 | a [element 3] : | array_flow.rb:375:9:375:9 | a [element 3] : | +| array_flow.rb:372:16:372:27 | call to source : | array_flow.rb:372:5:372:5 | a [element 2] : | +| array_flow.rb:372:16:372:27 | call to source : | array_flow.rb:372:5:372:5 | a [element 2] : | +| array_flow.rb:372:30:372:41 | call to source : | array_flow.rb:372:5:372:5 | a [element 3] : | +| array_flow.rb:372:30:372:41 | call to source : | array_flow.rb:372:5:372:5 | a [element 3] : | +| array_flow.rb:373:5:373:5 | b [element] : | array_flow.rb:374:10:374:10 | b [element] : | +| array_flow.rb:373:5:373:5 | b [element] : | array_flow.rb:374:10:374:10 | b [element] : | | array_flow.rb:373:9:373:9 | a [element 2] : | array_flow.rb:373:9:373:17 | call to drop [element] : | | array_flow.rb:373:9:373:9 | a [element 2] : | array_flow.rb:373:9:373:17 | call to drop [element] : | | array_flow.rb:373:9:373:9 | a [element 3] : | array_flow.rb:373:9:373:17 | call to drop [element] : | | array_flow.rb:373:9:373:9 | a [element 3] : | array_flow.rb:373:9:373:17 | call to drop [element] : | -| array_flow.rb:373:9:373:17 | call to drop [element] : | array_flow.rb:374:10:374:10 | b [element] : | -| array_flow.rb:373:9:373:17 | call to drop [element] : | array_flow.rb:374:10:374:10 | b [element] : | +| array_flow.rb:373:9:373:17 | call to drop [element] : | array_flow.rb:373:5:373:5 | b [element] : | +| array_flow.rb:373:9:373:17 | call to drop [element] : | array_flow.rb:373:5:373:5 | b [element] : | | array_flow.rb:374:10:374:10 | b [element] : | array_flow.rb:374:10:374:13 | ...[...] | | array_flow.rb:374:10:374:10 | b [element] : | array_flow.rb:374:10:374:13 | ...[...] | +| array_flow.rb:375:5:375:5 | b [element 1] : | array_flow.rb:377:10:377:10 | b [element 1] : | +| array_flow.rb:375:5:375:5 | b [element 1] : | array_flow.rb:377:10:377:10 | b [element 1] : | +| array_flow.rb:375:5:375:5 | b [element 1] : | array_flow.rb:378:10:378:10 | b [element 1] : | +| array_flow.rb:375:5:375:5 | b [element 1] : | array_flow.rb:378:10:378:10 | b [element 1] : | +| array_flow.rb:375:5:375:5 | b [element 2] : | array_flow.rb:378:10:378:10 | b [element 2] : | +| array_flow.rb:375:5:375:5 | b [element 2] : | array_flow.rb:378:10:378:10 | b [element 2] : | | array_flow.rb:375:9:375:9 | a [element 2] : | array_flow.rb:375:9:375:17 | call to drop [element 1] : | | array_flow.rb:375:9:375:9 | a [element 2] : | array_flow.rb:375:9:375:17 | call to drop [element 1] : | | array_flow.rb:375:9:375:9 | a [element 3] : | array_flow.rb:375:9:375:17 | call to drop [element 2] : | | array_flow.rb:375:9:375:9 | a [element 3] : | array_flow.rb:375:9:375:17 | call to drop [element 2] : | -| array_flow.rb:375:9:375:17 | call to drop [element 1] : | array_flow.rb:377:10:377:10 | b [element 1] : | -| array_flow.rb:375:9:375:17 | call to drop [element 1] : | array_flow.rb:377:10:377:10 | b [element 1] : | -| array_flow.rb:375:9:375:17 | call to drop [element 1] : | array_flow.rb:378:10:378:10 | b [element 1] : | -| array_flow.rb:375:9:375:17 | call to drop [element 1] : | array_flow.rb:378:10:378:10 | b [element 1] : | -| array_flow.rb:375:9:375:17 | call to drop [element 2] : | array_flow.rb:378:10:378:10 | b [element 2] : | -| array_flow.rb:375:9:375:17 | call to drop [element 2] : | array_flow.rb:378:10:378:10 | b [element 2] : | +| array_flow.rb:375:9:375:17 | call to drop [element 1] : | array_flow.rb:375:5:375:5 | b [element 1] : | +| array_flow.rb:375:9:375:17 | call to drop [element 1] : | array_flow.rb:375:5:375:5 | b [element 1] : | +| array_flow.rb:375:9:375:17 | call to drop [element 2] : | array_flow.rb:375:5:375:5 | b [element 2] : | +| array_flow.rb:375:9:375:17 | call to drop [element 2] : | array_flow.rb:375:5:375:5 | b [element 2] : | | array_flow.rb:377:10:377:10 | b [element 1] : | array_flow.rb:377:10:377:13 | ...[...] | | array_flow.rb:377:10:377:10 | b [element 1] : | array_flow.rb:377:10:377:13 | ...[...] | | array_flow.rb:378:10:378:10 | b [element 1] : | array_flow.rb:378:10:378:13 | ...[...] | @@ -658,30 +835,42 @@ edges | array_flow.rb:379:5:379:5 | [post] a [element] : | array_flow.rb:380:9:380:9 | a [element] : | | array_flow.rb:379:12:379:23 | call to source : | array_flow.rb:379:5:379:5 | [post] a [element] : | | array_flow.rb:379:12:379:23 | call to source : | array_flow.rb:379:5:379:5 | [post] a [element] : | +| array_flow.rb:380:5:380:5 | b [element 1] : | array_flow.rb:381:10:381:10 | b [element 1] : | +| array_flow.rb:380:5:380:5 | b [element 1] : | array_flow.rb:381:10:381:10 | b [element 1] : | +| array_flow.rb:380:5:380:5 | b [element] : | array_flow.rb:381:10:381:10 | b [element] : | +| array_flow.rb:380:5:380:5 | b [element] : | array_flow.rb:381:10:381:10 | b [element] : | +| array_flow.rb:380:5:380:5 | b [element] : | array_flow.rb:382:9:382:9 | b [element] : | +| array_flow.rb:380:5:380:5 | b [element] : | array_flow.rb:382:9:382:9 | b [element] : | | array_flow.rb:380:9:380:9 | a [element 2] : | array_flow.rb:380:9:380:17 | call to drop [element 1] : | | array_flow.rb:380:9:380:9 | a [element 2] : | array_flow.rb:380:9:380:17 | call to drop [element 1] : | | array_flow.rb:380:9:380:9 | a [element] : | array_flow.rb:380:9:380:17 | call to drop [element] : | | array_flow.rb:380:9:380:9 | a [element] : | array_flow.rb:380:9:380:17 | call to drop [element] : | -| array_flow.rb:380:9:380:17 | call to drop [element 1] : | array_flow.rb:381:10:381:10 | b [element 1] : | -| array_flow.rb:380:9:380:17 | call to drop [element 1] : | array_flow.rb:381:10:381:10 | b [element 1] : | -| array_flow.rb:380:9:380:17 | call to drop [element] : | array_flow.rb:381:10:381:10 | b [element] : | -| array_flow.rb:380:9:380:17 | call to drop [element] : | array_flow.rb:381:10:381:10 | b [element] : | -| array_flow.rb:380:9:380:17 | call to drop [element] : | array_flow.rb:382:9:382:9 | b [element] : | -| array_flow.rb:380:9:380:17 | call to drop [element] : | array_flow.rb:382:9:382:9 | b [element] : | +| array_flow.rb:380:9:380:17 | call to drop [element 1] : | array_flow.rb:380:5:380:5 | b [element 1] : | +| array_flow.rb:380:9:380:17 | call to drop [element 1] : | array_flow.rb:380:5:380:5 | b [element 1] : | +| array_flow.rb:380:9:380:17 | call to drop [element] : | array_flow.rb:380:5:380:5 | b [element] : | +| array_flow.rb:380:9:380:17 | call to drop [element] : | array_flow.rb:380:5:380:5 | b [element] : | | array_flow.rb:381:10:381:10 | b [element 1] : | array_flow.rb:381:10:381:13 | ...[...] | | array_flow.rb:381:10:381:10 | b [element 1] : | array_flow.rb:381:10:381:13 | ...[...] | | array_flow.rb:381:10:381:10 | b [element] : | array_flow.rb:381:10:381:13 | ...[...] | | array_flow.rb:381:10:381:10 | b [element] : | array_flow.rb:381:10:381:13 | ...[...] | +| array_flow.rb:382:5:382:5 | c [element] : | array_flow.rb:383:10:383:10 | c [element] : | +| array_flow.rb:382:5:382:5 | c [element] : | array_flow.rb:383:10:383:10 | c [element] : | | array_flow.rb:382:9:382:9 | b [element] : | array_flow.rb:382:9:382:19 | call to drop [element] : | | array_flow.rb:382:9:382:9 | b [element] : | array_flow.rb:382:9:382:19 | call to drop [element] : | -| array_flow.rb:382:9:382:19 | call to drop [element] : | array_flow.rb:383:10:383:10 | c [element] : | -| array_flow.rb:382:9:382:19 | call to drop [element] : | array_flow.rb:383:10:383:10 | c [element] : | +| array_flow.rb:382:9:382:19 | call to drop [element] : | array_flow.rb:382:5:382:5 | c [element] : | +| array_flow.rb:382:9:382:19 | call to drop [element] : | array_flow.rb:382:5:382:5 | c [element] : | | array_flow.rb:383:10:383:10 | c [element] : | array_flow.rb:383:10:383:13 | ...[...] | | array_flow.rb:383:10:383:10 | c [element] : | array_flow.rb:383:10:383:13 | ...[...] | -| array_flow.rb:387:16:387:27 | call to source : | array_flow.rb:388:9:388:9 | a [element 2] : | -| array_flow.rb:387:16:387:27 | call to source : | array_flow.rb:388:9:388:9 | a [element 2] : | -| array_flow.rb:387:30:387:41 | call to source : | array_flow.rb:388:9:388:9 | a [element 3] : | -| array_flow.rb:387:30:387:41 | call to source : | array_flow.rb:388:9:388:9 | a [element 3] : | +| array_flow.rb:387:5:387:5 | a [element 2] : | array_flow.rb:388:9:388:9 | a [element 2] : | +| array_flow.rb:387:5:387:5 | a [element 2] : | array_flow.rb:388:9:388:9 | a [element 2] : | +| array_flow.rb:387:5:387:5 | a [element 3] : | array_flow.rb:388:9:388:9 | a [element 3] : | +| array_flow.rb:387:5:387:5 | a [element 3] : | array_flow.rb:388:9:388:9 | a [element 3] : | +| array_flow.rb:387:16:387:27 | call to source : | array_flow.rb:387:5:387:5 | a [element 2] : | +| array_flow.rb:387:16:387:27 | call to source : | array_flow.rb:387:5:387:5 | a [element 2] : | +| array_flow.rb:387:30:387:41 | call to source : | array_flow.rb:387:5:387:5 | a [element 3] : | +| array_flow.rb:387:30:387:41 | call to source : | array_flow.rb:387:5:387:5 | a [element 3] : | +| array_flow.rb:388:5:388:5 | b [element] : | array_flow.rb:391:10:391:10 | b [element] : | +| array_flow.rb:388:5:388:5 | b [element] : | array_flow.rb:391:10:391:10 | b [element] : | | array_flow.rb:388:9:388:9 | a [element 2] : | array_flow.rb:388:9:390:7 | call to drop_while [element] : | | array_flow.rb:388:9:388:9 | a [element 2] : | array_flow.rb:388:9:390:7 | call to drop_while [element] : | | array_flow.rb:388:9:388:9 | a [element 2] : | array_flow.rb:388:26:388:26 | x : | @@ -690,40 +879,50 @@ edges | array_flow.rb:388:9:388:9 | a [element 3] : | array_flow.rb:388:9:390:7 | call to drop_while [element] : | | array_flow.rb:388:9:388:9 | a [element 3] : | array_flow.rb:388:26:388:26 | x : | | array_flow.rb:388:9:388:9 | a [element 3] : | array_flow.rb:388:26:388:26 | x : | -| array_flow.rb:388:9:390:7 | call to drop_while [element] : | array_flow.rb:391:10:391:10 | b [element] : | -| array_flow.rb:388:9:390:7 | call to drop_while [element] : | array_flow.rb:391:10:391:10 | b [element] : | +| array_flow.rb:388:9:390:7 | call to drop_while [element] : | array_flow.rb:388:5:388:5 | b [element] : | +| array_flow.rb:388:9:390:7 | call to drop_while [element] : | array_flow.rb:388:5:388:5 | b [element] : | | array_flow.rb:388:26:388:26 | x : | array_flow.rb:389:14:389:14 | x | | array_flow.rb:388:26:388:26 | x : | array_flow.rb:389:14:389:14 | x | | array_flow.rb:391:10:391:10 | b [element] : | array_flow.rb:391:10:391:13 | ...[...] | | array_flow.rb:391:10:391:10 | b [element] : | array_flow.rb:391:10:391:13 | ...[...] | -| array_flow.rb:395:16:395:25 | call to source : | array_flow.rb:396:9:396:9 | a [element 2] : | -| array_flow.rb:395:16:395:25 | call to source : | array_flow.rb:396:9:396:9 | a [element 2] : | +| array_flow.rb:395:5:395:5 | a [element 2] : | array_flow.rb:396:9:396:9 | a [element 2] : | +| array_flow.rb:395:5:395:5 | a [element 2] : | array_flow.rb:396:9:396:9 | a [element 2] : | +| array_flow.rb:395:16:395:25 | call to source : | array_flow.rb:395:5:395:5 | a [element 2] : | +| array_flow.rb:395:16:395:25 | call to source : | array_flow.rb:395:5:395:5 | a [element 2] : | +| array_flow.rb:396:5:396:5 | b [element 2] : | array_flow.rb:399:10:399:10 | b [element 2] : | +| array_flow.rb:396:5:396:5 | b [element 2] : | array_flow.rb:399:10:399:10 | b [element 2] : | | array_flow.rb:396:9:396:9 | a [element 2] : | array_flow.rb:396:9:398:7 | call to each [element 2] : | | array_flow.rb:396:9:396:9 | a [element 2] : | array_flow.rb:396:9:398:7 | call to each [element 2] : | | array_flow.rb:396:9:396:9 | a [element 2] : | array_flow.rb:396:20:396:20 | x : | | array_flow.rb:396:9:396:9 | a [element 2] : | array_flow.rb:396:20:396:20 | x : | -| array_flow.rb:396:9:398:7 | call to each [element 2] : | array_flow.rb:399:10:399:10 | b [element 2] : | -| array_flow.rb:396:9:398:7 | call to each [element 2] : | array_flow.rb:399:10:399:10 | b [element 2] : | +| array_flow.rb:396:9:398:7 | call to each [element 2] : | array_flow.rb:396:5:396:5 | b [element 2] : | +| array_flow.rb:396:9:398:7 | call to each [element 2] : | array_flow.rb:396:5:396:5 | b [element 2] : | | array_flow.rb:396:20:396:20 | x : | array_flow.rb:397:14:397:14 | x | | array_flow.rb:396:20:396:20 | x : | array_flow.rb:397:14:397:14 | x | | array_flow.rb:399:10:399:10 | b [element 2] : | array_flow.rb:399:10:399:13 | ...[...] | | array_flow.rb:399:10:399:10 | b [element 2] : | array_flow.rb:399:10:399:13 | ...[...] | -| array_flow.rb:403:16:403:25 | call to source : | array_flow.rb:404:18:404:18 | a [element 2] : | -| array_flow.rb:403:16:403:25 | call to source : | array_flow.rb:404:18:404:18 | a [element 2] : | -| array_flow.rb:404:9:406:7 | ... = ... : | array_flow.rb:407:10:407:10 | x | -| array_flow.rb:404:9:406:7 | ... = ... : | array_flow.rb:407:10:407:10 | x | -| array_flow.rb:404:9:406:7 | __synth__0__1 : | array_flow.rb:404:9:406:7 | ... = ... : | -| array_flow.rb:404:9:406:7 | __synth__0__1 : | array_flow.rb:404:9:406:7 | ... = ... : | -| array_flow.rb:404:9:406:7 | __synth__0__1 : | array_flow.rb:405:14:405:14 | x | -| array_flow.rb:404:9:406:7 | __synth__0__1 : | array_flow.rb:405:14:405:14 | x | +| array_flow.rb:403:5:403:5 | a [element 2] : | array_flow.rb:404:18:404:18 | a [element 2] : | +| array_flow.rb:403:5:403:5 | a [element 2] : | array_flow.rb:404:18:404:18 | a [element 2] : | +| array_flow.rb:403:16:403:25 | call to source : | array_flow.rb:403:5:403:5 | a [element 2] : | +| array_flow.rb:403:16:403:25 | call to source : | array_flow.rb:403:5:403:5 | a [element 2] : | +| array_flow.rb:404:5:404:5 | b [element 2] : | array_flow.rb:408:10:408:10 | b [element 2] : | +| array_flow.rb:404:5:404:5 | b [element 2] : | array_flow.rb:408:10:408:10 | b [element 2] : | +| array_flow.rb:404:9:406:7 | __synth__0__1 : | array_flow.rb:404:13:404:13 | x : | +| array_flow.rb:404:9:406:7 | __synth__0__1 : | array_flow.rb:404:13:404:13 | x : | +| array_flow.rb:404:13:404:13 | x : | array_flow.rb:405:14:405:14 | x | +| array_flow.rb:404:13:404:13 | x : | array_flow.rb:405:14:405:14 | x | +| array_flow.rb:404:13:404:13 | x : | array_flow.rb:407:10:407:10 | x | +| array_flow.rb:404:13:404:13 | x : | array_flow.rb:407:10:407:10 | x | +| array_flow.rb:404:18:404:18 | a [element 2] : | array_flow.rb:404:5:404:5 | b [element 2] : | +| array_flow.rb:404:18:404:18 | a [element 2] : | array_flow.rb:404:5:404:5 | b [element 2] : | | array_flow.rb:404:18:404:18 | a [element 2] : | array_flow.rb:404:9:406:7 | __synth__0__1 : | | array_flow.rb:404:18:404:18 | a [element 2] : | array_flow.rb:404:9:406:7 | __synth__0__1 : | -| array_flow.rb:404:18:404:18 | a [element 2] : | array_flow.rb:408:10:408:10 | b [element 2] : | -| array_flow.rb:404:18:404:18 | a [element 2] : | array_flow.rb:408:10:408:10 | b [element 2] : | | array_flow.rb:408:10:408:10 | b [element 2] : | array_flow.rb:408:10:408:13 | ...[...] | | array_flow.rb:408:10:408:10 | b [element 2] : | array_flow.rb:408:10:408:13 | ...[...] | -| array_flow.rb:412:16:412:25 | call to source : | array_flow.rb:413:5:413:5 | a [element 2] : | -| array_flow.rb:412:16:412:25 | call to source : | array_flow.rb:413:5:413:5 | a [element 2] : | +| array_flow.rb:412:5:412:5 | a [element 2] : | array_flow.rb:413:5:413:5 | a [element 2] : | +| array_flow.rb:412:5:412:5 | a [element 2] : | array_flow.rb:413:5:413:5 | a [element 2] : | +| array_flow.rb:412:16:412:25 | call to source : | array_flow.rb:412:5:412:5 | a [element 2] : | +| array_flow.rb:412:16:412:25 | call to source : | array_flow.rb:412:5:412:5 | a [element 2] : | | array_flow.rb:413:5:413:5 | a [element 2] : | array_flow.rb:413:24:413:24 | x [element] : | | array_flow.rb:413:5:413:5 | a [element 2] : | array_flow.rb:413:24:413:24 | x [element] : | | array_flow.rb:413:24:413:24 | x [element] : | array_flow.rb:414:15:414:15 | x [element] : | @@ -732,52 +931,70 @@ edges | array_flow.rb:414:15:414:15 | x [element] : | array_flow.rb:414:15:414:18 | ...[...] : | | array_flow.rb:414:15:414:18 | ...[...] : | array_flow.rb:414:14:414:19 | ( ... ) | | array_flow.rb:414:15:414:18 | ...[...] : | array_flow.rb:414:14:414:19 | ( ... ) | -| array_flow.rb:419:16:419:25 | call to source : | array_flow.rb:420:9:420:9 | a [element 2] : | -| array_flow.rb:419:16:419:25 | call to source : | array_flow.rb:420:9:420:9 | a [element 2] : | +| array_flow.rb:419:5:419:5 | a [element 2] : | array_flow.rb:420:9:420:9 | a [element 2] : | +| array_flow.rb:419:5:419:5 | a [element 2] : | array_flow.rb:420:9:420:9 | a [element 2] : | +| array_flow.rb:419:16:419:25 | call to source : | array_flow.rb:419:5:419:5 | a [element 2] : | +| array_flow.rb:419:16:419:25 | call to source : | array_flow.rb:419:5:419:5 | a [element 2] : | +| array_flow.rb:420:5:420:5 | b [element 2] : | array_flow.rb:423:10:423:10 | b [element 2] : | +| array_flow.rb:420:5:420:5 | b [element 2] : | array_flow.rb:423:10:423:10 | b [element 2] : | | array_flow.rb:420:9:420:9 | a [element 2] : | array_flow.rb:420:9:422:7 | call to each_entry [element 2] : | | array_flow.rb:420:9:420:9 | a [element 2] : | array_flow.rb:420:9:422:7 | call to each_entry [element 2] : | | array_flow.rb:420:9:420:9 | a [element 2] : | array_flow.rb:420:26:420:26 | x : | | array_flow.rb:420:9:420:9 | a [element 2] : | array_flow.rb:420:26:420:26 | x : | -| array_flow.rb:420:9:422:7 | call to each_entry [element 2] : | array_flow.rb:423:10:423:10 | b [element 2] : | -| array_flow.rb:420:9:422:7 | call to each_entry [element 2] : | array_flow.rb:423:10:423:10 | b [element 2] : | +| array_flow.rb:420:9:422:7 | call to each_entry [element 2] : | array_flow.rb:420:5:420:5 | b [element 2] : | +| array_flow.rb:420:9:422:7 | call to each_entry [element 2] : | array_flow.rb:420:5:420:5 | b [element 2] : | | array_flow.rb:420:26:420:26 | x : | array_flow.rb:421:14:421:14 | x | | array_flow.rb:420:26:420:26 | x : | array_flow.rb:421:14:421:14 | x | | array_flow.rb:423:10:423:10 | b [element 2] : | array_flow.rb:423:10:423:13 | ...[...] | | array_flow.rb:423:10:423:10 | b [element 2] : | array_flow.rb:423:10:423:13 | ...[...] | -| array_flow.rb:427:16:427:25 | call to source : | array_flow.rb:428:9:428:9 | a [element 2] : | -| array_flow.rb:427:16:427:25 | call to source : | array_flow.rb:428:9:428:9 | a [element 2] : | +| array_flow.rb:427:5:427:5 | a [element 2] : | array_flow.rb:428:9:428:9 | a [element 2] : | +| array_flow.rb:427:5:427:5 | a [element 2] : | array_flow.rb:428:9:428:9 | a [element 2] : | +| array_flow.rb:427:16:427:25 | call to source : | array_flow.rb:427:5:427:5 | a [element 2] : | +| array_flow.rb:427:16:427:25 | call to source : | array_flow.rb:427:5:427:5 | a [element 2] : | +| array_flow.rb:428:5:428:5 | b [element 2] : | array_flow.rb:431:10:431:10 | b [element 2] : | +| array_flow.rb:428:5:428:5 | b [element 2] : | array_flow.rb:431:10:431:10 | b [element 2] : | | array_flow.rb:428:9:428:9 | a [element 2] : | array_flow.rb:428:9:430:7 | call to each_index [element 2] : | | array_flow.rb:428:9:428:9 | a [element 2] : | array_flow.rb:428:9:430:7 | call to each_index [element 2] : | -| array_flow.rb:428:9:430:7 | call to each_index [element 2] : | array_flow.rb:431:10:431:10 | b [element 2] : | -| array_flow.rb:428:9:430:7 | call to each_index [element 2] : | array_flow.rb:431:10:431:10 | b [element 2] : | +| array_flow.rb:428:9:430:7 | call to each_index [element 2] : | array_flow.rb:428:5:428:5 | b [element 2] : | +| array_flow.rb:428:9:430:7 | call to each_index [element 2] : | array_flow.rb:428:5:428:5 | b [element 2] : | | array_flow.rb:431:10:431:10 | b [element 2] : | array_flow.rb:431:10:431:13 | ...[...] | | array_flow.rb:431:10:431:10 | b [element 2] : | array_flow.rb:431:10:431:13 | ...[...] | -| array_flow.rb:435:19:435:28 | call to source : | array_flow.rb:436:5:436:5 | a [element 3] : | -| array_flow.rb:435:19:435:28 | call to source : | array_flow.rb:436:5:436:5 | a [element 3] : | +| array_flow.rb:435:5:435:5 | a [element 3] : | array_flow.rb:436:5:436:5 | a [element 3] : | +| array_flow.rb:435:5:435:5 | a [element 3] : | array_flow.rb:436:5:436:5 | a [element 3] : | +| array_flow.rb:435:19:435:28 | call to source : | array_flow.rb:435:5:435:5 | a [element 3] : | +| array_flow.rb:435:19:435:28 | call to source : | array_flow.rb:435:5:435:5 | a [element 3] : | | array_flow.rb:436:5:436:5 | a [element 3] : | array_flow.rb:436:25:436:25 | x [element] : | | array_flow.rb:436:5:436:5 | a [element 3] : | array_flow.rb:436:25:436:25 | x [element] : | | array_flow.rb:436:25:436:25 | x [element] : | array_flow.rb:437:14:437:14 | x [element] : | | array_flow.rb:436:25:436:25 | x [element] : | array_flow.rb:437:14:437:14 | x [element] : | | array_flow.rb:437:14:437:14 | x [element] : | array_flow.rb:437:14:437:17 | ...[...] | | array_flow.rb:437:14:437:14 | x [element] : | array_flow.rb:437:14:437:17 | ...[...] | -| array_flow.rb:442:19:442:28 | call to source : | array_flow.rb:443:9:443:9 | a [element 3] : | -| array_flow.rb:442:19:442:28 | call to source : | array_flow.rb:443:9:443:9 | a [element 3] : | +| array_flow.rb:442:5:442:5 | a [element 3] : | array_flow.rb:443:9:443:9 | a [element 3] : | +| array_flow.rb:442:5:442:5 | a [element 3] : | array_flow.rb:443:9:443:9 | a [element 3] : | +| array_flow.rb:442:19:442:28 | call to source : | array_flow.rb:442:5:442:5 | a [element 3] : | +| array_flow.rb:442:19:442:28 | call to source : | array_flow.rb:442:5:442:5 | a [element 3] : | +| array_flow.rb:443:5:443:5 | b [element 3] : | array_flow.rb:447:10:447:10 | b [element 3] : | +| array_flow.rb:443:5:443:5 | b [element 3] : | array_flow.rb:447:10:447:10 | b [element 3] : | | array_flow.rb:443:9:443:9 | a [element 3] : | array_flow.rb:443:9:446:7 | call to each_with_index [element 3] : | | array_flow.rb:443:9:443:9 | a [element 3] : | array_flow.rb:443:9:446:7 | call to each_with_index [element 3] : | | array_flow.rb:443:9:443:9 | a [element 3] : | array_flow.rb:443:31:443:31 | x : | | array_flow.rb:443:9:443:9 | a [element 3] : | array_flow.rb:443:31:443:31 | x : | -| array_flow.rb:443:9:446:7 | call to each_with_index [element 3] : | array_flow.rb:447:10:447:10 | b [element 3] : | -| array_flow.rb:443:9:446:7 | call to each_with_index [element 3] : | array_flow.rb:447:10:447:10 | b [element 3] : | +| array_flow.rb:443:9:446:7 | call to each_with_index [element 3] : | array_flow.rb:443:5:443:5 | b [element 3] : | +| array_flow.rb:443:9:446:7 | call to each_with_index [element 3] : | array_flow.rb:443:5:443:5 | b [element 3] : | | array_flow.rb:443:31:443:31 | x : | array_flow.rb:444:14:444:14 | x | | array_flow.rb:443:31:443:31 | x : | array_flow.rb:444:14:444:14 | x | | array_flow.rb:447:10:447:10 | b [element 3] : | array_flow.rb:447:10:447:13 | ...[...] | | array_flow.rb:447:10:447:10 | b [element 3] : | array_flow.rb:447:10:447:13 | ...[...] | -| array_flow.rb:451:19:451:30 | call to source : | array_flow.rb:452:9:452:9 | a [element 3] : | -| array_flow.rb:451:19:451:30 | call to source : | array_flow.rb:452:9:452:9 | a [element 3] : | +| array_flow.rb:451:5:451:5 | a [element 3] : | array_flow.rb:452:9:452:9 | a [element 3] : | +| array_flow.rb:451:5:451:5 | a [element 3] : | array_flow.rb:452:9:452:9 | a [element 3] : | +| array_flow.rb:451:19:451:30 | call to source : | array_flow.rb:451:5:451:5 | a [element 3] : | +| array_flow.rb:451:19:451:30 | call to source : | array_flow.rb:451:5:451:5 | a [element 3] : | +| array_flow.rb:452:5:452:5 | b : | array_flow.rb:456:10:456:10 | b | +| array_flow.rb:452:5:452:5 | b : | array_flow.rb:456:10:456:10 | b | | array_flow.rb:452:9:452:9 | a [element 3] : | array_flow.rb:452:46:452:46 | x : | | array_flow.rb:452:9:452:9 | a [element 3] : | array_flow.rb:452:46:452:46 | x : | -| array_flow.rb:452:9:455:7 | call to each_with_object : | array_flow.rb:456:10:456:10 | b | -| array_flow.rb:452:9:455:7 | call to each_with_object : | array_flow.rb:456:10:456:10 | b | +| array_flow.rb:452:9:455:7 | call to each_with_object : | array_flow.rb:452:5:452:5 | b : | +| array_flow.rb:452:9:455:7 | call to each_with_object : | array_flow.rb:452:5:452:5 | b : | | array_flow.rb:452:28:452:39 | call to source : | array_flow.rb:452:9:455:7 | call to each_with_object : | | array_flow.rb:452:28:452:39 | call to source : | array_flow.rb:452:9:455:7 | call to each_with_object : | | array_flow.rb:452:28:452:39 | call to source : | array_flow.rb:452:48:452:48 | a : | @@ -786,60 +1003,80 @@ edges | array_flow.rb:452:46:452:46 | x : | array_flow.rb:453:14:453:14 | x | | array_flow.rb:452:48:452:48 | a : | array_flow.rb:454:14:454:14 | a | | array_flow.rb:452:48:452:48 | a : | array_flow.rb:454:14:454:14 | a | -| array_flow.rb:460:19:460:28 | call to source : | array_flow.rb:461:9:461:9 | a [element 3] : | -| array_flow.rb:460:19:460:28 | call to source : | array_flow.rb:461:9:461:9 | a [element 3] : | +| array_flow.rb:460:5:460:5 | a [element 3] : | array_flow.rb:461:9:461:9 | a [element 3] : | +| array_flow.rb:460:5:460:5 | a [element 3] : | array_flow.rb:461:9:461:9 | a [element 3] : | +| array_flow.rb:460:19:460:28 | call to source : | array_flow.rb:460:5:460:5 | a [element 3] : | +| array_flow.rb:460:19:460:28 | call to source : | array_flow.rb:460:5:460:5 | a [element 3] : | +| array_flow.rb:461:5:461:5 | b [element 3] : | array_flow.rb:462:10:462:10 | b [element 3] : | +| array_flow.rb:461:5:461:5 | b [element 3] : | array_flow.rb:462:10:462:10 | b [element 3] : | | array_flow.rb:461:9:461:9 | a [element 3] : | array_flow.rb:461:9:461:17 | call to entries [element 3] : | | array_flow.rb:461:9:461:9 | a [element 3] : | array_flow.rb:461:9:461:17 | call to entries [element 3] : | -| array_flow.rb:461:9:461:17 | call to entries [element 3] : | array_flow.rb:462:10:462:10 | b [element 3] : | -| array_flow.rb:461:9:461:17 | call to entries [element 3] : | array_flow.rb:462:10:462:10 | b [element 3] : | +| array_flow.rb:461:9:461:17 | call to entries [element 3] : | array_flow.rb:461:5:461:5 | b [element 3] : | +| array_flow.rb:461:9:461:17 | call to entries [element 3] : | array_flow.rb:461:5:461:5 | b [element 3] : | | array_flow.rb:462:10:462:10 | b [element 3] : | array_flow.rb:462:10:462:13 | ...[...] | | array_flow.rb:462:10:462:10 | b [element 3] : | array_flow.rb:462:10:462:13 | ...[...] | -| array_flow.rb:466:19:466:30 | call to source : | array_flow.rb:467:9:467:9 | a [element 3] : | -| array_flow.rb:466:19:466:30 | call to source : | array_flow.rb:467:9:467:9 | a [element 3] : | -| array_flow.rb:466:19:466:30 | call to source : | array_flow.rb:471:9:471:9 | a [element 3] : | -| array_flow.rb:466:19:466:30 | call to source : | array_flow.rb:471:9:471:9 | a [element 3] : | -| array_flow.rb:466:19:466:30 | call to source : | array_flow.rb:473:9:473:9 | a [element 3] : | -| array_flow.rb:466:19:466:30 | call to source : | array_flow.rb:473:9:473:9 | a [element 3] : | -| array_flow.rb:466:19:466:30 | call to source : | array_flow.rb:477:9:477:9 | a [element 3] : | -| array_flow.rb:466:19:466:30 | call to source : | array_flow.rb:477:9:477:9 | a [element 3] : | -| array_flow.rb:466:33:466:44 | call to source : | array_flow.rb:467:9:467:9 | a [element 4] : | -| array_flow.rb:466:33:466:44 | call to source : | array_flow.rb:467:9:467:9 | a [element 4] : | -| array_flow.rb:466:33:466:44 | call to source : | array_flow.rb:477:9:477:9 | a [element 4] : | -| array_flow.rb:466:33:466:44 | call to source : | array_flow.rb:477:9:477:9 | a [element 4] : | +| array_flow.rb:466:5:466:5 | a [element 3] : | array_flow.rb:467:9:467:9 | a [element 3] : | +| array_flow.rb:466:5:466:5 | a [element 3] : | array_flow.rb:467:9:467:9 | a [element 3] : | +| array_flow.rb:466:5:466:5 | a [element 3] : | array_flow.rb:471:9:471:9 | a [element 3] : | +| array_flow.rb:466:5:466:5 | a [element 3] : | array_flow.rb:471:9:471:9 | a [element 3] : | +| array_flow.rb:466:5:466:5 | a [element 3] : | array_flow.rb:473:9:473:9 | a [element 3] : | +| array_flow.rb:466:5:466:5 | a [element 3] : | array_flow.rb:473:9:473:9 | a [element 3] : | +| array_flow.rb:466:5:466:5 | a [element 3] : | array_flow.rb:477:9:477:9 | a [element 3] : | +| array_flow.rb:466:5:466:5 | a [element 3] : | array_flow.rb:477:9:477:9 | a [element 3] : | +| array_flow.rb:466:5:466:5 | a [element 4] : | array_flow.rb:467:9:467:9 | a [element 4] : | +| array_flow.rb:466:5:466:5 | a [element 4] : | array_flow.rb:467:9:467:9 | a [element 4] : | +| array_flow.rb:466:5:466:5 | a [element 4] : | array_flow.rb:477:9:477:9 | a [element 4] : | +| array_flow.rb:466:5:466:5 | a [element 4] : | array_flow.rb:477:9:477:9 | a [element 4] : | +| array_flow.rb:466:19:466:30 | call to source : | array_flow.rb:466:5:466:5 | a [element 3] : | +| array_flow.rb:466:19:466:30 | call to source : | array_flow.rb:466:5:466:5 | a [element 3] : | +| array_flow.rb:466:33:466:44 | call to source : | array_flow.rb:466:5:466:5 | a [element 4] : | +| array_flow.rb:466:33:466:44 | call to source : | array_flow.rb:466:5:466:5 | a [element 4] : | +| array_flow.rb:467:5:467:5 | b : | array_flow.rb:470:10:470:10 | b | +| array_flow.rb:467:5:467:5 | b : | array_flow.rb:470:10:470:10 | b | | array_flow.rb:467:9:467:9 | a [element 3] : | array_flow.rb:467:9:469:7 | call to fetch : | | array_flow.rb:467:9:467:9 | a [element 3] : | array_flow.rb:467:9:469:7 | call to fetch : | | array_flow.rb:467:9:467:9 | a [element 4] : | array_flow.rb:467:9:469:7 | call to fetch : | | array_flow.rb:467:9:467:9 | a [element 4] : | array_flow.rb:467:9:469:7 | call to fetch : | -| array_flow.rb:467:9:469:7 | call to fetch : | array_flow.rb:470:10:470:10 | b | -| array_flow.rb:467:9:469:7 | call to fetch : | array_flow.rb:470:10:470:10 | b | +| array_flow.rb:467:9:469:7 | call to fetch : | array_flow.rb:467:5:467:5 | b : | +| array_flow.rb:467:9:469:7 | call to fetch : | array_flow.rb:467:5:467:5 | b : | | array_flow.rb:467:17:467:28 | call to source : | array_flow.rb:467:35:467:35 | x : | | array_flow.rb:467:17:467:28 | call to source : | array_flow.rb:467:35:467:35 | x : | | array_flow.rb:467:35:467:35 | x : | array_flow.rb:468:14:468:14 | x | | array_flow.rb:467:35:467:35 | x : | array_flow.rb:468:14:468:14 | x | +| array_flow.rb:471:5:471:5 | b : | array_flow.rb:472:10:472:10 | b | +| array_flow.rb:471:5:471:5 | b : | array_flow.rb:472:10:472:10 | b | | array_flow.rb:471:9:471:9 | a [element 3] : | array_flow.rb:471:9:471:18 | call to fetch : | | array_flow.rb:471:9:471:9 | a [element 3] : | array_flow.rb:471:9:471:18 | call to fetch : | -| array_flow.rb:471:9:471:18 | call to fetch : | array_flow.rb:472:10:472:10 | b | -| array_flow.rb:471:9:471:18 | call to fetch : | array_flow.rb:472:10:472:10 | b | +| array_flow.rb:471:9:471:18 | call to fetch : | array_flow.rb:471:5:471:5 | b : | +| array_flow.rb:471:9:471:18 | call to fetch : | array_flow.rb:471:5:471:5 | b : | +| array_flow.rb:473:5:473:5 | b : | array_flow.rb:474:10:474:10 | b | +| array_flow.rb:473:5:473:5 | b : | array_flow.rb:474:10:474:10 | b | | array_flow.rb:473:9:473:9 | a [element 3] : | array_flow.rb:473:9:473:32 | call to fetch : | | array_flow.rb:473:9:473:9 | a [element 3] : | array_flow.rb:473:9:473:32 | call to fetch : | -| array_flow.rb:473:9:473:32 | call to fetch : | array_flow.rb:474:10:474:10 | b | -| array_flow.rb:473:9:473:32 | call to fetch : | array_flow.rb:474:10:474:10 | b | +| array_flow.rb:473:9:473:32 | call to fetch : | array_flow.rb:473:5:473:5 | b : | +| array_flow.rb:473:9:473:32 | call to fetch : | array_flow.rb:473:5:473:5 | b : | | array_flow.rb:473:20:473:31 | call to source : | array_flow.rb:473:9:473:32 | call to fetch : | | array_flow.rb:473:20:473:31 | call to source : | array_flow.rb:473:9:473:32 | call to fetch : | -| array_flow.rb:475:9:475:34 | call to fetch : | array_flow.rb:476:10:476:10 | b | -| array_flow.rb:475:9:475:34 | call to fetch : | array_flow.rb:476:10:476:10 | b | +| array_flow.rb:475:5:475:5 | b : | array_flow.rb:476:10:476:10 | b | +| array_flow.rb:475:5:475:5 | b : | array_flow.rb:476:10:476:10 | b | +| array_flow.rb:475:9:475:34 | call to fetch : | array_flow.rb:475:5:475:5 | b : | +| array_flow.rb:475:9:475:34 | call to fetch : | array_flow.rb:475:5:475:5 | b : | | array_flow.rb:475:22:475:33 | call to source : | array_flow.rb:475:9:475:34 | call to fetch : | | array_flow.rb:475:22:475:33 | call to source : | array_flow.rb:475:9:475:34 | call to fetch : | +| array_flow.rb:477:5:477:5 | b : | array_flow.rb:478:10:478:10 | b | +| array_flow.rb:477:5:477:5 | b : | array_flow.rb:478:10:478:10 | b | | array_flow.rb:477:9:477:9 | a [element 3] : | array_flow.rb:477:9:477:32 | call to fetch : | | array_flow.rb:477:9:477:9 | a [element 3] : | array_flow.rb:477:9:477:32 | call to fetch : | | array_flow.rb:477:9:477:9 | a [element 4] : | array_flow.rb:477:9:477:32 | call to fetch : | | array_flow.rb:477:9:477:9 | a [element 4] : | array_flow.rb:477:9:477:32 | call to fetch : | -| array_flow.rb:477:9:477:32 | call to fetch : | array_flow.rb:478:10:478:10 | b | -| array_flow.rb:477:9:477:32 | call to fetch : | array_flow.rb:478:10:478:10 | b | +| array_flow.rb:477:9:477:32 | call to fetch : | array_flow.rb:477:5:477:5 | b : | +| array_flow.rb:477:9:477:32 | call to fetch : | array_flow.rb:477:5:477:5 | b : | | array_flow.rb:477:20:477:31 | call to source : | array_flow.rb:477:9:477:32 | call to fetch : | | array_flow.rb:477:20:477:31 | call to source : | array_flow.rb:477:9:477:32 | call to fetch : | -| array_flow.rb:482:19:482:30 | call to source : | array_flow.rb:484:10:484:10 | a [element 3] : | -| array_flow.rb:482:19:482:30 | call to source : | array_flow.rb:484:10:484:10 | a [element 3] : | +| array_flow.rb:482:5:482:5 | a [element 3] : | array_flow.rb:484:10:484:10 | a [element 3] : | +| array_flow.rb:482:5:482:5 | a [element 3] : | array_flow.rb:484:10:484:10 | a [element 3] : | +| array_flow.rb:482:19:482:30 | call to source : | array_flow.rb:482:5:482:5 | a [element 3] : | +| array_flow.rb:482:19:482:30 | call to source : | array_flow.rb:482:5:482:5 | a [element 3] : | | array_flow.rb:483:5:483:5 | [post] a [element] : | array_flow.rb:484:10:484:10 | a [element] : | | array_flow.rb:483:5:483:5 | [post] a [element] : | array_flow.rb:484:10:484:10 | a [element] : | | array_flow.rb:483:12:483:23 | call to source : | array_flow.rb:483:5:483:5 | [post] a [element] : | @@ -868,32 +1105,44 @@ edges | array_flow.rb:492:9:492:20 | call to source : | array_flow.rb:491:5:491:5 | [post] a [element] : | | array_flow.rb:494:10:494:10 | a [element] : | array_flow.rb:494:10:494:13 | ...[...] | | array_flow.rb:494:10:494:10 | a [element] : | array_flow.rb:494:10:494:13 | ...[...] | -| array_flow.rb:498:19:498:28 | call to source : | array_flow.rb:499:9:499:9 | a [element 3] : | -| array_flow.rb:498:19:498:28 | call to source : | array_flow.rb:499:9:499:9 | a [element 3] : | +| array_flow.rb:498:5:498:5 | a [element 3] : | array_flow.rb:499:9:499:9 | a [element 3] : | +| array_flow.rb:498:5:498:5 | a [element 3] : | array_flow.rb:499:9:499:9 | a [element 3] : | +| array_flow.rb:498:19:498:28 | call to source : | array_flow.rb:498:5:498:5 | a [element 3] : | +| array_flow.rb:498:19:498:28 | call to source : | array_flow.rb:498:5:498:5 | a [element 3] : | +| array_flow.rb:499:5:499:5 | b [element] : | array_flow.rb:502:10:502:10 | b [element] : | +| array_flow.rb:499:5:499:5 | b [element] : | array_flow.rb:502:10:502:10 | b [element] : | | array_flow.rb:499:9:499:9 | a [element 3] : | array_flow.rb:499:9:501:7 | call to filter [element] : | | array_flow.rb:499:9:499:9 | a [element 3] : | array_flow.rb:499:9:501:7 | call to filter [element] : | | array_flow.rb:499:9:499:9 | a [element 3] : | array_flow.rb:499:22:499:22 | x : | | array_flow.rb:499:9:499:9 | a [element 3] : | array_flow.rb:499:22:499:22 | x : | -| array_flow.rb:499:9:501:7 | call to filter [element] : | array_flow.rb:502:10:502:10 | b [element] : | -| array_flow.rb:499:9:501:7 | call to filter [element] : | array_flow.rb:502:10:502:10 | b [element] : | +| array_flow.rb:499:9:501:7 | call to filter [element] : | array_flow.rb:499:5:499:5 | b [element] : | +| array_flow.rb:499:9:501:7 | call to filter [element] : | array_flow.rb:499:5:499:5 | b [element] : | | array_flow.rb:499:22:499:22 | x : | array_flow.rb:500:14:500:14 | x | | array_flow.rb:499:22:499:22 | x : | array_flow.rb:500:14:500:14 | x | | array_flow.rb:502:10:502:10 | b [element] : | array_flow.rb:502:10:502:13 | ...[...] | | array_flow.rb:502:10:502:10 | b [element] : | array_flow.rb:502:10:502:13 | ...[...] | -| array_flow.rb:506:19:506:28 | call to source : | array_flow.rb:507:9:507:9 | a [element 3] : | -| array_flow.rb:506:19:506:28 | call to source : | array_flow.rb:507:9:507:9 | a [element 3] : | +| array_flow.rb:506:5:506:5 | a [element 3] : | array_flow.rb:507:9:507:9 | a [element 3] : | +| array_flow.rb:506:5:506:5 | a [element 3] : | array_flow.rb:507:9:507:9 | a [element 3] : | +| array_flow.rb:506:19:506:28 | call to source : | array_flow.rb:506:5:506:5 | a [element 3] : | +| array_flow.rb:506:19:506:28 | call to source : | array_flow.rb:506:5:506:5 | a [element 3] : | +| array_flow.rb:507:5:507:5 | b [element] : | array_flow.rb:510:10:510:10 | b [element] : | +| array_flow.rb:507:5:507:5 | b [element] : | array_flow.rb:510:10:510:10 | b [element] : | | array_flow.rb:507:9:507:9 | a [element 3] : | array_flow.rb:507:9:509:7 | call to filter_map [element] : | | array_flow.rb:507:9:507:9 | a [element 3] : | array_flow.rb:507:9:509:7 | call to filter_map [element] : | | array_flow.rb:507:9:507:9 | a [element 3] : | array_flow.rb:507:26:507:26 | x : | | array_flow.rb:507:9:507:9 | a [element 3] : | array_flow.rb:507:26:507:26 | x : | -| array_flow.rb:507:9:509:7 | call to filter_map [element] : | array_flow.rb:510:10:510:10 | b [element] : | -| array_flow.rb:507:9:509:7 | call to filter_map [element] : | array_flow.rb:510:10:510:10 | b [element] : | +| array_flow.rb:507:9:509:7 | call to filter_map [element] : | array_flow.rb:507:5:507:5 | b [element] : | +| array_flow.rb:507:9:509:7 | call to filter_map [element] : | array_flow.rb:507:5:507:5 | b [element] : | | array_flow.rb:507:26:507:26 | x : | array_flow.rb:508:14:508:14 | x | | array_flow.rb:507:26:507:26 | x : | array_flow.rb:508:14:508:14 | x | | array_flow.rb:510:10:510:10 | b [element] : | array_flow.rb:510:10:510:13 | ...[...] | | array_flow.rb:510:10:510:10 | b [element] : | array_flow.rb:510:10:510:13 | ...[...] | -| array_flow.rb:514:19:514:28 | call to source : | array_flow.rb:515:9:515:9 | a [element 3] : | -| array_flow.rb:514:19:514:28 | call to source : | array_flow.rb:515:9:515:9 | a [element 3] : | +| array_flow.rb:514:5:514:5 | a [element 3] : | array_flow.rb:515:9:515:9 | a [element 3] : | +| array_flow.rb:514:5:514:5 | a [element 3] : | array_flow.rb:515:9:515:9 | a [element 3] : | +| array_flow.rb:514:19:514:28 | call to source : | array_flow.rb:514:5:514:5 | a [element 3] : | +| array_flow.rb:514:19:514:28 | call to source : | array_flow.rb:514:5:514:5 | a [element 3] : | +| array_flow.rb:515:5:515:5 | b [element] : | array_flow.rb:520:10:520:10 | b [element] : | +| array_flow.rb:515:5:515:5 | b [element] : | array_flow.rb:520:10:520:10 | b [element] : | | array_flow.rb:515:9:515:9 | [post] a [element] : | array_flow.rb:519:10:519:10 | a [element] : | | array_flow.rb:515:9:515:9 | [post] a [element] : | array_flow.rb:519:10:519:10 | a [element] : | | array_flow.rb:515:9:515:9 | a [element 3] : | array_flow.rb:515:9:515:9 | [post] a [element] : | @@ -902,52 +1151,66 @@ edges | array_flow.rb:515:9:515:9 | a [element 3] : | array_flow.rb:515:9:518:7 | call to filter! [element] : | | array_flow.rb:515:9:515:9 | a [element 3] : | array_flow.rb:515:23:515:23 | x : | | array_flow.rb:515:9:515:9 | a [element 3] : | array_flow.rb:515:23:515:23 | x : | -| array_flow.rb:515:9:518:7 | call to filter! [element] : | array_flow.rb:520:10:520:10 | b [element] : | -| array_flow.rb:515:9:518:7 | call to filter! [element] : | array_flow.rb:520:10:520:10 | b [element] : | +| array_flow.rb:515:9:518:7 | call to filter! [element] : | array_flow.rb:515:5:515:5 | b [element] : | +| array_flow.rb:515:9:518:7 | call to filter! [element] : | array_flow.rb:515:5:515:5 | b [element] : | | array_flow.rb:515:23:515:23 | x : | array_flow.rb:516:14:516:14 | x | | array_flow.rb:515:23:515:23 | x : | array_flow.rb:516:14:516:14 | x | | array_flow.rb:519:10:519:10 | a [element] : | array_flow.rb:519:10:519:13 | ...[...] | | array_flow.rb:519:10:519:10 | a [element] : | array_flow.rb:519:10:519:13 | ...[...] | | array_flow.rb:520:10:520:10 | b [element] : | array_flow.rb:520:10:520:13 | ...[...] | | array_flow.rb:520:10:520:10 | b [element] : | array_flow.rb:520:10:520:13 | ...[...] | -| array_flow.rb:524:19:524:30 | call to source : | array_flow.rb:525:9:525:9 | a [element 3] : | -| array_flow.rb:524:19:524:30 | call to source : | array_flow.rb:525:9:525:9 | a [element 3] : | +| array_flow.rb:524:5:524:5 | a [element 3] : | array_flow.rb:525:9:525:9 | a [element 3] : | +| array_flow.rb:524:5:524:5 | a [element 3] : | array_flow.rb:525:9:525:9 | a [element 3] : | +| array_flow.rb:524:19:524:30 | call to source : | array_flow.rb:524:5:524:5 | a [element 3] : | +| array_flow.rb:524:19:524:30 | call to source : | array_flow.rb:524:5:524:5 | a [element 3] : | +| array_flow.rb:525:5:525:5 | b : | array_flow.rb:528:10:528:10 | b | +| array_flow.rb:525:5:525:5 | b : | array_flow.rb:528:10:528:10 | b | | array_flow.rb:525:9:525:9 | a [element 3] : | array_flow.rb:525:9:527:7 | call to find : | | array_flow.rb:525:9:525:9 | a [element 3] : | array_flow.rb:525:9:527:7 | call to find : | | array_flow.rb:525:9:525:9 | a [element 3] : | array_flow.rb:525:41:525:41 | x : | | array_flow.rb:525:9:525:9 | a [element 3] : | array_flow.rb:525:41:525:41 | x : | -| array_flow.rb:525:9:527:7 | call to find : | array_flow.rb:528:10:528:10 | b | -| array_flow.rb:525:9:527:7 | call to find : | array_flow.rb:528:10:528:10 | b | +| array_flow.rb:525:9:527:7 | call to find : | array_flow.rb:525:5:525:5 | b : | +| array_flow.rb:525:9:527:7 | call to find : | array_flow.rb:525:5:525:5 | b : | | array_flow.rb:525:21:525:32 | call to source : | array_flow.rb:525:9:527:7 | call to find : | | array_flow.rb:525:21:525:32 | call to source : | array_flow.rb:525:9:527:7 | call to find : | | array_flow.rb:525:41:525:41 | x : | array_flow.rb:526:14:526:14 | x | | array_flow.rb:525:41:525:41 | x : | array_flow.rb:526:14:526:14 | x | -| array_flow.rb:532:19:532:28 | call to source : | array_flow.rb:533:9:533:9 | a [element 3] : | -| array_flow.rb:532:19:532:28 | call to source : | array_flow.rb:533:9:533:9 | a [element 3] : | +| array_flow.rb:532:5:532:5 | a [element 3] : | array_flow.rb:533:9:533:9 | a [element 3] : | +| array_flow.rb:532:5:532:5 | a [element 3] : | array_flow.rb:533:9:533:9 | a [element 3] : | +| array_flow.rb:532:19:532:28 | call to source : | array_flow.rb:532:5:532:5 | a [element 3] : | +| array_flow.rb:532:19:532:28 | call to source : | array_flow.rb:532:5:532:5 | a [element 3] : | +| array_flow.rb:533:5:533:5 | b [element] : | array_flow.rb:536:10:536:10 | b [element] : | +| array_flow.rb:533:5:533:5 | b [element] : | array_flow.rb:536:10:536:10 | b [element] : | | array_flow.rb:533:9:533:9 | a [element 3] : | array_flow.rb:533:9:535:7 | call to find_all [element] : | | array_flow.rb:533:9:533:9 | a [element 3] : | array_flow.rb:533:9:535:7 | call to find_all [element] : | | array_flow.rb:533:9:533:9 | a [element 3] : | array_flow.rb:533:24:533:24 | x : | | array_flow.rb:533:9:533:9 | a [element 3] : | array_flow.rb:533:24:533:24 | x : | -| array_flow.rb:533:9:535:7 | call to find_all [element] : | array_flow.rb:536:10:536:10 | b [element] : | -| array_flow.rb:533:9:535:7 | call to find_all [element] : | array_flow.rb:536:10:536:10 | b [element] : | +| array_flow.rb:533:9:535:7 | call to find_all [element] : | array_flow.rb:533:5:533:5 | b [element] : | +| array_flow.rb:533:9:535:7 | call to find_all [element] : | array_flow.rb:533:5:533:5 | b [element] : | | array_flow.rb:533:24:533:24 | x : | array_flow.rb:534:14:534:14 | x | | array_flow.rb:533:24:533:24 | x : | array_flow.rb:534:14:534:14 | x | | array_flow.rb:536:10:536:10 | b [element] : | array_flow.rb:536:10:536:13 | ...[...] | | array_flow.rb:536:10:536:10 | b [element] : | array_flow.rb:536:10:536:13 | ...[...] | -| array_flow.rb:540:19:540:28 | call to source : | array_flow.rb:541:5:541:5 | a [element 3] : | -| array_flow.rb:540:19:540:28 | call to source : | array_flow.rb:541:5:541:5 | a [element 3] : | +| array_flow.rb:540:5:540:5 | a [element 3] : | array_flow.rb:541:5:541:5 | a [element 3] : | +| array_flow.rb:540:5:540:5 | a [element 3] : | array_flow.rb:541:5:541:5 | a [element 3] : | +| array_flow.rb:540:19:540:28 | call to source : | array_flow.rb:540:5:540:5 | a [element 3] : | +| array_flow.rb:540:19:540:28 | call to source : | array_flow.rb:540:5:540:5 | a [element 3] : | | array_flow.rb:541:5:541:5 | a [element 3] : | array_flow.rb:541:22:541:22 | x : | | array_flow.rb:541:5:541:5 | a [element 3] : | array_flow.rb:541:22:541:22 | x : | | array_flow.rb:541:22:541:22 | x : | array_flow.rb:542:14:542:14 | x | | array_flow.rb:541:22:541:22 | x : | array_flow.rb:542:14:542:14 | x | -| array_flow.rb:547:10:547:21 | call to source : | array_flow.rb:549:10:549:10 | a [element 0] : | -| array_flow.rb:547:10:547:21 | call to source : | array_flow.rb:549:10:549:10 | a [element 0] : | -| array_flow.rb:547:10:547:21 | call to source : | array_flow.rb:550:9:550:9 | a [element 0] : | -| array_flow.rb:547:10:547:21 | call to source : | array_flow.rb:550:9:550:9 | a [element 0] : | -| array_flow.rb:547:10:547:21 | call to source : | array_flow.rb:553:9:553:9 | a [element 0] : | -| array_flow.rb:547:10:547:21 | call to source : | array_flow.rb:553:9:553:9 | a [element 0] : | -| array_flow.rb:547:30:547:41 | call to source : | array_flow.rb:553:9:553:9 | a [element 3] : | -| array_flow.rb:547:30:547:41 | call to source : | array_flow.rb:553:9:553:9 | a [element 3] : | +| array_flow.rb:547:5:547:5 | a [element 0] : | array_flow.rb:549:10:549:10 | a [element 0] : | +| array_flow.rb:547:5:547:5 | a [element 0] : | array_flow.rb:549:10:549:10 | a [element 0] : | +| array_flow.rb:547:5:547:5 | a [element 0] : | array_flow.rb:550:9:550:9 | a [element 0] : | +| array_flow.rb:547:5:547:5 | a [element 0] : | array_flow.rb:550:9:550:9 | a [element 0] : | +| array_flow.rb:547:5:547:5 | a [element 0] : | array_flow.rb:553:9:553:9 | a [element 0] : | +| array_flow.rb:547:5:547:5 | a [element 0] : | array_flow.rb:553:9:553:9 | a [element 0] : | +| array_flow.rb:547:5:547:5 | a [element 3] : | array_flow.rb:553:9:553:9 | a [element 3] : | +| array_flow.rb:547:5:547:5 | a [element 3] : | array_flow.rb:553:9:553:9 | a [element 3] : | +| array_flow.rb:547:10:547:21 | call to source : | array_flow.rb:547:5:547:5 | a [element 0] : | +| array_flow.rb:547:10:547:21 | call to source : | array_flow.rb:547:5:547:5 | a [element 0] : | +| array_flow.rb:547:30:547:41 | call to source : | array_flow.rb:547:5:547:5 | a [element 3] : | +| array_flow.rb:547:30:547:41 | call to source : | array_flow.rb:547:5:547:5 | a [element 3] : | | array_flow.rb:548:5:548:5 | [post] a [element] : | array_flow.rb:549:10:549:10 | a [element] : | | array_flow.rb:548:5:548:5 | [post] a [element] : | array_flow.rb:549:10:549:10 | a [element] : | | array_flow.rb:548:5:548:5 | [post] a [element] : | array_flow.rb:550:9:550:9 | a [element] : | @@ -960,36 +1223,46 @@ edges | array_flow.rb:549:10:549:10 | a [element 0] : | array_flow.rb:549:10:549:16 | call to first | | array_flow.rb:549:10:549:10 | a [element] : | array_flow.rb:549:10:549:16 | call to first | | array_flow.rb:549:10:549:10 | a [element] : | array_flow.rb:549:10:549:16 | call to first | +| array_flow.rb:550:5:550:5 | b [element 0] : | array_flow.rb:551:10:551:10 | b [element 0] : | +| array_flow.rb:550:5:550:5 | b [element 0] : | array_flow.rb:551:10:551:10 | b [element 0] : | +| array_flow.rb:550:5:550:5 | b [element] : | array_flow.rb:551:10:551:10 | b [element] : | +| array_flow.rb:550:5:550:5 | b [element] : | array_flow.rb:551:10:551:10 | b [element] : | +| array_flow.rb:550:5:550:5 | b [element] : | array_flow.rb:552:10:552:10 | b [element] : | +| array_flow.rb:550:5:550:5 | b [element] : | array_flow.rb:552:10:552:10 | b [element] : | | array_flow.rb:550:9:550:9 | a [element 0] : | array_flow.rb:550:9:550:18 | call to first [element 0] : | | array_flow.rb:550:9:550:9 | a [element 0] : | array_flow.rb:550:9:550:18 | call to first [element 0] : | | array_flow.rb:550:9:550:9 | a [element] : | array_flow.rb:550:9:550:18 | call to first [element] : | | array_flow.rb:550:9:550:9 | a [element] : | array_flow.rb:550:9:550:18 | call to first [element] : | -| array_flow.rb:550:9:550:18 | call to first [element 0] : | array_flow.rb:551:10:551:10 | b [element 0] : | -| array_flow.rb:550:9:550:18 | call to first [element 0] : | array_flow.rb:551:10:551:10 | b [element 0] : | -| array_flow.rb:550:9:550:18 | call to first [element] : | array_flow.rb:551:10:551:10 | b [element] : | -| array_flow.rb:550:9:550:18 | call to first [element] : | array_flow.rb:551:10:551:10 | b [element] : | -| array_flow.rb:550:9:550:18 | call to first [element] : | array_flow.rb:552:10:552:10 | b [element] : | -| array_flow.rb:550:9:550:18 | call to first [element] : | array_flow.rb:552:10:552:10 | b [element] : | +| array_flow.rb:550:9:550:18 | call to first [element 0] : | array_flow.rb:550:5:550:5 | b [element 0] : | +| array_flow.rb:550:9:550:18 | call to first [element 0] : | array_flow.rb:550:5:550:5 | b [element 0] : | +| array_flow.rb:550:9:550:18 | call to first [element] : | array_flow.rb:550:5:550:5 | b [element] : | +| array_flow.rb:550:9:550:18 | call to first [element] : | array_flow.rb:550:5:550:5 | b [element] : | | array_flow.rb:551:10:551:10 | b [element 0] : | array_flow.rb:551:10:551:13 | ...[...] | | array_flow.rb:551:10:551:10 | b [element 0] : | array_flow.rb:551:10:551:13 | ...[...] | | array_flow.rb:551:10:551:10 | b [element] : | array_flow.rb:551:10:551:13 | ...[...] | | array_flow.rb:551:10:551:10 | b [element] : | array_flow.rb:551:10:551:13 | ...[...] | | array_flow.rb:552:10:552:10 | b [element] : | array_flow.rb:552:10:552:13 | ...[...] | | array_flow.rb:552:10:552:10 | b [element] : | array_flow.rb:552:10:552:13 | ...[...] | +| array_flow.rb:553:5:553:5 | c [element 0] : | array_flow.rb:554:10:554:10 | c [element 0] : | +| array_flow.rb:553:5:553:5 | c [element 0] : | array_flow.rb:554:10:554:10 | c [element 0] : | +| array_flow.rb:553:5:553:5 | c [element 3] : | array_flow.rb:555:10:555:10 | c [element 3] : | +| array_flow.rb:553:5:553:5 | c [element 3] : | array_flow.rb:555:10:555:10 | c [element 3] : | +| array_flow.rb:553:5:553:5 | c [element] : | array_flow.rb:554:10:554:10 | c [element] : | +| array_flow.rb:553:5:553:5 | c [element] : | array_flow.rb:554:10:554:10 | c [element] : | +| array_flow.rb:553:5:553:5 | c [element] : | array_flow.rb:555:10:555:10 | c [element] : | +| array_flow.rb:553:5:553:5 | c [element] : | array_flow.rb:555:10:555:10 | c [element] : | | array_flow.rb:553:9:553:9 | a [element 0] : | array_flow.rb:553:9:553:18 | call to first [element 0] : | | array_flow.rb:553:9:553:9 | a [element 0] : | array_flow.rb:553:9:553:18 | call to first [element 0] : | | array_flow.rb:553:9:553:9 | a [element 3] : | array_flow.rb:553:9:553:18 | call to first [element 3] : | | array_flow.rb:553:9:553:9 | a [element 3] : | array_flow.rb:553:9:553:18 | call to first [element 3] : | | array_flow.rb:553:9:553:9 | a [element] : | array_flow.rb:553:9:553:18 | call to first [element] : | | array_flow.rb:553:9:553:9 | a [element] : | array_flow.rb:553:9:553:18 | call to first [element] : | -| array_flow.rb:553:9:553:18 | call to first [element 0] : | array_flow.rb:554:10:554:10 | c [element 0] : | -| array_flow.rb:553:9:553:18 | call to first [element 0] : | array_flow.rb:554:10:554:10 | c [element 0] : | -| array_flow.rb:553:9:553:18 | call to first [element 3] : | array_flow.rb:555:10:555:10 | c [element 3] : | -| array_flow.rb:553:9:553:18 | call to first [element 3] : | array_flow.rb:555:10:555:10 | c [element 3] : | -| array_flow.rb:553:9:553:18 | call to first [element] : | array_flow.rb:554:10:554:10 | c [element] : | -| array_flow.rb:553:9:553:18 | call to first [element] : | array_flow.rb:554:10:554:10 | c [element] : | -| array_flow.rb:553:9:553:18 | call to first [element] : | array_flow.rb:555:10:555:10 | c [element] : | -| array_flow.rb:553:9:553:18 | call to first [element] : | array_flow.rb:555:10:555:10 | c [element] : | +| array_flow.rb:553:9:553:18 | call to first [element 0] : | array_flow.rb:553:5:553:5 | c [element 0] : | +| array_flow.rb:553:9:553:18 | call to first [element 0] : | array_flow.rb:553:5:553:5 | c [element 0] : | +| array_flow.rb:553:9:553:18 | call to first [element 3] : | array_flow.rb:553:5:553:5 | c [element 3] : | +| array_flow.rb:553:9:553:18 | call to first [element 3] : | array_flow.rb:553:5:553:5 | c [element 3] : | +| array_flow.rb:553:9:553:18 | call to first [element] : | array_flow.rb:553:5:553:5 | c [element] : | +| array_flow.rb:553:9:553:18 | call to first [element] : | array_flow.rb:553:5:553:5 | c [element] : | | array_flow.rb:554:10:554:10 | c [element 0] : | array_flow.rb:554:10:554:13 | ...[...] | | array_flow.rb:554:10:554:10 | c [element 0] : | array_flow.rb:554:10:554:13 | ...[...] | | array_flow.rb:554:10:554:10 | c [element] : | array_flow.rb:554:10:554:13 | ...[...] | @@ -998,48 +1271,65 @@ edges | array_flow.rb:555:10:555:10 | c [element 3] : | array_flow.rb:555:10:555:13 | ...[...] | | array_flow.rb:555:10:555:10 | c [element] : | array_flow.rb:555:10:555:13 | ...[...] | | array_flow.rb:555:10:555:10 | c [element] : | array_flow.rb:555:10:555:13 | ...[...] | -| array_flow.rb:559:16:559:27 | call to source : | array_flow.rb:560:9:560:9 | a [element 2] : | -| array_flow.rb:559:16:559:27 | call to source : | array_flow.rb:560:9:560:9 | a [element 2] : | -| array_flow.rb:559:16:559:27 | call to source : | array_flow.rb:565:9:565:9 | a [element 2] : | -| array_flow.rb:559:16:559:27 | call to source : | array_flow.rb:565:9:565:9 | a [element 2] : | +| array_flow.rb:559:5:559:5 | a [element 2] : | array_flow.rb:560:9:560:9 | a [element 2] : | +| array_flow.rb:559:5:559:5 | a [element 2] : | array_flow.rb:560:9:560:9 | a [element 2] : | +| array_flow.rb:559:5:559:5 | a [element 2] : | array_flow.rb:565:9:565:9 | a [element 2] : | +| array_flow.rb:559:5:559:5 | a [element 2] : | array_flow.rb:565:9:565:9 | a [element 2] : | +| array_flow.rb:559:16:559:27 | call to source : | array_flow.rb:559:5:559:5 | a [element 2] : | +| array_flow.rb:559:16:559:27 | call to source : | array_flow.rb:559:5:559:5 | a [element 2] : | +| array_flow.rb:560:5:560:5 | b [element] : | array_flow.rb:564:10:564:10 | b [element] : | +| array_flow.rb:560:5:560:5 | b [element] : | array_flow.rb:564:10:564:10 | b [element] : | | array_flow.rb:560:9:560:9 | a [element 2] : | array_flow.rb:560:9:563:7 | call to flat_map [element] : | | array_flow.rb:560:9:560:9 | a [element 2] : | array_flow.rb:560:9:563:7 | call to flat_map [element] : | | array_flow.rb:560:9:560:9 | a [element 2] : | array_flow.rb:560:24:560:24 | x : | | array_flow.rb:560:9:560:9 | a [element 2] : | array_flow.rb:560:24:560:24 | x : | -| array_flow.rb:560:9:563:7 | call to flat_map [element] : | array_flow.rb:564:10:564:10 | b [element] : | -| array_flow.rb:560:9:563:7 | call to flat_map [element] : | array_flow.rb:564:10:564:10 | b [element] : | +| array_flow.rb:560:9:563:7 | call to flat_map [element] : | array_flow.rb:560:5:560:5 | b [element] : | +| array_flow.rb:560:9:563:7 | call to flat_map [element] : | array_flow.rb:560:5:560:5 | b [element] : | | array_flow.rb:560:24:560:24 | x : | array_flow.rb:561:14:561:14 | x | | array_flow.rb:560:24:560:24 | x : | array_flow.rb:561:14:561:14 | x | | array_flow.rb:562:13:562:24 | call to source : | array_flow.rb:560:9:563:7 | call to flat_map [element] : | | array_flow.rb:562:13:562:24 | call to source : | array_flow.rb:560:9:563:7 | call to flat_map [element] : | | array_flow.rb:564:10:564:10 | b [element] : | array_flow.rb:564:10:564:13 | ...[...] | | array_flow.rb:564:10:564:10 | b [element] : | array_flow.rb:564:10:564:13 | ...[...] | +| array_flow.rb:565:5:565:5 | b [element] : | array_flow.rb:569:10:569:10 | b [element] : | +| array_flow.rb:565:5:565:5 | b [element] : | array_flow.rb:569:10:569:10 | b [element] : | | array_flow.rb:565:9:565:9 | a [element 2] : | array_flow.rb:565:24:565:24 | x : | | array_flow.rb:565:9:565:9 | a [element 2] : | array_flow.rb:565:24:565:24 | x : | -| array_flow.rb:565:9:568:7 | call to flat_map [element] : | array_flow.rb:569:10:569:10 | b [element] : | -| array_flow.rb:565:9:568:7 | call to flat_map [element] : | array_flow.rb:569:10:569:10 | b [element] : | +| array_flow.rb:565:9:568:7 | call to flat_map [element] : | array_flow.rb:565:5:565:5 | b [element] : | +| array_flow.rb:565:9:568:7 | call to flat_map [element] : | array_flow.rb:565:5:565:5 | b [element] : | | array_flow.rb:565:24:565:24 | x : | array_flow.rb:566:14:566:14 | x | | array_flow.rb:565:24:565:24 | x : | array_flow.rb:566:14:566:14 | x | | array_flow.rb:567:9:567:20 | call to source : | array_flow.rb:565:9:568:7 | call to flat_map [element] : | | array_flow.rb:567:9:567:20 | call to source : | array_flow.rb:565:9:568:7 | call to flat_map [element] : | | array_flow.rb:569:10:569:10 | b [element] : | array_flow.rb:569:10:569:13 | ...[...] | | array_flow.rb:569:10:569:10 | b [element] : | array_flow.rb:569:10:569:13 | ...[...] | -| array_flow.rb:573:20:573:29 | call to source : | array_flow.rb:574:9:574:9 | a [element 2, element 1] : | -| array_flow.rb:573:20:573:29 | call to source : | array_flow.rb:574:9:574:9 | a [element 2, element 1] : | +| array_flow.rb:573:5:573:5 | a [element 2, element 1] : | array_flow.rb:574:9:574:9 | a [element 2, element 1] : | +| array_flow.rb:573:5:573:5 | a [element 2, element 1] : | array_flow.rb:574:9:574:9 | a [element 2, element 1] : | +| array_flow.rb:573:20:573:29 | call to source : | array_flow.rb:573:5:573:5 | a [element 2, element 1] : | +| array_flow.rb:573:20:573:29 | call to source : | array_flow.rb:573:5:573:5 | a [element 2, element 1] : | +| array_flow.rb:574:5:574:5 | b [element] : | array_flow.rb:575:10:575:10 | b [element] : | +| array_flow.rb:574:5:574:5 | b [element] : | array_flow.rb:575:10:575:10 | b [element] : | | array_flow.rb:574:9:574:9 | a [element 2, element 1] : | array_flow.rb:574:9:574:17 | call to flatten [element] : | | array_flow.rb:574:9:574:9 | a [element 2, element 1] : | array_flow.rb:574:9:574:17 | call to flatten [element] : | -| array_flow.rb:574:9:574:17 | call to flatten [element] : | array_flow.rb:575:10:575:10 | b [element] : | -| array_flow.rb:574:9:574:17 | call to flatten [element] : | array_flow.rb:575:10:575:10 | b [element] : | +| array_flow.rb:574:9:574:17 | call to flatten [element] : | array_flow.rb:574:5:574:5 | b [element] : | +| array_flow.rb:574:9:574:17 | call to flatten [element] : | array_flow.rb:574:5:574:5 | b [element] : | | array_flow.rb:575:10:575:10 | b [element] : | array_flow.rb:575:10:575:13 | ...[...] | | array_flow.rb:575:10:575:10 | b [element] : | array_flow.rb:575:10:575:13 | ...[...] | -| array_flow.rb:579:20:579:29 | call to source : | array_flow.rb:580:10:580:10 | a [element 2, element 1] : | -| array_flow.rb:579:20:579:29 | call to source : | array_flow.rb:580:10:580:10 | a [element 2, element 1] : | -| array_flow.rb:579:20:579:29 | call to source : | array_flow.rb:581:9:581:9 | a [element 2, element 1] : | -| array_flow.rb:579:20:579:29 | call to source : | array_flow.rb:581:9:581:9 | a [element 2, element 1] : | +| array_flow.rb:579:5:579:5 | a [element 2, element 1] : | array_flow.rb:580:10:580:10 | a [element 2, element 1] : | +| array_flow.rb:579:5:579:5 | a [element 2, element 1] : | array_flow.rb:580:10:580:10 | a [element 2, element 1] : | +| array_flow.rb:579:5:579:5 | a [element 2, element 1] : | array_flow.rb:581:9:581:9 | a [element 2, element 1] : | +| array_flow.rb:579:5:579:5 | a [element 2, element 1] : | array_flow.rb:581:9:581:9 | a [element 2, element 1] : | +| array_flow.rb:579:20:579:29 | call to source : | array_flow.rb:579:5:579:5 | a [element 2, element 1] : | +| array_flow.rb:579:20:579:29 | call to source : | array_flow.rb:579:5:579:5 | a [element 2, element 1] : | | array_flow.rb:580:10:580:10 | a [element 2, element 1] : | array_flow.rb:580:10:580:13 | ...[...] [element 1] : | | array_flow.rb:580:10:580:10 | a [element 2, element 1] : | array_flow.rb:580:10:580:13 | ...[...] [element 1] : | | array_flow.rb:580:10:580:13 | ...[...] [element 1] : | array_flow.rb:580:10:580:16 | ...[...] | | array_flow.rb:580:10:580:13 | ...[...] [element 1] : | array_flow.rb:580:10:580:16 | ...[...] | +| array_flow.rb:581:5:581:5 | b [element, element 1] : | array_flow.rb:585:10:585:10 | b [element, element 1] : | +| array_flow.rb:581:5:581:5 | b [element, element 1] : | array_flow.rb:585:10:585:10 | b [element, element 1] : | +| array_flow.rb:581:5:581:5 | b [element] : | array_flow.rb:584:10:584:10 | b [element] : | +| array_flow.rb:581:5:581:5 | b [element] : | array_flow.rb:584:10:584:10 | b [element] : | +| array_flow.rb:581:5:581:5 | b [element] : | array_flow.rb:585:10:585:10 | b [element] : | | array_flow.rb:581:9:581:9 | [post] a [element, element 1] : | array_flow.rb:583:10:583:10 | a [element, element 1] : | | array_flow.rb:581:9:581:9 | [post] a [element, element 1] : | array_flow.rb:583:10:583:10 | a [element, element 1] : | | array_flow.rb:581:9:581:9 | [post] a [element] : | array_flow.rb:582:10:582:10 | a [element] : | @@ -1053,11 +1343,10 @@ edges | array_flow.rb:581:9:581:9 | a [element 2, element 1] : | array_flow.rb:581:9:581:18 | call to flatten! [element, element 1] : | | array_flow.rb:581:9:581:9 | a [element 2, element 1] : | array_flow.rb:581:9:581:18 | call to flatten! [element] : | | array_flow.rb:581:9:581:9 | a [element 2, element 1] : | array_flow.rb:581:9:581:18 | call to flatten! [element] : | -| array_flow.rb:581:9:581:18 | call to flatten! [element, element 1] : | array_flow.rb:585:10:585:10 | b [element, element 1] : | -| array_flow.rb:581:9:581:18 | call to flatten! [element, element 1] : | array_flow.rb:585:10:585:10 | b [element, element 1] : | -| array_flow.rb:581:9:581:18 | call to flatten! [element] : | array_flow.rb:584:10:584:10 | b [element] : | -| array_flow.rb:581:9:581:18 | call to flatten! [element] : | array_flow.rb:584:10:584:10 | b [element] : | -| array_flow.rb:581:9:581:18 | call to flatten! [element] : | array_flow.rb:585:10:585:10 | b [element] : | +| array_flow.rb:581:9:581:18 | call to flatten! [element, element 1] : | array_flow.rb:581:5:581:5 | b [element, element 1] : | +| array_flow.rb:581:9:581:18 | call to flatten! [element, element 1] : | array_flow.rb:581:5:581:5 | b [element, element 1] : | +| array_flow.rb:581:9:581:18 | call to flatten! [element] : | array_flow.rb:581:5:581:5 | b [element] : | +| array_flow.rb:581:9:581:18 | call to flatten! [element] : | array_flow.rb:581:5:581:5 | b [element] : | | array_flow.rb:582:10:582:10 | a [element] : | array_flow.rb:582:10:582:13 | ...[...] | | array_flow.rb:582:10:582:10 | a [element] : | array_flow.rb:582:10:582:13 | ...[...] | | array_flow.rb:583:10:583:10 | a [element, element 1] : | array_flow.rb:583:10:583:13 | ...[...] [element 1] : | @@ -1074,90 +1363,122 @@ edges | array_flow.rb:585:10:585:13 | ...[...] : | array_flow.rb:585:10:585:16 | ...[...] | | array_flow.rb:585:10:585:13 | ...[...] [element 1] : | array_flow.rb:585:10:585:16 | ...[...] | | array_flow.rb:585:10:585:13 | ...[...] [element 1] : | array_flow.rb:585:10:585:16 | ...[...] | -| array_flow.rb:589:19:589:30 | call to source : | array_flow.rb:590:9:590:9 | a [element 3] : | -| array_flow.rb:589:19:589:30 | call to source : | array_flow.rb:590:9:590:9 | a [element 3] : | -| array_flow.rb:589:19:589:30 | call to source : | array_flow.rb:592:9:592:9 | a [element 3] : | -| array_flow.rb:589:19:589:30 | call to source : | array_flow.rb:592:9:592:9 | a [element 3] : | +| array_flow.rb:589:5:589:5 | a [element 3] : | array_flow.rb:590:9:590:9 | a [element 3] : | +| array_flow.rb:589:5:589:5 | a [element 3] : | array_flow.rb:590:9:590:9 | a [element 3] : | +| array_flow.rb:589:5:589:5 | a [element 3] : | array_flow.rb:592:9:592:9 | a [element 3] : | +| array_flow.rb:589:5:589:5 | a [element 3] : | array_flow.rb:592:9:592:9 | a [element 3] : | +| array_flow.rb:589:19:589:30 | call to source : | array_flow.rb:589:5:589:5 | a [element 3] : | +| array_flow.rb:589:19:589:30 | call to source : | array_flow.rb:589:5:589:5 | a [element 3] : | +| array_flow.rb:590:5:590:5 | b [element] : | array_flow.rb:591:10:591:10 | b [element] : | +| array_flow.rb:590:5:590:5 | b [element] : | array_flow.rb:591:10:591:10 | b [element] : | | array_flow.rb:590:9:590:9 | a [element 3] : | array_flow.rb:590:9:590:20 | call to grep [element] : | | array_flow.rb:590:9:590:9 | a [element 3] : | array_flow.rb:590:9:590:20 | call to grep [element] : | -| array_flow.rb:590:9:590:20 | call to grep [element] : | array_flow.rb:591:10:591:10 | b [element] : | -| array_flow.rb:590:9:590:20 | call to grep [element] : | array_flow.rb:591:10:591:10 | b [element] : | +| array_flow.rb:590:9:590:20 | call to grep [element] : | array_flow.rb:590:5:590:5 | b [element] : | +| array_flow.rb:590:9:590:20 | call to grep [element] : | array_flow.rb:590:5:590:5 | b [element] : | | array_flow.rb:591:10:591:10 | b [element] : | array_flow.rb:591:10:591:13 | ...[...] | | array_flow.rb:591:10:591:10 | b [element] : | array_flow.rb:591:10:591:13 | ...[...] | +| array_flow.rb:592:5:592:5 | b [element] : | array_flow.rb:596:10:596:10 | b [element] : | +| array_flow.rb:592:5:592:5 | b [element] : | array_flow.rb:596:10:596:10 | b [element] : | | array_flow.rb:592:9:592:9 | a [element 3] : | array_flow.rb:592:26:592:26 | x : | | array_flow.rb:592:9:592:9 | a [element 3] : | array_flow.rb:592:26:592:26 | x : | -| array_flow.rb:592:9:595:7 | call to grep [element] : | array_flow.rb:596:10:596:10 | b [element] : | -| array_flow.rb:592:9:595:7 | call to grep [element] : | array_flow.rb:596:10:596:10 | b [element] : | +| array_flow.rb:592:9:595:7 | call to grep [element] : | array_flow.rb:592:5:592:5 | b [element] : | +| array_flow.rb:592:9:595:7 | call to grep [element] : | array_flow.rb:592:5:592:5 | b [element] : | | array_flow.rb:592:26:592:26 | x : | array_flow.rb:593:14:593:14 | x | | array_flow.rb:592:26:592:26 | x : | array_flow.rb:593:14:593:14 | x | | array_flow.rb:594:9:594:20 | call to source : | array_flow.rb:592:9:595:7 | call to grep [element] : | | array_flow.rb:594:9:594:20 | call to source : | array_flow.rb:592:9:595:7 | call to grep [element] : | | array_flow.rb:596:10:596:10 | b [element] : | array_flow.rb:596:10:596:13 | ...[...] | | array_flow.rb:596:10:596:10 | b [element] : | array_flow.rb:596:10:596:13 | ...[...] | -| array_flow.rb:600:19:600:30 | call to source : | array_flow.rb:601:9:601:9 | a [element 3] : | -| array_flow.rb:600:19:600:30 | call to source : | array_flow.rb:601:9:601:9 | a [element 3] : | -| array_flow.rb:600:19:600:30 | call to source : | array_flow.rb:603:9:603:9 | a [element 3] : | -| array_flow.rb:600:19:600:30 | call to source : | array_flow.rb:603:9:603:9 | a [element 3] : | +| array_flow.rb:600:5:600:5 | a [element 3] : | array_flow.rb:601:9:601:9 | a [element 3] : | +| array_flow.rb:600:5:600:5 | a [element 3] : | array_flow.rb:601:9:601:9 | a [element 3] : | +| array_flow.rb:600:5:600:5 | a [element 3] : | array_flow.rb:603:9:603:9 | a [element 3] : | +| array_flow.rb:600:5:600:5 | a [element 3] : | array_flow.rb:603:9:603:9 | a [element 3] : | +| array_flow.rb:600:19:600:30 | call to source : | array_flow.rb:600:5:600:5 | a [element 3] : | +| array_flow.rb:600:19:600:30 | call to source : | array_flow.rb:600:5:600:5 | a [element 3] : | +| array_flow.rb:601:5:601:5 | b [element] : | array_flow.rb:602:10:602:10 | b [element] : | +| array_flow.rb:601:5:601:5 | b [element] : | array_flow.rb:602:10:602:10 | b [element] : | | array_flow.rb:601:9:601:9 | a [element 3] : | array_flow.rb:601:9:601:21 | call to grep_v [element] : | | array_flow.rb:601:9:601:9 | a [element 3] : | array_flow.rb:601:9:601:21 | call to grep_v [element] : | -| array_flow.rb:601:9:601:21 | call to grep_v [element] : | array_flow.rb:602:10:602:10 | b [element] : | -| array_flow.rb:601:9:601:21 | call to grep_v [element] : | array_flow.rb:602:10:602:10 | b [element] : | +| array_flow.rb:601:9:601:21 | call to grep_v [element] : | array_flow.rb:601:5:601:5 | b [element] : | +| array_flow.rb:601:9:601:21 | call to grep_v [element] : | array_flow.rb:601:5:601:5 | b [element] : | | array_flow.rb:602:10:602:10 | b [element] : | array_flow.rb:602:10:602:13 | ...[...] | | array_flow.rb:602:10:602:10 | b [element] : | array_flow.rb:602:10:602:13 | ...[...] | +| array_flow.rb:603:5:603:5 | b [element] : | array_flow.rb:607:10:607:10 | b [element] : | +| array_flow.rb:603:5:603:5 | b [element] : | array_flow.rb:607:10:607:10 | b [element] : | | array_flow.rb:603:9:603:9 | a [element 3] : | array_flow.rb:603:27:603:27 | x : | | array_flow.rb:603:9:603:9 | a [element 3] : | array_flow.rb:603:27:603:27 | x : | -| array_flow.rb:603:9:606:7 | call to grep_v [element] : | array_flow.rb:607:10:607:10 | b [element] : | -| array_flow.rb:603:9:606:7 | call to grep_v [element] : | array_flow.rb:607:10:607:10 | b [element] : | +| array_flow.rb:603:9:606:7 | call to grep_v [element] : | array_flow.rb:603:5:603:5 | b [element] : | +| array_flow.rb:603:9:606:7 | call to grep_v [element] : | array_flow.rb:603:5:603:5 | b [element] : | | array_flow.rb:603:27:603:27 | x : | array_flow.rb:604:14:604:14 | x | | array_flow.rb:603:27:603:27 | x : | array_flow.rb:604:14:604:14 | x | | array_flow.rb:605:9:605:20 | call to source : | array_flow.rb:603:9:606:7 | call to grep_v [element] : | | array_flow.rb:605:9:605:20 | call to source : | array_flow.rb:603:9:606:7 | call to grep_v [element] : | | array_flow.rb:607:10:607:10 | b [element] : | array_flow.rb:607:10:607:13 | ...[...] | | array_flow.rb:607:10:607:10 | b [element] : | array_flow.rb:607:10:607:13 | ...[...] | -| array_flow.rb:611:19:611:30 | call to source : | array_flow.rb:612:9:612:9 | a [element 3] : | -| array_flow.rb:611:19:611:30 | call to source : | array_flow.rb:612:9:612:9 | a [element 3] : | +| array_flow.rb:611:5:611:5 | a [element 3] : | array_flow.rb:612:9:612:9 | a [element 3] : | +| array_flow.rb:611:5:611:5 | a [element 3] : | array_flow.rb:612:9:612:9 | a [element 3] : | +| array_flow.rb:611:19:611:30 | call to source : | array_flow.rb:611:5:611:5 | a [element 3] : | +| array_flow.rb:611:19:611:30 | call to source : | array_flow.rb:611:5:611:5 | a [element 3] : | | array_flow.rb:612:9:612:9 | a [element 3] : | array_flow.rb:612:24:612:24 | x : | | array_flow.rb:612:9:612:9 | a [element 3] : | array_flow.rb:612:24:612:24 | x : | | array_flow.rb:612:24:612:24 | x : | array_flow.rb:613:14:613:14 | x | | array_flow.rb:612:24:612:24 | x : | array_flow.rb:613:14:613:14 | x | -| array_flow.rb:620:19:620:28 | call to source : | array_flow.rb:621:5:621:5 | a [element 3] : | -| array_flow.rb:620:19:620:28 | call to source : | array_flow.rb:621:5:621:5 | a [element 3] : | +| array_flow.rb:620:5:620:5 | a [element 3] : | array_flow.rb:621:5:621:5 | a [element 3] : | +| array_flow.rb:620:5:620:5 | a [element 3] : | array_flow.rb:621:5:621:5 | a [element 3] : | +| array_flow.rb:620:19:620:28 | call to source : | array_flow.rb:620:5:620:5 | a [element 3] : | +| array_flow.rb:620:19:620:28 | call to source : | array_flow.rb:620:5:620:5 | a [element 3] : | | array_flow.rb:621:5:621:5 | a [element 3] : | array_flow.rb:621:17:621:17 | x : | | array_flow.rb:621:5:621:5 | a [element 3] : | array_flow.rb:621:17:621:17 | x : | | array_flow.rb:621:17:621:17 | x : | array_flow.rb:622:14:622:14 | x | | array_flow.rb:621:17:621:17 | x : | array_flow.rb:622:14:622:14 | x | -| array_flow.rb:627:10:627:21 | call to source : | array_flow.rb:628:9:628:9 | a [element 0] : | -| array_flow.rb:627:10:627:21 | call to source : | array_flow.rb:628:9:628:9 | a [element 0] : | -| array_flow.rb:627:10:627:21 | call to source : | array_flow.rb:634:9:634:9 | a [element 0] : | -| array_flow.rb:627:10:627:21 | call to source : | array_flow.rb:634:9:634:9 | a [element 0] : | -| array_flow.rb:627:27:627:38 | call to source : | array_flow.rb:628:9:628:9 | a [element 2] : | -| array_flow.rb:627:27:627:38 | call to source : | array_flow.rb:628:9:628:9 | a [element 2] : | -| array_flow.rb:627:27:627:38 | call to source : | array_flow.rb:634:9:634:9 | a [element 2] : | -| array_flow.rb:627:27:627:38 | call to source : | array_flow.rb:634:9:634:9 | a [element 2] : | +| array_flow.rb:627:5:627:5 | a [element 0] : | array_flow.rb:628:9:628:9 | a [element 0] : | +| array_flow.rb:627:5:627:5 | a [element 0] : | array_flow.rb:628:9:628:9 | a [element 0] : | +| array_flow.rb:627:5:627:5 | a [element 0] : | array_flow.rb:634:9:634:9 | a [element 0] : | +| array_flow.rb:627:5:627:5 | a [element 0] : | array_flow.rb:634:9:634:9 | a [element 0] : | +| array_flow.rb:627:5:627:5 | a [element 2] : | array_flow.rb:628:9:628:9 | a [element 2] : | +| array_flow.rb:627:5:627:5 | a [element 2] : | array_flow.rb:628:9:628:9 | a [element 2] : | +| array_flow.rb:627:5:627:5 | a [element 2] : | array_flow.rb:634:9:634:9 | a [element 2] : | +| array_flow.rb:627:5:627:5 | a [element 2] : | array_flow.rb:634:9:634:9 | a [element 2] : | +| array_flow.rb:627:10:627:21 | call to source : | array_flow.rb:627:5:627:5 | a [element 0] : | +| array_flow.rb:627:10:627:21 | call to source : | array_flow.rb:627:5:627:5 | a [element 0] : | +| array_flow.rb:627:27:627:38 | call to source : | array_flow.rb:627:5:627:5 | a [element 2] : | +| array_flow.rb:627:27:627:38 | call to source : | array_flow.rb:627:5:627:5 | a [element 2] : | +| array_flow.rb:628:5:628:5 | b : | array_flow.rb:633:10:633:10 | b | +| array_flow.rb:628:5:628:5 | b : | array_flow.rb:633:10:633:10 | b | | array_flow.rb:628:9:628:9 | a [element 0] : | array_flow.rb:628:22:628:22 | x : | | array_flow.rb:628:9:628:9 | a [element 0] : | array_flow.rb:628:22:628:22 | x : | | array_flow.rb:628:9:628:9 | a [element 2] : | array_flow.rb:628:25:628:25 | y : | | array_flow.rb:628:9:628:9 | a [element 2] : | array_flow.rb:628:25:628:25 | y : | -| array_flow.rb:628:9:632:7 | call to inject : | array_flow.rb:633:10:633:10 | b | -| array_flow.rb:628:9:632:7 | call to inject : | array_flow.rb:633:10:633:10 | b | +| array_flow.rb:628:9:632:7 | call to inject : | array_flow.rb:628:5:628:5 | b : | +| array_flow.rb:628:9:632:7 | call to inject : | array_flow.rb:628:5:628:5 | b : | | array_flow.rb:628:22:628:22 | x : | array_flow.rb:629:14:629:14 | x | | array_flow.rb:628:22:628:22 | x : | array_flow.rb:629:14:629:14 | x | | array_flow.rb:628:25:628:25 | y : | array_flow.rb:630:14:630:14 | y | | array_flow.rb:628:25:628:25 | y : | array_flow.rb:630:14:630:14 | y | | array_flow.rb:631:9:631:19 | call to source : | array_flow.rb:628:9:632:7 | call to inject : | | array_flow.rb:631:9:631:19 | call to source : | array_flow.rb:628:9:632:7 | call to inject : | +| array_flow.rb:634:5:634:5 | c : | array_flow.rb:639:10:639:10 | c | +| array_flow.rb:634:5:634:5 | c : | array_flow.rb:639:10:639:10 | c | | array_flow.rb:634:9:634:9 | a [element 0] : | array_flow.rb:634:28:634:28 | y : | | array_flow.rb:634:9:634:9 | a [element 0] : | array_flow.rb:634:28:634:28 | y : | | array_flow.rb:634:9:634:9 | a [element 2] : | array_flow.rb:634:28:634:28 | y : | | array_flow.rb:634:9:634:9 | a [element 2] : | array_flow.rb:634:28:634:28 | y : | -| array_flow.rb:634:9:638:7 | call to inject : | array_flow.rb:639:10:639:10 | c | -| array_flow.rb:634:9:638:7 | call to inject : | array_flow.rb:639:10:639:10 | c | +| array_flow.rb:634:9:638:7 | call to inject : | array_flow.rb:634:5:634:5 | c : | +| array_flow.rb:634:9:638:7 | call to inject : | array_flow.rb:634:5:634:5 | c : | | array_flow.rb:634:28:634:28 | y : | array_flow.rb:636:14:636:14 | y | | array_flow.rb:634:28:634:28 | y : | array_flow.rb:636:14:636:14 | y | | array_flow.rb:637:9:637:19 | call to source : | array_flow.rb:634:9:638:7 | call to inject : | | array_flow.rb:637:9:637:19 | call to source : | array_flow.rb:634:9:638:7 | call to inject : | -| array_flow.rb:644:16:644:27 | call to source : | array_flow.rb:645:9:645:9 | a [element 2] : | -| array_flow.rb:644:16:644:27 | call to source : | array_flow.rb:645:9:645:9 | a [element 2] : | +| array_flow.rb:644:5:644:5 | a [element 2] : | array_flow.rb:645:9:645:9 | a [element 2] : | +| array_flow.rb:644:5:644:5 | a [element 2] : | array_flow.rb:645:9:645:9 | a [element 2] : | +| array_flow.rb:644:16:644:27 | call to source : | array_flow.rb:644:5:644:5 | a [element 2] : | +| array_flow.rb:644:16:644:27 | call to source : | array_flow.rb:644:5:644:5 | a [element 2] : | +| array_flow.rb:645:5:645:5 | b [element 1] : | array_flow.rb:652:10:652:10 | b [element 1] : | +| array_flow.rb:645:5:645:5 | b [element 1] : | array_flow.rb:652:10:652:10 | b [element 1] : | +| array_flow.rb:645:5:645:5 | b [element 2] : | array_flow.rb:653:10:653:10 | b [element 2] : | +| array_flow.rb:645:5:645:5 | b [element 2] : | array_flow.rb:653:10:653:10 | b [element 2] : | +| array_flow.rb:645:5:645:5 | b [element 4] : | array_flow.rb:655:10:655:10 | b [element 4] : | +| array_flow.rb:645:5:645:5 | b [element 4] : | array_flow.rb:655:10:655:10 | b [element 4] : | | array_flow.rb:645:9:645:9 | [post] a [element 1] : | array_flow.rb:647:10:647:10 | a [element 1] : | | array_flow.rb:645:9:645:9 | [post] a [element 1] : | array_flow.rb:647:10:647:10 | a [element 1] : | | array_flow.rb:645:9:645:9 | [post] a [element 2] : | array_flow.rb:648:10:648:10 | a [element 2] : | @@ -1168,12 +1489,12 @@ edges | array_flow.rb:645:9:645:9 | a [element 2] : | array_flow.rb:645:9:645:9 | [post] a [element 4] : | | array_flow.rb:645:9:645:9 | a [element 2] : | array_flow.rb:645:9:645:47 | call to insert [element 4] : | | array_flow.rb:645:9:645:9 | a [element 2] : | array_flow.rb:645:9:645:47 | call to insert [element 4] : | -| array_flow.rb:645:9:645:47 | call to insert [element 1] : | array_flow.rb:652:10:652:10 | b [element 1] : | -| array_flow.rb:645:9:645:47 | call to insert [element 1] : | array_flow.rb:652:10:652:10 | b [element 1] : | -| array_flow.rb:645:9:645:47 | call to insert [element 2] : | array_flow.rb:653:10:653:10 | b [element 2] : | -| array_flow.rb:645:9:645:47 | call to insert [element 2] : | array_flow.rb:653:10:653:10 | b [element 2] : | -| array_flow.rb:645:9:645:47 | call to insert [element 4] : | array_flow.rb:655:10:655:10 | b [element 4] : | -| array_flow.rb:645:9:645:47 | call to insert [element 4] : | array_flow.rb:655:10:655:10 | b [element 4] : | +| array_flow.rb:645:9:645:47 | call to insert [element 1] : | array_flow.rb:645:5:645:5 | b [element 1] : | +| array_flow.rb:645:9:645:47 | call to insert [element 1] : | array_flow.rb:645:5:645:5 | b [element 1] : | +| array_flow.rb:645:9:645:47 | call to insert [element 2] : | array_flow.rb:645:5:645:5 | b [element 2] : | +| array_flow.rb:645:9:645:47 | call to insert [element 2] : | array_flow.rb:645:5:645:5 | b [element 2] : | +| array_flow.rb:645:9:645:47 | call to insert [element 4] : | array_flow.rb:645:5:645:5 | b [element 4] : | +| array_flow.rb:645:9:645:47 | call to insert [element 4] : | array_flow.rb:645:5:645:5 | b [element 4] : | | array_flow.rb:645:21:645:32 | call to source : | array_flow.rb:645:9:645:9 | [post] a [element 1] : | | array_flow.rb:645:21:645:32 | call to source : | array_flow.rb:645:9:645:9 | [post] a [element 1] : | | array_flow.rb:645:21:645:32 | call to source : | array_flow.rb:645:9:645:47 | call to insert [element 1] : | @@ -1194,16 +1515,20 @@ edges | array_flow.rb:653:10:653:10 | b [element 2] : | array_flow.rb:653:10:653:13 | ...[...] | | array_flow.rb:655:10:655:10 | b [element 4] : | array_flow.rb:655:10:655:13 | ...[...] | | array_flow.rb:655:10:655:10 | b [element 4] : | array_flow.rb:655:10:655:13 | ...[...] | -| array_flow.rb:658:16:658:27 | call to source : | array_flow.rb:659:9:659:9 | c [element 2] : | -| array_flow.rb:658:16:658:27 | call to source : | array_flow.rb:659:9:659:9 | c [element 2] : | +| array_flow.rb:658:5:658:5 | c [element 2] : | array_flow.rb:659:9:659:9 | c [element 2] : | +| array_flow.rb:658:5:658:5 | c [element 2] : | array_flow.rb:659:9:659:9 | c [element 2] : | +| array_flow.rb:658:16:658:27 | call to source : | array_flow.rb:658:5:658:5 | c [element 2] : | +| array_flow.rb:658:16:658:27 | call to source : | array_flow.rb:658:5:658:5 | c [element 2] : | +| array_flow.rb:659:5:659:5 | d [element] : | array_flow.rb:661:10:661:10 | d [element] : | +| array_flow.rb:659:5:659:5 | d [element] : | array_flow.rb:661:10:661:10 | d [element] : | | array_flow.rb:659:9:659:9 | [post] c [element] : | array_flow.rb:660:10:660:10 | c [element] : | | array_flow.rb:659:9:659:9 | [post] c [element] : | array_flow.rb:660:10:660:10 | c [element] : | | array_flow.rb:659:9:659:9 | c [element 2] : | array_flow.rb:659:9:659:9 | [post] c [element] : | | array_flow.rb:659:9:659:9 | c [element 2] : | array_flow.rb:659:9:659:9 | [post] c [element] : | | array_flow.rb:659:9:659:9 | c [element 2] : | array_flow.rb:659:9:659:47 | call to insert [element] : | | array_flow.rb:659:9:659:9 | c [element 2] : | array_flow.rb:659:9:659:47 | call to insert [element] : | -| array_flow.rb:659:9:659:47 | call to insert [element] : | array_flow.rb:661:10:661:10 | d [element] : | -| array_flow.rb:659:9:659:47 | call to insert [element] : | array_flow.rb:661:10:661:10 | d [element] : | +| array_flow.rb:659:9:659:47 | call to insert [element] : | array_flow.rb:659:5:659:5 | d [element] : | +| array_flow.rb:659:9:659:47 | call to insert [element] : | array_flow.rb:659:5:659:5 | d [element] : | | array_flow.rb:659:21:659:32 | call to source : | array_flow.rb:659:9:659:9 | [post] c [element] : | | array_flow.rb:659:21:659:32 | call to source : | array_flow.rb:659:9:659:9 | [post] c [element] : | | array_flow.rb:659:21:659:32 | call to source : | array_flow.rb:659:9:659:47 | call to insert [element] : | @@ -1216,20 +1541,28 @@ edges | array_flow.rb:660:10:660:10 | c [element] : | array_flow.rb:660:10:660:13 | ...[...] | | array_flow.rb:661:10:661:10 | d [element] : | array_flow.rb:661:10:661:13 | ...[...] | | array_flow.rb:661:10:661:10 | d [element] : | array_flow.rb:661:10:661:13 | ...[...] | -| array_flow.rb:672:16:672:27 | call to source : | array_flow.rb:673:9:673:9 | a [element 2] : | -| array_flow.rb:672:16:672:27 | call to source : | array_flow.rb:673:9:673:9 | a [element 2] : | +| array_flow.rb:672:5:672:5 | a [element 2] : | array_flow.rb:673:9:673:9 | a [element 2] : | +| array_flow.rb:672:5:672:5 | a [element 2] : | array_flow.rb:673:9:673:9 | a [element 2] : | +| array_flow.rb:672:16:672:27 | call to source : | array_flow.rb:672:5:672:5 | a [element 2] : | +| array_flow.rb:672:16:672:27 | call to source : | array_flow.rb:672:5:672:5 | a [element 2] : | +| array_flow.rb:673:5:673:5 | b [element] : | array_flow.rb:674:10:674:10 | b [element] : | +| array_flow.rb:673:5:673:5 | b [element] : | array_flow.rb:674:10:674:10 | b [element] : | | array_flow.rb:673:9:673:9 | a [element 2] : | array_flow.rb:673:9:673:60 | call to intersection [element] : | | array_flow.rb:673:9:673:9 | a [element 2] : | array_flow.rb:673:9:673:60 | call to intersection [element] : | -| array_flow.rb:673:9:673:60 | call to intersection [element] : | array_flow.rb:674:10:674:10 | b [element] : | -| array_flow.rb:673:9:673:60 | call to intersection [element] : | array_flow.rb:674:10:674:10 | b [element] : | +| array_flow.rb:673:9:673:60 | call to intersection [element] : | array_flow.rb:673:5:673:5 | b [element] : | +| array_flow.rb:673:9:673:60 | call to intersection [element] : | array_flow.rb:673:5:673:5 | b [element] : | | array_flow.rb:673:31:673:42 | call to source : | array_flow.rb:673:9:673:60 | call to intersection [element] : | | array_flow.rb:673:31:673:42 | call to source : | array_flow.rb:673:9:673:60 | call to intersection [element] : | | array_flow.rb:673:47:673:58 | call to source : | array_flow.rb:673:9:673:60 | call to intersection [element] : | | array_flow.rb:673:47:673:58 | call to source : | array_flow.rb:673:9:673:60 | call to intersection [element] : | | array_flow.rb:674:10:674:10 | b [element] : | array_flow.rb:674:10:674:13 | ...[...] | | array_flow.rb:674:10:674:10 | b [element] : | array_flow.rb:674:10:674:13 | ...[...] | -| array_flow.rb:678:16:678:25 | call to source : | array_flow.rb:679:9:679:9 | a [element 2] : | -| array_flow.rb:678:16:678:25 | call to source : | array_flow.rb:679:9:679:9 | a [element 2] : | +| array_flow.rb:678:5:678:5 | a [element 2] : | array_flow.rb:679:9:679:9 | a [element 2] : | +| array_flow.rb:678:5:678:5 | a [element 2] : | array_flow.rb:679:9:679:9 | a [element 2] : | +| array_flow.rb:678:16:678:25 | call to source : | array_flow.rb:678:5:678:5 | a [element 2] : | +| array_flow.rb:678:16:678:25 | call to source : | array_flow.rb:678:5:678:5 | a [element 2] : | +| array_flow.rb:679:5:679:5 | b [element] : | array_flow.rb:684:10:684:10 | b [element] : | +| array_flow.rb:679:5:679:5 | b [element] : | array_flow.rb:684:10:684:10 | b [element] : | | array_flow.rb:679:9:679:9 | [post] a [element] : | array_flow.rb:683:10:683:10 | a [element] : | | array_flow.rb:679:9:679:9 | [post] a [element] : | array_flow.rb:683:10:683:10 | a [element] : | | array_flow.rb:679:9:679:9 | a [element 2] : | array_flow.rb:679:9:679:9 | [post] a [element] : | @@ -1238,18 +1571,20 @@ edges | array_flow.rb:679:9:679:9 | a [element 2] : | array_flow.rb:679:9:682:7 | call to keep_if [element] : | | array_flow.rb:679:9:679:9 | a [element 2] : | array_flow.rb:679:23:679:23 | x : | | array_flow.rb:679:9:679:9 | a [element 2] : | array_flow.rb:679:23:679:23 | x : | -| array_flow.rb:679:9:682:7 | call to keep_if [element] : | array_flow.rb:684:10:684:10 | b [element] : | -| array_flow.rb:679:9:682:7 | call to keep_if [element] : | array_flow.rb:684:10:684:10 | b [element] : | +| array_flow.rb:679:9:682:7 | call to keep_if [element] : | array_flow.rb:679:5:679:5 | b [element] : | +| array_flow.rb:679:9:682:7 | call to keep_if [element] : | array_flow.rb:679:5:679:5 | b [element] : | | array_flow.rb:679:23:679:23 | x : | array_flow.rb:680:14:680:14 | x | | array_flow.rb:679:23:679:23 | x : | array_flow.rb:680:14:680:14 | x | | array_flow.rb:683:10:683:10 | a [element] : | array_flow.rb:683:10:683:13 | ...[...] | | array_flow.rb:683:10:683:10 | a [element] : | array_flow.rb:683:10:683:13 | ...[...] | | array_flow.rb:684:10:684:10 | b [element] : | array_flow.rb:684:10:684:13 | ...[...] | | array_flow.rb:684:10:684:10 | b [element] : | array_flow.rb:684:10:684:13 | ...[...] | -| array_flow.rb:688:16:688:27 | call to source : | array_flow.rb:690:10:690:10 | a [element 2] : | -| array_flow.rb:688:16:688:27 | call to source : | array_flow.rb:690:10:690:10 | a [element 2] : | -| array_flow.rb:688:16:688:27 | call to source : | array_flow.rb:691:9:691:9 | a [element 2] : | -| array_flow.rb:688:16:688:27 | call to source : | array_flow.rb:691:9:691:9 | a [element 2] : | +| array_flow.rb:688:5:688:5 | a [element 2] : | array_flow.rb:690:10:690:10 | a [element 2] : | +| array_flow.rb:688:5:688:5 | a [element 2] : | array_flow.rb:690:10:690:10 | a [element 2] : | +| array_flow.rb:688:5:688:5 | a [element 2] : | array_flow.rb:691:9:691:9 | a [element 2] : | +| array_flow.rb:688:5:688:5 | a [element 2] : | array_flow.rb:691:9:691:9 | a [element 2] : | +| array_flow.rb:688:16:688:27 | call to source : | array_flow.rb:688:5:688:5 | a [element 2] : | +| array_flow.rb:688:16:688:27 | call to source : | array_flow.rb:688:5:688:5 | a [element 2] : | | array_flow.rb:689:5:689:5 | [post] a [element] : | array_flow.rb:690:10:690:10 | a [element] : | | array_flow.rb:689:5:689:5 | [post] a [element] : | array_flow.rb:690:10:690:10 | a [element] : | | array_flow.rb:689:5:689:5 | [post] a [element] : | array_flow.rb:691:9:691:9 | a [element] : | @@ -1260,198 +1595,246 @@ edges | array_flow.rb:690:10:690:10 | a [element 2] : | array_flow.rb:690:10:690:15 | call to last | | array_flow.rb:690:10:690:10 | a [element] : | array_flow.rb:690:10:690:15 | call to last | | array_flow.rb:690:10:690:10 | a [element] : | array_flow.rb:690:10:690:15 | call to last | +| array_flow.rb:691:5:691:5 | b [element] : | array_flow.rb:692:10:692:10 | b [element] : | +| array_flow.rb:691:5:691:5 | b [element] : | array_flow.rb:692:10:692:10 | b [element] : | +| array_flow.rb:691:5:691:5 | b [element] : | array_flow.rb:693:10:693:10 | b [element] : | +| array_flow.rb:691:5:691:5 | b [element] : | array_flow.rb:693:10:693:10 | b [element] : | | array_flow.rb:691:9:691:9 | a [element 2] : | array_flow.rb:691:9:691:17 | call to last [element] : | | array_flow.rb:691:9:691:9 | a [element 2] : | array_flow.rb:691:9:691:17 | call to last [element] : | | array_flow.rb:691:9:691:9 | a [element] : | array_flow.rb:691:9:691:17 | call to last [element] : | | array_flow.rb:691:9:691:9 | a [element] : | array_flow.rb:691:9:691:17 | call to last [element] : | -| array_flow.rb:691:9:691:17 | call to last [element] : | array_flow.rb:692:10:692:10 | b [element] : | -| array_flow.rb:691:9:691:17 | call to last [element] : | array_flow.rb:692:10:692:10 | b [element] : | -| array_flow.rb:691:9:691:17 | call to last [element] : | array_flow.rb:693:10:693:10 | b [element] : | -| array_flow.rb:691:9:691:17 | call to last [element] : | array_flow.rb:693:10:693:10 | b [element] : | +| array_flow.rb:691:9:691:17 | call to last [element] : | array_flow.rb:691:5:691:5 | b [element] : | +| array_flow.rb:691:9:691:17 | call to last [element] : | array_flow.rb:691:5:691:5 | b [element] : | | array_flow.rb:692:10:692:10 | b [element] : | array_flow.rb:692:10:692:13 | ...[...] | | array_flow.rb:692:10:692:10 | b [element] : | array_flow.rb:692:10:692:13 | ...[...] | | array_flow.rb:693:10:693:10 | b [element] : | array_flow.rb:693:10:693:13 | ...[...] | | array_flow.rb:693:10:693:10 | b [element] : | array_flow.rb:693:10:693:13 | ...[...] | -| array_flow.rb:697:16:697:27 | call to source : | array_flow.rb:698:9:698:9 | a [element 2] : | -| array_flow.rb:697:16:697:27 | call to source : | array_flow.rb:698:9:698:9 | a [element 2] : | +| array_flow.rb:697:5:697:5 | a [element 2] : | array_flow.rb:698:9:698:9 | a [element 2] : | +| array_flow.rb:697:5:697:5 | a [element 2] : | array_flow.rb:698:9:698:9 | a [element 2] : | +| array_flow.rb:697:16:697:27 | call to source : | array_flow.rb:697:5:697:5 | a [element 2] : | +| array_flow.rb:697:16:697:27 | call to source : | array_flow.rb:697:5:697:5 | a [element 2] : | +| array_flow.rb:698:5:698:5 | b [element] : | array_flow.rb:702:10:702:10 | b [element] : | +| array_flow.rb:698:5:698:5 | b [element] : | array_flow.rb:702:10:702:10 | b [element] : | | array_flow.rb:698:9:698:9 | a [element 2] : | array_flow.rb:698:19:698:19 | x : | | array_flow.rb:698:9:698:9 | a [element 2] : | array_flow.rb:698:19:698:19 | x : | -| array_flow.rb:698:9:701:7 | call to map [element] : | array_flow.rb:702:10:702:10 | b [element] : | -| array_flow.rb:698:9:701:7 | call to map [element] : | array_flow.rb:702:10:702:10 | b [element] : | +| array_flow.rb:698:9:701:7 | call to map [element] : | array_flow.rb:698:5:698:5 | b [element] : | +| array_flow.rb:698:9:701:7 | call to map [element] : | array_flow.rb:698:5:698:5 | b [element] : | | array_flow.rb:698:19:698:19 | x : | array_flow.rb:699:14:699:14 | x | | array_flow.rb:698:19:698:19 | x : | array_flow.rb:699:14:699:14 | x | | array_flow.rb:700:9:700:19 | call to source : | array_flow.rb:698:9:701:7 | call to map [element] : | | array_flow.rb:700:9:700:19 | call to source : | array_flow.rb:698:9:701:7 | call to map [element] : | | array_flow.rb:702:10:702:10 | b [element] : | array_flow.rb:702:10:702:13 | ...[...] | | array_flow.rb:702:10:702:10 | b [element] : | array_flow.rb:702:10:702:13 | ...[...] | -| array_flow.rb:706:16:706:27 | call to source : | array_flow.rb:707:9:707:9 | a [element 2] : | -| array_flow.rb:706:16:706:27 | call to source : | array_flow.rb:707:9:707:9 | a [element 2] : | +| array_flow.rb:706:5:706:5 | a [element 2] : | array_flow.rb:707:9:707:9 | a [element 2] : | +| array_flow.rb:706:5:706:5 | a [element 2] : | array_flow.rb:707:9:707:9 | a [element 2] : | +| array_flow.rb:706:16:706:27 | call to source : | array_flow.rb:706:5:706:5 | a [element 2] : | +| array_flow.rb:706:16:706:27 | call to source : | array_flow.rb:706:5:706:5 | a [element 2] : | +| array_flow.rb:707:5:707:5 | b [element] : | array_flow.rb:711:10:711:10 | b [element] : | +| array_flow.rb:707:5:707:5 | b [element] : | array_flow.rb:711:10:711:10 | b [element] : | | array_flow.rb:707:9:707:9 | a [element 2] : | array_flow.rb:707:20:707:20 | x : | | array_flow.rb:707:9:707:9 | a [element 2] : | array_flow.rb:707:20:707:20 | x : | -| array_flow.rb:707:9:710:7 | call to map! [element] : | array_flow.rb:711:10:711:10 | b [element] : | -| array_flow.rb:707:9:710:7 | call to map! [element] : | array_flow.rb:711:10:711:10 | b [element] : | +| array_flow.rb:707:9:710:7 | call to map! [element] : | array_flow.rb:707:5:707:5 | b [element] : | +| array_flow.rb:707:9:710:7 | call to map! [element] : | array_flow.rb:707:5:707:5 | b [element] : | | array_flow.rb:707:20:707:20 | x : | array_flow.rb:708:14:708:14 | x | | array_flow.rb:707:20:707:20 | x : | array_flow.rb:708:14:708:14 | x | | array_flow.rb:709:9:709:19 | call to source : | array_flow.rb:707:9:710:7 | call to map! [element] : | | array_flow.rb:709:9:709:19 | call to source : | array_flow.rb:707:9:710:7 | call to map! [element] : | | array_flow.rb:711:10:711:10 | b [element] : | array_flow.rb:711:10:711:13 | ...[...] | | array_flow.rb:711:10:711:10 | b [element] : | array_flow.rb:711:10:711:13 | ...[...] | -| array_flow.rb:715:16:715:25 | call to source : | array_flow.rb:718:9:718:9 | a [element 2] : | -| array_flow.rb:715:16:715:25 | call to source : | array_flow.rb:718:9:718:9 | a [element 2] : | -| array_flow.rb:715:16:715:25 | call to source : | array_flow.rb:722:9:722:9 | a [element 2] : | -| array_flow.rb:715:16:715:25 | call to source : | array_flow.rb:722:9:722:9 | a [element 2] : | -| array_flow.rb:715:16:715:25 | call to source : | array_flow.rb:726:9:726:9 | a [element 2] : | -| array_flow.rb:715:16:715:25 | call to source : | array_flow.rb:726:9:726:9 | a [element 2] : | -| array_flow.rb:715:16:715:25 | call to source : | array_flow.rb:734:9:734:9 | a [element 2] : | -| array_flow.rb:715:16:715:25 | call to source : | array_flow.rb:734:9:734:9 | a [element 2] : | +| array_flow.rb:715:5:715:5 | a [element 2] : | array_flow.rb:718:9:718:9 | a [element 2] : | +| array_flow.rb:715:5:715:5 | a [element 2] : | array_flow.rb:718:9:718:9 | a [element 2] : | +| array_flow.rb:715:5:715:5 | a [element 2] : | array_flow.rb:722:9:722:9 | a [element 2] : | +| array_flow.rb:715:5:715:5 | a [element 2] : | array_flow.rb:722:9:722:9 | a [element 2] : | +| array_flow.rb:715:5:715:5 | a [element 2] : | array_flow.rb:726:9:726:9 | a [element 2] : | +| array_flow.rb:715:5:715:5 | a [element 2] : | array_flow.rb:726:9:726:9 | a [element 2] : | +| array_flow.rb:715:5:715:5 | a [element 2] : | array_flow.rb:734:9:734:9 | a [element 2] : | +| array_flow.rb:715:5:715:5 | a [element 2] : | array_flow.rb:734:9:734:9 | a [element 2] : | +| array_flow.rb:715:16:715:25 | call to source : | array_flow.rb:715:5:715:5 | a [element 2] : | +| array_flow.rb:715:16:715:25 | call to source : | array_flow.rb:715:5:715:5 | a [element 2] : | +| array_flow.rb:718:5:718:5 | b : | array_flow.rb:719:10:719:10 | b | +| array_flow.rb:718:5:718:5 | b : | array_flow.rb:719:10:719:10 | b | | array_flow.rb:718:9:718:9 | a [element 2] : | array_flow.rb:718:9:718:13 | call to max : | | array_flow.rb:718:9:718:9 | a [element 2] : | array_flow.rb:718:9:718:13 | call to max : | -| array_flow.rb:718:9:718:13 | call to max : | array_flow.rb:719:10:719:10 | b | -| array_flow.rb:718:9:718:13 | call to max : | array_flow.rb:719:10:719:10 | b | +| array_flow.rb:718:9:718:13 | call to max : | array_flow.rb:718:5:718:5 | b : | +| array_flow.rb:718:9:718:13 | call to max : | array_flow.rb:718:5:718:5 | b : | +| array_flow.rb:722:5:722:5 | c [element] : | array_flow.rb:723:10:723:10 | c [element] : | +| array_flow.rb:722:5:722:5 | c [element] : | array_flow.rb:723:10:723:10 | c [element] : | | array_flow.rb:722:9:722:9 | a [element 2] : | array_flow.rb:722:9:722:16 | call to max [element] : | | array_flow.rb:722:9:722:9 | a [element 2] : | array_flow.rb:722:9:722:16 | call to max [element] : | -| array_flow.rb:722:9:722:16 | call to max [element] : | array_flow.rb:723:10:723:10 | c [element] : | -| array_flow.rb:722:9:722:16 | call to max [element] : | array_flow.rb:723:10:723:10 | c [element] : | +| array_flow.rb:722:9:722:16 | call to max [element] : | array_flow.rb:722:5:722:5 | c [element] : | +| array_flow.rb:722:9:722:16 | call to max [element] : | array_flow.rb:722:5:722:5 | c [element] : | | array_flow.rb:723:10:723:10 | c [element] : | array_flow.rb:723:10:723:13 | ...[...] | | array_flow.rb:723:10:723:10 | c [element] : | array_flow.rb:723:10:723:13 | ...[...] | +| array_flow.rb:726:5:726:5 | d : | array_flow.rb:731:10:731:10 | d | +| array_flow.rb:726:5:726:5 | d : | array_flow.rb:731:10:731:10 | d | | array_flow.rb:726:9:726:9 | a [element 2] : | array_flow.rb:726:9:730:7 | call to max : | | array_flow.rb:726:9:726:9 | a [element 2] : | array_flow.rb:726:9:730:7 | call to max : | | array_flow.rb:726:9:726:9 | a [element 2] : | array_flow.rb:726:19:726:19 | x : | | array_flow.rb:726:9:726:9 | a [element 2] : | array_flow.rb:726:19:726:19 | x : | | array_flow.rb:726:9:726:9 | a [element 2] : | array_flow.rb:726:22:726:22 | y : | | array_flow.rb:726:9:726:9 | a [element 2] : | array_flow.rb:726:22:726:22 | y : | -| array_flow.rb:726:9:730:7 | call to max : | array_flow.rb:731:10:731:10 | d | -| array_flow.rb:726:9:730:7 | call to max : | array_flow.rb:731:10:731:10 | d | +| array_flow.rb:726:9:730:7 | call to max : | array_flow.rb:726:5:726:5 | d : | +| array_flow.rb:726:9:730:7 | call to max : | array_flow.rb:726:5:726:5 | d : | | array_flow.rb:726:19:726:19 | x : | array_flow.rb:727:14:727:14 | x | | array_flow.rb:726:19:726:19 | x : | array_flow.rb:727:14:727:14 | x | | array_flow.rb:726:22:726:22 | y : | array_flow.rb:728:14:728:14 | y | | array_flow.rb:726:22:726:22 | y : | array_flow.rb:728:14:728:14 | y | +| array_flow.rb:734:5:734:5 | e [element] : | array_flow.rb:739:10:739:10 | e [element] : | +| array_flow.rb:734:5:734:5 | e [element] : | array_flow.rb:739:10:739:10 | e [element] : | | array_flow.rb:734:9:734:9 | a [element 2] : | array_flow.rb:734:9:738:7 | call to max [element] : | | array_flow.rb:734:9:734:9 | a [element 2] : | array_flow.rb:734:9:738:7 | call to max [element] : | | array_flow.rb:734:9:734:9 | a [element 2] : | array_flow.rb:734:22:734:22 | x : | | array_flow.rb:734:9:734:9 | a [element 2] : | array_flow.rb:734:22:734:22 | x : | | array_flow.rb:734:9:734:9 | a [element 2] : | array_flow.rb:734:25:734:25 | y : | | array_flow.rb:734:9:734:9 | a [element 2] : | array_flow.rb:734:25:734:25 | y : | -| array_flow.rb:734:9:738:7 | call to max [element] : | array_flow.rb:739:10:739:10 | e [element] : | -| array_flow.rb:734:9:738:7 | call to max [element] : | array_flow.rb:739:10:739:10 | e [element] : | +| array_flow.rb:734:9:738:7 | call to max [element] : | array_flow.rb:734:5:734:5 | e [element] : | +| array_flow.rb:734:9:738:7 | call to max [element] : | array_flow.rb:734:5:734:5 | e [element] : | | array_flow.rb:734:22:734:22 | x : | array_flow.rb:735:14:735:14 | x | | array_flow.rb:734:22:734:22 | x : | array_flow.rb:735:14:735:14 | x | | array_flow.rb:734:25:734:25 | y : | array_flow.rb:736:14:736:14 | y | | array_flow.rb:734:25:734:25 | y : | array_flow.rb:736:14:736:14 | y | | array_flow.rb:739:10:739:10 | e [element] : | array_flow.rb:739:10:739:13 | ...[...] | | array_flow.rb:739:10:739:10 | e [element] : | array_flow.rb:739:10:739:13 | ...[...] | -| array_flow.rb:743:16:743:25 | call to source : | array_flow.rb:746:9:746:9 | a [element 2] : | -| array_flow.rb:743:16:743:25 | call to source : | array_flow.rb:746:9:746:9 | a [element 2] : | -| array_flow.rb:743:16:743:25 | call to source : | array_flow.rb:753:9:753:9 | a [element 2] : | -| array_flow.rb:743:16:743:25 | call to source : | array_flow.rb:753:9:753:9 | a [element 2] : | +| array_flow.rb:743:5:743:5 | a [element 2] : | array_flow.rb:746:9:746:9 | a [element 2] : | +| array_flow.rb:743:5:743:5 | a [element 2] : | array_flow.rb:746:9:746:9 | a [element 2] : | +| array_flow.rb:743:5:743:5 | a [element 2] : | array_flow.rb:753:9:753:9 | a [element 2] : | +| array_flow.rb:743:5:743:5 | a [element 2] : | array_flow.rb:753:9:753:9 | a [element 2] : | +| array_flow.rb:743:16:743:25 | call to source : | array_flow.rb:743:5:743:5 | a [element 2] : | +| array_flow.rb:743:16:743:25 | call to source : | array_flow.rb:743:5:743:5 | a [element 2] : | +| array_flow.rb:746:5:746:5 | b : | array_flow.rb:750:10:750:10 | b | +| array_flow.rb:746:5:746:5 | b : | array_flow.rb:750:10:750:10 | b | | array_flow.rb:746:9:746:9 | a [element 2] : | array_flow.rb:746:9:749:7 | call to max_by : | | array_flow.rb:746:9:746:9 | a [element 2] : | array_flow.rb:746:9:749:7 | call to max_by : | | array_flow.rb:746:9:746:9 | a [element 2] : | array_flow.rb:746:22:746:22 | x : | | array_flow.rb:746:9:746:9 | a [element 2] : | array_flow.rb:746:22:746:22 | x : | -| array_flow.rb:746:9:749:7 | call to max_by : | array_flow.rb:750:10:750:10 | b | -| array_flow.rb:746:9:749:7 | call to max_by : | array_flow.rb:750:10:750:10 | b | +| array_flow.rb:746:9:749:7 | call to max_by : | array_flow.rb:746:5:746:5 | b : | +| array_flow.rb:746:9:749:7 | call to max_by : | array_flow.rb:746:5:746:5 | b : | | array_flow.rb:746:22:746:22 | x : | array_flow.rb:747:14:747:14 | x | | array_flow.rb:746:22:746:22 | x : | array_flow.rb:747:14:747:14 | x | +| array_flow.rb:753:5:753:5 | c [element] : | array_flow.rb:757:10:757:10 | c [element] : | +| array_flow.rb:753:5:753:5 | c [element] : | array_flow.rb:757:10:757:10 | c [element] : | | array_flow.rb:753:9:753:9 | a [element 2] : | array_flow.rb:753:9:756:7 | call to max_by [element] : | | array_flow.rb:753:9:753:9 | a [element 2] : | array_flow.rb:753:9:756:7 | call to max_by [element] : | | array_flow.rb:753:9:753:9 | a [element 2] : | array_flow.rb:753:25:753:25 | x : | | array_flow.rb:753:9:753:9 | a [element 2] : | array_flow.rb:753:25:753:25 | x : | -| array_flow.rb:753:9:756:7 | call to max_by [element] : | array_flow.rb:757:10:757:10 | c [element] : | -| array_flow.rb:753:9:756:7 | call to max_by [element] : | array_flow.rb:757:10:757:10 | c [element] : | +| array_flow.rb:753:9:756:7 | call to max_by [element] : | array_flow.rb:753:5:753:5 | c [element] : | +| array_flow.rb:753:9:756:7 | call to max_by [element] : | array_flow.rb:753:5:753:5 | c [element] : | | array_flow.rb:753:25:753:25 | x : | array_flow.rb:754:14:754:14 | x | | array_flow.rb:753:25:753:25 | x : | array_flow.rb:754:14:754:14 | x | | array_flow.rb:757:10:757:10 | c [element] : | array_flow.rb:757:10:757:13 | ...[...] | | array_flow.rb:757:10:757:10 | c [element] : | array_flow.rb:757:10:757:13 | ...[...] | -| array_flow.rb:761:16:761:25 | call to source : | array_flow.rb:764:9:764:9 | a [element 2] : | -| array_flow.rb:761:16:761:25 | call to source : | array_flow.rb:764:9:764:9 | a [element 2] : | -| array_flow.rb:761:16:761:25 | call to source : | array_flow.rb:768:9:768:9 | a [element 2] : | -| array_flow.rb:761:16:761:25 | call to source : | array_flow.rb:768:9:768:9 | a [element 2] : | -| array_flow.rb:761:16:761:25 | call to source : | array_flow.rb:772:9:772:9 | a [element 2] : | -| array_flow.rb:761:16:761:25 | call to source : | array_flow.rb:772:9:772:9 | a [element 2] : | -| array_flow.rb:761:16:761:25 | call to source : | array_flow.rb:780:9:780:9 | a [element 2] : | -| array_flow.rb:761:16:761:25 | call to source : | array_flow.rb:780:9:780:9 | a [element 2] : | +| array_flow.rb:761:5:761:5 | a [element 2] : | array_flow.rb:764:9:764:9 | a [element 2] : | +| array_flow.rb:761:5:761:5 | a [element 2] : | array_flow.rb:764:9:764:9 | a [element 2] : | +| array_flow.rb:761:5:761:5 | a [element 2] : | array_flow.rb:768:9:768:9 | a [element 2] : | +| array_flow.rb:761:5:761:5 | a [element 2] : | array_flow.rb:768:9:768:9 | a [element 2] : | +| array_flow.rb:761:5:761:5 | a [element 2] : | array_flow.rb:772:9:772:9 | a [element 2] : | +| array_flow.rb:761:5:761:5 | a [element 2] : | array_flow.rb:772:9:772:9 | a [element 2] : | +| array_flow.rb:761:5:761:5 | a [element 2] : | array_flow.rb:780:9:780:9 | a [element 2] : | +| array_flow.rb:761:5:761:5 | a [element 2] : | array_flow.rb:780:9:780:9 | a [element 2] : | +| array_flow.rb:761:16:761:25 | call to source : | array_flow.rb:761:5:761:5 | a [element 2] : | +| array_flow.rb:761:16:761:25 | call to source : | array_flow.rb:761:5:761:5 | a [element 2] : | +| array_flow.rb:764:5:764:5 | b : | array_flow.rb:765:10:765:10 | b | +| array_flow.rb:764:5:764:5 | b : | array_flow.rb:765:10:765:10 | b | | array_flow.rb:764:9:764:9 | a [element 2] : | array_flow.rb:764:9:764:13 | call to min : | | array_flow.rb:764:9:764:9 | a [element 2] : | array_flow.rb:764:9:764:13 | call to min : | -| array_flow.rb:764:9:764:13 | call to min : | array_flow.rb:765:10:765:10 | b | -| array_flow.rb:764:9:764:13 | call to min : | array_flow.rb:765:10:765:10 | b | +| array_flow.rb:764:9:764:13 | call to min : | array_flow.rb:764:5:764:5 | b : | +| array_flow.rb:764:9:764:13 | call to min : | array_flow.rb:764:5:764:5 | b : | +| array_flow.rb:768:5:768:5 | c [element] : | array_flow.rb:769:10:769:10 | c [element] : | +| array_flow.rb:768:5:768:5 | c [element] : | array_flow.rb:769:10:769:10 | c [element] : | | array_flow.rb:768:9:768:9 | a [element 2] : | array_flow.rb:768:9:768:16 | call to min [element] : | | array_flow.rb:768:9:768:9 | a [element 2] : | array_flow.rb:768:9:768:16 | call to min [element] : | -| array_flow.rb:768:9:768:16 | call to min [element] : | array_flow.rb:769:10:769:10 | c [element] : | -| array_flow.rb:768:9:768:16 | call to min [element] : | array_flow.rb:769:10:769:10 | c [element] : | +| array_flow.rb:768:9:768:16 | call to min [element] : | array_flow.rb:768:5:768:5 | c [element] : | +| array_flow.rb:768:9:768:16 | call to min [element] : | array_flow.rb:768:5:768:5 | c [element] : | | array_flow.rb:769:10:769:10 | c [element] : | array_flow.rb:769:10:769:13 | ...[...] | | array_flow.rb:769:10:769:10 | c [element] : | array_flow.rb:769:10:769:13 | ...[...] | +| array_flow.rb:772:5:772:5 | d : | array_flow.rb:777:10:777:10 | d | +| array_flow.rb:772:5:772:5 | d : | array_flow.rb:777:10:777:10 | d | | array_flow.rb:772:9:772:9 | a [element 2] : | array_flow.rb:772:9:776:7 | call to min : | | array_flow.rb:772:9:772:9 | a [element 2] : | array_flow.rb:772:9:776:7 | call to min : | | array_flow.rb:772:9:772:9 | a [element 2] : | array_flow.rb:772:19:772:19 | x : | | array_flow.rb:772:9:772:9 | a [element 2] : | array_flow.rb:772:19:772:19 | x : | | array_flow.rb:772:9:772:9 | a [element 2] : | array_flow.rb:772:22:772:22 | y : | | array_flow.rb:772:9:772:9 | a [element 2] : | array_flow.rb:772:22:772:22 | y : | -| array_flow.rb:772:9:776:7 | call to min : | array_flow.rb:777:10:777:10 | d | -| array_flow.rb:772:9:776:7 | call to min : | array_flow.rb:777:10:777:10 | d | +| array_flow.rb:772:9:776:7 | call to min : | array_flow.rb:772:5:772:5 | d : | +| array_flow.rb:772:9:776:7 | call to min : | array_flow.rb:772:5:772:5 | d : | | array_flow.rb:772:19:772:19 | x : | array_flow.rb:773:14:773:14 | x | | array_flow.rb:772:19:772:19 | x : | array_flow.rb:773:14:773:14 | x | | array_flow.rb:772:22:772:22 | y : | array_flow.rb:774:14:774:14 | y | | array_flow.rb:772:22:772:22 | y : | array_flow.rb:774:14:774:14 | y | +| array_flow.rb:780:5:780:5 | e [element] : | array_flow.rb:785:10:785:10 | e [element] : | +| array_flow.rb:780:5:780:5 | e [element] : | array_flow.rb:785:10:785:10 | e [element] : | | array_flow.rb:780:9:780:9 | a [element 2] : | array_flow.rb:780:9:784:7 | call to min [element] : | | array_flow.rb:780:9:780:9 | a [element 2] : | array_flow.rb:780:9:784:7 | call to min [element] : | | array_flow.rb:780:9:780:9 | a [element 2] : | array_flow.rb:780:22:780:22 | x : | | array_flow.rb:780:9:780:9 | a [element 2] : | array_flow.rb:780:22:780:22 | x : | | array_flow.rb:780:9:780:9 | a [element 2] : | array_flow.rb:780:25:780:25 | y : | | array_flow.rb:780:9:780:9 | a [element 2] : | array_flow.rb:780:25:780:25 | y : | -| array_flow.rb:780:9:784:7 | call to min [element] : | array_flow.rb:785:10:785:10 | e [element] : | -| array_flow.rb:780:9:784:7 | call to min [element] : | array_flow.rb:785:10:785:10 | e [element] : | +| array_flow.rb:780:9:784:7 | call to min [element] : | array_flow.rb:780:5:780:5 | e [element] : | +| array_flow.rb:780:9:784:7 | call to min [element] : | array_flow.rb:780:5:780:5 | e [element] : | | array_flow.rb:780:22:780:22 | x : | array_flow.rb:781:14:781:14 | x | | array_flow.rb:780:22:780:22 | x : | array_flow.rb:781:14:781:14 | x | | array_flow.rb:780:25:780:25 | y : | array_flow.rb:782:14:782:14 | y | | array_flow.rb:780:25:780:25 | y : | array_flow.rb:782:14:782:14 | y | | array_flow.rb:785:10:785:10 | e [element] : | array_flow.rb:785:10:785:13 | ...[...] | | array_flow.rb:785:10:785:10 | e [element] : | array_flow.rb:785:10:785:13 | ...[...] | -| array_flow.rb:789:16:789:25 | call to source : | array_flow.rb:792:9:792:9 | a [element 2] : | -| array_flow.rb:789:16:789:25 | call to source : | array_flow.rb:792:9:792:9 | a [element 2] : | -| array_flow.rb:789:16:789:25 | call to source : | array_flow.rb:799:9:799:9 | a [element 2] : | -| array_flow.rb:789:16:789:25 | call to source : | array_flow.rb:799:9:799:9 | a [element 2] : | +| array_flow.rb:789:5:789:5 | a [element 2] : | array_flow.rb:792:9:792:9 | a [element 2] : | +| array_flow.rb:789:5:789:5 | a [element 2] : | array_flow.rb:792:9:792:9 | a [element 2] : | +| array_flow.rb:789:5:789:5 | a [element 2] : | array_flow.rb:799:9:799:9 | a [element 2] : | +| array_flow.rb:789:5:789:5 | a [element 2] : | array_flow.rb:799:9:799:9 | a [element 2] : | +| array_flow.rb:789:16:789:25 | call to source : | array_flow.rb:789:5:789:5 | a [element 2] : | +| array_flow.rb:789:16:789:25 | call to source : | array_flow.rb:789:5:789:5 | a [element 2] : | +| array_flow.rb:792:5:792:5 | b : | array_flow.rb:796:10:796:10 | b | +| array_flow.rb:792:5:792:5 | b : | array_flow.rb:796:10:796:10 | b | | array_flow.rb:792:9:792:9 | a [element 2] : | array_flow.rb:792:9:795:7 | call to min_by : | | array_flow.rb:792:9:792:9 | a [element 2] : | array_flow.rb:792:9:795:7 | call to min_by : | | array_flow.rb:792:9:792:9 | a [element 2] : | array_flow.rb:792:22:792:22 | x : | | array_flow.rb:792:9:792:9 | a [element 2] : | array_flow.rb:792:22:792:22 | x : | -| array_flow.rb:792:9:795:7 | call to min_by : | array_flow.rb:796:10:796:10 | b | -| array_flow.rb:792:9:795:7 | call to min_by : | array_flow.rb:796:10:796:10 | b | +| array_flow.rb:792:9:795:7 | call to min_by : | array_flow.rb:792:5:792:5 | b : | +| array_flow.rb:792:9:795:7 | call to min_by : | array_flow.rb:792:5:792:5 | b : | | array_flow.rb:792:22:792:22 | x : | array_flow.rb:793:14:793:14 | x | | array_flow.rb:792:22:792:22 | x : | array_flow.rb:793:14:793:14 | x | +| array_flow.rb:799:5:799:5 | c [element] : | array_flow.rb:803:10:803:10 | c [element] : | +| array_flow.rb:799:5:799:5 | c [element] : | array_flow.rb:803:10:803:10 | c [element] : | | array_flow.rb:799:9:799:9 | a [element 2] : | array_flow.rb:799:9:802:7 | call to min_by [element] : | | array_flow.rb:799:9:799:9 | a [element 2] : | array_flow.rb:799:9:802:7 | call to min_by [element] : | | array_flow.rb:799:9:799:9 | a [element 2] : | array_flow.rb:799:25:799:25 | x : | | array_flow.rb:799:9:799:9 | a [element 2] : | array_flow.rb:799:25:799:25 | x : | -| array_flow.rb:799:9:802:7 | call to min_by [element] : | array_flow.rb:803:10:803:10 | c [element] : | -| array_flow.rb:799:9:802:7 | call to min_by [element] : | array_flow.rb:803:10:803:10 | c [element] : | +| array_flow.rb:799:9:802:7 | call to min_by [element] : | array_flow.rb:799:5:799:5 | c [element] : | +| array_flow.rb:799:9:802:7 | call to min_by [element] : | array_flow.rb:799:5:799:5 | c [element] : | | array_flow.rb:799:25:799:25 | x : | array_flow.rb:800:14:800:14 | x | | array_flow.rb:799:25:799:25 | x : | array_flow.rb:800:14:800:14 | x | | array_flow.rb:803:10:803:10 | c [element] : | array_flow.rb:803:10:803:13 | ...[...] | | array_flow.rb:803:10:803:10 | c [element] : | array_flow.rb:803:10:803:13 | ...[...] | -| array_flow.rb:807:16:807:25 | call to source : | array_flow.rb:809:9:809:9 | a [element 2] : | -| array_flow.rb:807:16:807:25 | call to source : | array_flow.rb:809:9:809:9 | a [element 2] : | -| array_flow.rb:807:16:807:25 | call to source : | array_flow.rb:813:9:813:9 | a [element 2] : | -| array_flow.rb:807:16:807:25 | call to source : | array_flow.rb:813:9:813:9 | a [element 2] : | +| array_flow.rb:807:5:807:5 | a [element 2] : | array_flow.rb:809:9:809:9 | a [element 2] : | +| array_flow.rb:807:5:807:5 | a [element 2] : | array_flow.rb:809:9:809:9 | a [element 2] : | +| array_flow.rb:807:5:807:5 | a [element 2] : | array_flow.rb:813:9:813:9 | a [element 2] : | +| array_flow.rb:807:5:807:5 | a [element 2] : | array_flow.rb:813:9:813:9 | a [element 2] : | +| array_flow.rb:807:16:807:25 | call to source : | array_flow.rb:807:5:807:5 | a [element 2] : | +| array_flow.rb:807:16:807:25 | call to source : | array_flow.rb:807:5:807:5 | a [element 2] : | +| array_flow.rb:809:5:809:5 | b [element] : | array_flow.rb:810:10:810:10 | b [element] : | +| array_flow.rb:809:5:809:5 | b [element] : | array_flow.rb:810:10:810:10 | b [element] : | +| array_flow.rb:809:5:809:5 | b [element] : | array_flow.rb:811:10:811:10 | b [element] : | +| array_flow.rb:809:5:809:5 | b [element] : | array_flow.rb:811:10:811:10 | b [element] : | | array_flow.rb:809:9:809:9 | a [element 2] : | array_flow.rb:809:9:809:16 | call to minmax [element] : | | array_flow.rb:809:9:809:9 | a [element 2] : | array_flow.rb:809:9:809:16 | call to minmax [element] : | -| array_flow.rb:809:9:809:16 | call to minmax [element] : | array_flow.rb:810:10:810:10 | b [element] : | -| array_flow.rb:809:9:809:16 | call to minmax [element] : | array_flow.rb:810:10:810:10 | b [element] : | -| array_flow.rb:809:9:809:16 | call to minmax [element] : | array_flow.rb:811:10:811:10 | b [element] : | -| array_flow.rb:809:9:809:16 | call to minmax [element] : | array_flow.rb:811:10:811:10 | b [element] : | +| array_flow.rb:809:9:809:16 | call to minmax [element] : | array_flow.rb:809:5:809:5 | b [element] : | +| array_flow.rb:809:9:809:16 | call to minmax [element] : | array_flow.rb:809:5:809:5 | b [element] : | | array_flow.rb:810:10:810:10 | b [element] : | array_flow.rb:810:10:810:13 | ...[...] | | array_flow.rb:810:10:810:10 | b [element] : | array_flow.rb:810:10:810:13 | ...[...] | | array_flow.rb:811:10:811:10 | b [element] : | array_flow.rb:811:10:811:13 | ...[...] | | array_flow.rb:811:10:811:10 | b [element] : | array_flow.rb:811:10:811:13 | ...[...] | +| array_flow.rb:813:5:813:5 | c [element] : | array_flow.rb:818:10:818:10 | c [element] : | +| array_flow.rb:813:5:813:5 | c [element] : | array_flow.rb:818:10:818:10 | c [element] : | +| array_flow.rb:813:5:813:5 | c [element] : | array_flow.rb:819:10:819:10 | c [element] : | +| array_flow.rb:813:5:813:5 | c [element] : | array_flow.rb:819:10:819:10 | c [element] : | | array_flow.rb:813:9:813:9 | a [element 2] : | array_flow.rb:813:9:817:7 | call to minmax [element] : | | array_flow.rb:813:9:813:9 | a [element 2] : | array_flow.rb:813:9:817:7 | call to minmax [element] : | | array_flow.rb:813:9:813:9 | a [element 2] : | array_flow.rb:813:22:813:22 | x : | | array_flow.rb:813:9:813:9 | a [element 2] : | array_flow.rb:813:22:813:22 | x : | | array_flow.rb:813:9:813:9 | a [element 2] : | array_flow.rb:813:25:813:25 | y : | | array_flow.rb:813:9:813:9 | a [element 2] : | array_flow.rb:813:25:813:25 | y : | -| array_flow.rb:813:9:817:7 | call to minmax [element] : | array_flow.rb:818:10:818:10 | c [element] : | -| array_flow.rb:813:9:817:7 | call to minmax [element] : | array_flow.rb:818:10:818:10 | c [element] : | -| array_flow.rb:813:9:817:7 | call to minmax [element] : | array_flow.rb:819:10:819:10 | c [element] : | -| array_flow.rb:813:9:817:7 | call to minmax [element] : | array_flow.rb:819:10:819:10 | c [element] : | +| array_flow.rb:813:9:817:7 | call to minmax [element] : | array_flow.rb:813:5:813:5 | c [element] : | +| array_flow.rb:813:9:817:7 | call to minmax [element] : | array_flow.rb:813:5:813:5 | c [element] : | | array_flow.rb:813:22:813:22 | x : | array_flow.rb:814:14:814:14 | x | | array_flow.rb:813:22:813:22 | x : | array_flow.rb:814:14:814:14 | x | | array_flow.rb:813:25:813:25 | y : | array_flow.rb:815:14:815:14 | y | @@ -1460,47 +1843,61 @@ edges | array_flow.rb:818:10:818:10 | c [element] : | array_flow.rb:818:10:818:13 | ...[...] | | array_flow.rb:819:10:819:10 | c [element] : | array_flow.rb:819:10:819:13 | ...[...] | | array_flow.rb:819:10:819:10 | c [element] : | array_flow.rb:819:10:819:13 | ...[...] | -| array_flow.rb:823:16:823:25 | call to source : | array_flow.rb:824:9:824:9 | a [element 2] : | -| array_flow.rb:823:16:823:25 | call to source : | array_flow.rb:824:9:824:9 | a [element 2] : | +| array_flow.rb:823:5:823:5 | a [element 2] : | array_flow.rb:824:9:824:9 | a [element 2] : | +| array_flow.rb:823:5:823:5 | a [element 2] : | array_flow.rb:824:9:824:9 | a [element 2] : | +| array_flow.rb:823:16:823:25 | call to source : | array_flow.rb:823:5:823:5 | a [element 2] : | +| array_flow.rb:823:16:823:25 | call to source : | array_flow.rb:823:5:823:5 | a [element 2] : | +| array_flow.rb:824:5:824:5 | b [element] : | array_flow.rb:828:10:828:10 | b [element] : | +| array_flow.rb:824:5:824:5 | b [element] : | array_flow.rb:828:10:828:10 | b [element] : | +| array_flow.rb:824:5:824:5 | b [element] : | array_flow.rb:829:10:829:10 | b [element] : | +| array_flow.rb:824:5:824:5 | b [element] : | array_flow.rb:829:10:829:10 | b [element] : | | array_flow.rb:824:9:824:9 | a [element 2] : | array_flow.rb:824:9:827:7 | call to minmax_by [element] : | | array_flow.rb:824:9:824:9 | a [element 2] : | array_flow.rb:824:9:827:7 | call to minmax_by [element] : | | array_flow.rb:824:9:824:9 | a [element 2] : | array_flow.rb:824:25:824:25 | x : | | array_flow.rb:824:9:824:9 | a [element 2] : | array_flow.rb:824:25:824:25 | x : | -| array_flow.rb:824:9:827:7 | call to minmax_by [element] : | array_flow.rb:828:10:828:10 | b [element] : | -| array_flow.rb:824:9:827:7 | call to minmax_by [element] : | array_flow.rb:828:10:828:10 | b [element] : | -| array_flow.rb:824:9:827:7 | call to minmax_by [element] : | array_flow.rb:829:10:829:10 | b [element] : | -| array_flow.rb:824:9:827:7 | call to minmax_by [element] : | array_flow.rb:829:10:829:10 | b [element] : | +| array_flow.rb:824:9:827:7 | call to minmax_by [element] : | array_flow.rb:824:5:824:5 | b [element] : | +| array_flow.rb:824:9:827:7 | call to minmax_by [element] : | array_flow.rb:824:5:824:5 | b [element] : | | array_flow.rb:824:25:824:25 | x : | array_flow.rb:825:14:825:14 | x | | array_flow.rb:824:25:824:25 | x : | array_flow.rb:825:14:825:14 | x | | array_flow.rb:828:10:828:10 | b [element] : | array_flow.rb:828:10:828:13 | ...[...] | | array_flow.rb:828:10:828:10 | b [element] : | array_flow.rb:828:10:828:13 | ...[...] | | array_flow.rb:829:10:829:10 | b [element] : | array_flow.rb:829:10:829:13 | ...[...] | | array_flow.rb:829:10:829:10 | b [element] : | array_flow.rb:829:10:829:13 | ...[...] | -| array_flow.rb:833:16:833:25 | call to source : | array_flow.rb:834:5:834:5 | a [element 2] : | -| array_flow.rb:833:16:833:25 | call to source : | array_flow.rb:834:5:834:5 | a [element 2] : | +| array_flow.rb:833:5:833:5 | a [element 2] : | array_flow.rb:834:5:834:5 | a [element 2] : | +| array_flow.rb:833:5:833:5 | a [element 2] : | array_flow.rb:834:5:834:5 | a [element 2] : | +| array_flow.rb:833:16:833:25 | call to source : | array_flow.rb:833:5:833:5 | a [element 2] : | +| array_flow.rb:833:16:833:25 | call to source : | array_flow.rb:833:5:833:5 | a [element 2] : | | array_flow.rb:834:5:834:5 | a [element 2] : | array_flow.rb:834:17:834:17 | x : | | array_flow.rb:834:5:834:5 | a [element 2] : | array_flow.rb:834:17:834:17 | x : | | array_flow.rb:834:17:834:17 | x : | array_flow.rb:835:14:835:14 | x | | array_flow.rb:834:17:834:17 | x : | array_flow.rb:835:14:835:14 | x | -| array_flow.rb:842:16:842:25 | call to source : | array_flow.rb:843:5:843:5 | a [element 2] : | -| array_flow.rb:842:16:842:25 | call to source : | array_flow.rb:843:5:843:5 | a [element 2] : | +| array_flow.rb:842:5:842:5 | a [element 2] : | array_flow.rb:843:5:843:5 | a [element 2] : | +| array_flow.rb:842:5:842:5 | a [element 2] : | array_flow.rb:843:5:843:5 | a [element 2] : | +| array_flow.rb:842:16:842:25 | call to source : | array_flow.rb:842:5:842:5 | a [element 2] : | +| array_flow.rb:842:16:842:25 | call to source : | array_flow.rb:842:5:842:5 | a [element 2] : | | array_flow.rb:843:5:843:5 | a [element 2] : | array_flow.rb:843:16:843:16 | x : | | array_flow.rb:843:5:843:5 | a [element 2] : | array_flow.rb:843:16:843:16 | x : | | array_flow.rb:843:16:843:16 | x : | array_flow.rb:844:14:844:14 | x | | array_flow.rb:843:16:843:16 | x : | array_flow.rb:844:14:844:14 | x | -| array_flow.rb:849:16:849:25 | call to source : | array_flow.rb:850:9:850:9 | a [element 2] : | +| array_flow.rb:849:5:849:5 | a [element 2] : | array_flow.rb:850:9:850:9 | a [element 2] : | +| array_flow.rb:849:16:849:25 | call to source : | array_flow.rb:849:5:849:5 | a [element 2] : | +| array_flow.rb:850:5:850:5 | b : | array_flow.rb:851:10:851:10 | b | | array_flow.rb:850:9:850:9 | a [element 2] : | array_flow.rb:850:9:850:20 | call to pack : | -| array_flow.rb:850:9:850:20 | call to pack : | array_flow.rb:851:10:851:10 | b | -| array_flow.rb:855:16:855:25 | call to source : | array_flow.rb:856:9:856:9 | a [element 2] : | -| array_flow.rb:855:16:855:25 | call to source : | array_flow.rb:856:9:856:9 | a [element 2] : | +| array_flow.rb:850:9:850:20 | call to pack : | array_flow.rb:850:5:850:5 | b : | +| array_flow.rb:855:5:855:5 | a [element 2] : | array_flow.rb:856:9:856:9 | a [element 2] : | +| array_flow.rb:855:5:855:5 | a [element 2] : | array_flow.rb:856:9:856:9 | a [element 2] : | +| array_flow.rb:855:16:855:25 | call to source : | array_flow.rb:855:5:855:5 | a [element 2] : | +| array_flow.rb:855:16:855:25 | call to source : | array_flow.rb:855:5:855:5 | a [element 2] : | +| array_flow.rb:856:5:856:5 | b [element, element] : | array_flow.rb:860:10:860:10 | b [element, element] : | +| array_flow.rb:856:5:856:5 | b [element, element] : | array_flow.rb:860:10:860:10 | b [element, element] : | +| array_flow.rb:856:5:856:5 | b [element, element] : | array_flow.rb:861:10:861:10 | b [element, element] : | +| array_flow.rb:856:5:856:5 | b [element, element] : | array_flow.rb:861:10:861:10 | b [element, element] : | | array_flow.rb:856:9:856:9 | a [element 2] : | array_flow.rb:856:9:859:7 | call to partition [element, element] : | | array_flow.rb:856:9:856:9 | a [element 2] : | array_flow.rb:856:9:859:7 | call to partition [element, element] : | | array_flow.rb:856:9:856:9 | a [element 2] : | array_flow.rb:856:25:856:25 | x : | | array_flow.rb:856:9:856:9 | a [element 2] : | array_flow.rb:856:25:856:25 | x : | -| array_flow.rb:856:9:859:7 | call to partition [element, element] : | array_flow.rb:860:10:860:10 | b [element, element] : | -| array_flow.rb:856:9:859:7 | call to partition [element, element] : | array_flow.rb:860:10:860:10 | b [element, element] : | -| array_flow.rb:856:9:859:7 | call to partition [element, element] : | array_flow.rb:861:10:861:10 | b [element, element] : | -| array_flow.rb:856:9:859:7 | call to partition [element, element] : | array_flow.rb:861:10:861:10 | b [element, element] : | +| array_flow.rb:856:9:859:7 | call to partition [element, element] : | array_flow.rb:856:5:856:5 | b [element, element] : | +| array_flow.rb:856:9:859:7 | call to partition [element, element] : | array_flow.rb:856:5:856:5 | b [element, element] : | | array_flow.rb:856:25:856:25 | x : | array_flow.rb:857:14:857:14 | x | | array_flow.rb:856:25:856:25 | x : | array_flow.rb:857:14:857:14 | x | | array_flow.rb:860:10:860:10 | b [element, element] : | array_flow.rb:860:10:860:13 | ...[...] [element] : | @@ -1511,18 +1908,22 @@ edges | array_flow.rb:861:10:861:10 | b [element, element] : | array_flow.rb:861:10:861:13 | ...[...] [element] : | | array_flow.rb:861:10:861:13 | ...[...] [element] : | array_flow.rb:861:10:861:16 | ...[...] | | array_flow.rb:861:10:861:13 | ...[...] [element] : | array_flow.rb:861:10:861:16 | ...[...] | -| array_flow.rb:865:16:865:25 | call to source : | array_flow.rb:867:9:867:9 | a [element 2] : | -| array_flow.rb:865:16:865:25 | call to source : | array_flow.rb:867:9:867:9 | a [element 2] : | -| array_flow.rb:865:16:865:25 | call to source : | array_flow.rb:875:9:875:9 | a [element 2] : | -| array_flow.rb:865:16:865:25 | call to source : | array_flow.rb:875:9:875:9 | a [element 2] : | -| array_flow.rb:865:16:865:25 | call to source : | array_flow.rb:882:9:882:9 | a [element 2] : | -| array_flow.rb:865:16:865:25 | call to source : | array_flow.rb:882:9:882:9 | a [element 2] : | +| array_flow.rb:865:5:865:5 | a [element 2] : | array_flow.rb:867:9:867:9 | a [element 2] : | +| array_flow.rb:865:5:865:5 | a [element 2] : | array_flow.rb:867:9:867:9 | a [element 2] : | +| array_flow.rb:865:5:865:5 | a [element 2] : | array_flow.rb:875:9:875:9 | a [element 2] : | +| array_flow.rb:865:5:865:5 | a [element 2] : | array_flow.rb:875:9:875:9 | a [element 2] : | +| array_flow.rb:865:5:865:5 | a [element 2] : | array_flow.rb:882:9:882:9 | a [element 2] : | +| array_flow.rb:865:5:865:5 | a [element 2] : | array_flow.rb:882:9:882:9 | a [element 2] : | +| array_flow.rb:865:16:865:25 | call to source : | array_flow.rb:865:5:865:5 | a [element 2] : | +| array_flow.rb:865:16:865:25 | call to source : | array_flow.rb:865:5:865:5 | a [element 2] : | +| array_flow.rb:867:5:867:5 | b [element 2] : | array_flow.rb:873:10:873:10 | b [element 2] : | +| array_flow.rb:867:5:867:5 | b [element 2] : | array_flow.rb:873:10:873:10 | b [element 2] : | | array_flow.rb:867:9:867:9 | a [element 2] : | array_flow.rb:867:9:871:7 | call to permutation [element 2] : | | array_flow.rb:867:9:867:9 | a [element 2] : | array_flow.rb:867:9:871:7 | call to permutation [element 2] : | | array_flow.rb:867:9:867:9 | a [element 2] : | array_flow.rb:867:27:867:27 | x [element] : | | array_flow.rb:867:9:867:9 | a [element 2] : | array_flow.rb:867:27:867:27 | x [element] : | -| array_flow.rb:867:9:871:7 | call to permutation [element 2] : | array_flow.rb:873:10:873:10 | b [element 2] : | -| array_flow.rb:867:9:871:7 | call to permutation [element 2] : | array_flow.rb:873:10:873:10 | b [element 2] : | +| array_flow.rb:867:9:871:7 | call to permutation [element 2] : | array_flow.rb:867:5:867:5 | b [element 2] : | +| array_flow.rb:867:9:871:7 | call to permutation [element 2] : | array_flow.rb:867:5:867:5 | b [element 2] : | | array_flow.rb:867:27:867:27 | x [element] : | array_flow.rb:868:14:868:14 | x [element] : | | array_flow.rb:867:27:867:27 | x [element] : | array_flow.rb:868:14:868:14 | x [element] : | | array_flow.rb:867:27:867:27 | x [element] : | array_flow.rb:869:14:869:14 | x [element] : | @@ -1537,14 +1938,16 @@ edges | array_flow.rb:870:14:870:14 | x [element] : | array_flow.rb:870:14:870:17 | ...[...] | | array_flow.rb:873:10:873:10 | b [element 2] : | array_flow.rb:873:10:873:13 | ...[...] | | array_flow.rb:873:10:873:10 | b [element 2] : | array_flow.rb:873:10:873:13 | ...[...] | +| array_flow.rb:875:5:875:5 | c [element 2] : | array_flow.rb:880:10:880:10 | c [element 2] : | +| array_flow.rb:875:5:875:5 | c [element 2] : | array_flow.rb:880:10:880:10 | c [element 2] : | +| array_flow.rb:875:5:875:5 | c [element 2] : | array_flow.rb:887:10:887:10 | c [element 2] : | +| array_flow.rb:875:5:875:5 | c [element 2] : | array_flow.rb:887:10:887:10 | c [element 2] : | | array_flow.rb:875:9:875:9 | a [element 2] : | array_flow.rb:875:9:878:7 | call to permutation [element 2] : | | array_flow.rb:875:9:875:9 | a [element 2] : | array_flow.rb:875:9:878:7 | call to permutation [element 2] : | | array_flow.rb:875:9:875:9 | a [element 2] : | array_flow.rb:875:30:875:30 | x [element] : | | array_flow.rb:875:9:875:9 | a [element 2] : | array_flow.rb:875:30:875:30 | x [element] : | -| array_flow.rb:875:9:878:7 | call to permutation [element 2] : | array_flow.rb:880:10:880:10 | c [element 2] : | -| array_flow.rb:875:9:878:7 | call to permutation [element 2] : | array_flow.rb:880:10:880:10 | c [element 2] : | -| array_flow.rb:875:9:878:7 | call to permutation [element 2] : | array_flow.rb:887:10:887:10 | c [element 2] : | -| array_flow.rb:875:9:878:7 | call to permutation [element 2] : | array_flow.rb:887:10:887:10 | c [element 2] : | +| array_flow.rb:875:9:878:7 | call to permutation [element 2] : | array_flow.rb:875:5:875:5 | c [element 2] : | +| array_flow.rb:875:9:878:7 | call to permutation [element 2] : | array_flow.rb:875:5:875:5 | c [element 2] : | | array_flow.rb:875:30:875:30 | x [element] : | array_flow.rb:876:14:876:14 | x [element] : | | array_flow.rb:875:30:875:30 | x [element] : | array_flow.rb:876:14:876:14 | x [element] : | | array_flow.rb:875:30:875:30 | x [element] : | array_flow.rb:877:14:877:14 | x [element] : | @@ -1567,40 +1970,52 @@ edges | array_flow.rb:884:14:884:14 | x [element] : | array_flow.rb:884:14:884:17 | ...[...] | | array_flow.rb:887:10:887:10 | c [element 2] : | array_flow.rb:887:10:887:13 | ...[...] | | array_flow.rb:887:10:887:10 | c [element 2] : | array_flow.rb:887:10:887:13 | ...[...] | -| array_flow.rb:894:13:894:24 | call to source : | array_flow.rb:895:9:895:9 | a [element 1] : | -| array_flow.rb:894:13:894:24 | call to source : | array_flow.rb:895:9:895:9 | a [element 1] : | -| array_flow.rb:894:13:894:24 | call to source : | array_flow.rb:898:10:898:10 | a [element 1] : | -| array_flow.rb:894:13:894:24 | call to source : | array_flow.rb:898:10:898:10 | a [element 1] : | -| array_flow.rb:894:30:894:41 | call to source : | array_flow.rb:895:9:895:9 | a [element 3] : | -| array_flow.rb:894:30:894:41 | call to source : | array_flow.rb:895:9:895:9 | a [element 3] : | -| array_flow.rb:894:30:894:41 | call to source : | array_flow.rb:900:10:900:10 | a [element 3] : | -| array_flow.rb:894:30:894:41 | call to source : | array_flow.rb:900:10:900:10 | a [element 3] : | +| array_flow.rb:894:5:894:5 | a [element 1] : | array_flow.rb:895:9:895:9 | a [element 1] : | +| array_flow.rb:894:5:894:5 | a [element 1] : | array_flow.rb:895:9:895:9 | a [element 1] : | +| array_flow.rb:894:5:894:5 | a [element 1] : | array_flow.rb:898:10:898:10 | a [element 1] : | +| array_flow.rb:894:5:894:5 | a [element 1] : | array_flow.rb:898:10:898:10 | a [element 1] : | +| array_flow.rb:894:5:894:5 | a [element 3] : | array_flow.rb:895:9:895:9 | a [element 3] : | +| array_flow.rb:894:5:894:5 | a [element 3] : | array_flow.rb:895:9:895:9 | a [element 3] : | +| array_flow.rb:894:5:894:5 | a [element 3] : | array_flow.rb:900:10:900:10 | a [element 3] : | +| array_flow.rb:894:5:894:5 | a [element 3] : | array_flow.rb:900:10:900:10 | a [element 3] : | +| array_flow.rb:894:13:894:24 | call to source : | array_flow.rb:894:5:894:5 | a [element 1] : | +| array_flow.rb:894:13:894:24 | call to source : | array_flow.rb:894:5:894:5 | a [element 1] : | +| array_flow.rb:894:30:894:41 | call to source : | array_flow.rb:894:5:894:5 | a [element 3] : | +| array_flow.rb:894:30:894:41 | call to source : | array_flow.rb:894:5:894:5 | a [element 3] : | +| array_flow.rb:895:5:895:5 | b : | array_flow.rb:896:10:896:10 | b | +| array_flow.rb:895:5:895:5 | b : | array_flow.rb:896:10:896:10 | b | | array_flow.rb:895:9:895:9 | a [element 1] : | array_flow.rb:895:9:895:13 | call to pop : | | array_flow.rb:895:9:895:9 | a [element 1] : | array_flow.rb:895:9:895:13 | call to pop : | | array_flow.rb:895:9:895:9 | a [element 3] : | array_flow.rb:895:9:895:13 | call to pop : | | array_flow.rb:895:9:895:9 | a [element 3] : | array_flow.rb:895:9:895:13 | call to pop : | -| array_flow.rb:895:9:895:13 | call to pop : | array_flow.rb:896:10:896:10 | b | -| array_flow.rb:895:9:895:13 | call to pop : | array_flow.rb:896:10:896:10 | b | +| array_flow.rb:895:9:895:13 | call to pop : | array_flow.rb:895:5:895:5 | b : | +| array_flow.rb:895:9:895:13 | call to pop : | array_flow.rb:895:5:895:5 | b : | | array_flow.rb:898:10:898:10 | a [element 1] : | array_flow.rb:898:10:898:13 | ...[...] | | array_flow.rb:898:10:898:10 | a [element 1] : | array_flow.rb:898:10:898:13 | ...[...] | | array_flow.rb:900:10:900:10 | a [element 3] : | array_flow.rb:900:10:900:13 | ...[...] | | array_flow.rb:900:10:900:10 | a [element 3] : | array_flow.rb:900:10:900:13 | ...[...] | -| array_flow.rb:902:13:902:24 | call to source : | array_flow.rb:903:9:903:9 | a [element 1] : | -| array_flow.rb:902:13:902:24 | call to source : | array_flow.rb:903:9:903:9 | a [element 1] : | -| array_flow.rb:902:13:902:24 | call to source : | array_flow.rb:907:10:907:10 | a [element 1] : | -| array_flow.rb:902:13:902:24 | call to source : | array_flow.rb:907:10:907:10 | a [element 1] : | -| array_flow.rb:902:30:902:41 | call to source : | array_flow.rb:903:9:903:9 | a [element 3] : | -| array_flow.rb:902:30:902:41 | call to source : | array_flow.rb:903:9:903:9 | a [element 3] : | -| array_flow.rb:902:30:902:41 | call to source : | array_flow.rb:909:10:909:10 | a [element 3] : | -| array_flow.rb:902:30:902:41 | call to source : | array_flow.rb:909:10:909:10 | a [element 3] : | +| array_flow.rb:902:5:902:5 | a [element 1] : | array_flow.rb:903:9:903:9 | a [element 1] : | +| array_flow.rb:902:5:902:5 | a [element 1] : | array_flow.rb:903:9:903:9 | a [element 1] : | +| array_flow.rb:902:5:902:5 | a [element 1] : | array_flow.rb:907:10:907:10 | a [element 1] : | +| array_flow.rb:902:5:902:5 | a [element 1] : | array_flow.rb:907:10:907:10 | a [element 1] : | +| array_flow.rb:902:5:902:5 | a [element 3] : | array_flow.rb:903:9:903:9 | a [element 3] : | +| array_flow.rb:902:5:902:5 | a [element 3] : | array_flow.rb:903:9:903:9 | a [element 3] : | +| array_flow.rb:902:5:902:5 | a [element 3] : | array_flow.rb:909:10:909:10 | a [element 3] : | +| array_flow.rb:902:5:902:5 | a [element 3] : | array_flow.rb:909:10:909:10 | a [element 3] : | +| array_flow.rb:902:13:902:24 | call to source : | array_flow.rb:902:5:902:5 | a [element 1] : | +| array_flow.rb:902:13:902:24 | call to source : | array_flow.rb:902:5:902:5 | a [element 1] : | +| array_flow.rb:902:30:902:41 | call to source : | array_flow.rb:902:5:902:5 | a [element 3] : | +| array_flow.rb:902:30:902:41 | call to source : | array_flow.rb:902:5:902:5 | a [element 3] : | +| array_flow.rb:903:5:903:5 | b [element] : | array_flow.rb:904:10:904:10 | b [element] : | +| array_flow.rb:903:5:903:5 | b [element] : | array_flow.rb:904:10:904:10 | b [element] : | +| array_flow.rb:903:5:903:5 | b [element] : | array_flow.rb:905:10:905:10 | b [element] : | +| array_flow.rb:903:5:903:5 | b [element] : | array_flow.rb:905:10:905:10 | b [element] : | | array_flow.rb:903:9:903:9 | a [element 1] : | array_flow.rb:903:9:903:16 | call to pop [element] : | | array_flow.rb:903:9:903:9 | a [element 1] : | array_flow.rb:903:9:903:16 | call to pop [element] : | | array_flow.rb:903:9:903:9 | a [element 3] : | array_flow.rb:903:9:903:16 | call to pop [element] : | | array_flow.rb:903:9:903:9 | a [element 3] : | array_flow.rb:903:9:903:16 | call to pop [element] : | -| array_flow.rb:903:9:903:16 | call to pop [element] : | array_flow.rb:904:10:904:10 | b [element] : | -| array_flow.rb:903:9:903:16 | call to pop [element] : | array_flow.rb:904:10:904:10 | b [element] : | -| array_flow.rb:903:9:903:16 | call to pop [element] : | array_flow.rb:905:10:905:10 | b [element] : | -| array_flow.rb:903:9:903:16 | call to pop [element] : | array_flow.rb:905:10:905:10 | b [element] : | +| array_flow.rb:903:9:903:16 | call to pop [element] : | array_flow.rb:903:5:903:5 | b [element] : | +| array_flow.rb:903:9:903:16 | call to pop [element] : | array_flow.rb:903:5:903:5 | b [element] : | | array_flow.rb:904:10:904:10 | b [element] : | array_flow.rb:904:10:904:13 | ...[...] | | array_flow.rb:904:10:904:10 | b [element] : | array_flow.rb:904:10:904:13 | ...[...] | | array_flow.rb:905:10:905:10 | b [element] : | array_flow.rb:905:10:905:13 | ...[...] | @@ -1609,8 +2024,10 @@ edges | array_flow.rb:907:10:907:10 | a [element 1] : | array_flow.rb:907:10:907:13 | ...[...] | | array_flow.rb:909:10:909:10 | a [element 3] : | array_flow.rb:909:10:909:13 | ...[...] | | array_flow.rb:909:10:909:10 | a [element 3] : | array_flow.rb:909:10:909:13 | ...[...] | -| array_flow.rb:913:16:913:27 | call to source : | array_flow.rb:914:5:914:5 | a [element 2] : | -| array_flow.rb:913:16:913:27 | call to source : | array_flow.rb:914:5:914:5 | a [element 2] : | +| array_flow.rb:913:5:913:5 | a [element 2] : | array_flow.rb:914:5:914:5 | a [element 2] : | +| array_flow.rb:913:5:913:5 | a [element 2] : | array_flow.rb:914:5:914:5 | a [element 2] : | +| array_flow.rb:913:16:913:27 | call to source : | array_flow.rb:913:5:913:5 | a [element 2] : | +| array_flow.rb:913:16:913:27 | call to source : | array_flow.rb:913:5:913:5 | a [element 2] : | | array_flow.rb:914:5:914:5 | [post] a [element 2] : | array_flow.rb:917:10:917:10 | a [element 2] : | | array_flow.rb:914:5:914:5 | [post] a [element 2] : | array_flow.rb:917:10:917:10 | a [element 2] : | | array_flow.rb:914:5:914:5 | [post] a [element 5] : | array_flow.rb:920:10:920:10 | a [element 5] : | @@ -1623,18 +2040,26 @@ edges | array_flow.rb:917:10:917:10 | a [element 2] : | array_flow.rb:917:10:917:13 | ...[...] | | array_flow.rb:920:10:920:10 | a [element 5] : | array_flow.rb:920:10:920:13 | ...[...] | | array_flow.rb:920:10:920:10 | a [element 5] : | array_flow.rb:920:10:920:13 | ...[...] | -| array_flow.rb:924:16:924:27 | call to source : | array_flow.rb:927:9:927:9 | a [element 2] : | -| array_flow.rb:924:16:924:27 | call to source : | array_flow.rb:927:9:927:9 | a [element 2] : | -| array_flow.rb:925:13:925:24 | call to source : | array_flow.rb:927:19:927:19 | b [element 1] : | -| array_flow.rb:925:13:925:24 | call to source : | array_flow.rb:927:19:927:19 | b [element 1] : | -| array_flow.rb:926:10:926:21 | call to source : | array_flow.rb:927:22:927:22 | c [element 0] : | -| array_flow.rb:926:10:926:21 | call to source : | array_flow.rb:927:22:927:22 | c [element 0] : | +| array_flow.rb:924:5:924:5 | a [element 2] : | array_flow.rb:927:9:927:9 | a [element 2] : | +| array_flow.rb:924:5:924:5 | a [element 2] : | array_flow.rb:927:9:927:9 | a [element 2] : | +| array_flow.rb:924:16:924:27 | call to source : | array_flow.rb:924:5:924:5 | a [element 2] : | +| array_flow.rb:924:16:924:27 | call to source : | array_flow.rb:924:5:924:5 | a [element 2] : | +| array_flow.rb:925:5:925:5 | b [element 1] : | array_flow.rb:927:19:927:19 | b [element 1] : | +| array_flow.rb:925:5:925:5 | b [element 1] : | array_flow.rb:927:19:927:19 | b [element 1] : | +| array_flow.rb:925:13:925:24 | call to source : | array_flow.rb:925:5:925:5 | b [element 1] : | +| array_flow.rb:925:13:925:24 | call to source : | array_flow.rb:925:5:925:5 | b [element 1] : | +| array_flow.rb:926:5:926:5 | c [element 0] : | array_flow.rb:927:22:927:22 | c [element 0] : | +| array_flow.rb:926:5:926:5 | c [element 0] : | array_flow.rb:927:22:927:22 | c [element 0] : | +| array_flow.rb:926:10:926:21 | call to source : | array_flow.rb:926:5:926:5 | c [element 0] : | +| array_flow.rb:926:10:926:21 | call to source : | array_flow.rb:926:5:926:5 | c [element 0] : | +| array_flow.rb:927:5:927:5 | d [element, element] : | array_flow.rb:928:10:928:10 | d [element, element] : | +| array_flow.rb:927:5:927:5 | d [element, element] : | array_flow.rb:928:10:928:10 | d [element, element] : | +| array_flow.rb:927:5:927:5 | d [element, element] : | array_flow.rb:929:10:929:10 | d [element, element] : | +| array_flow.rb:927:5:927:5 | d [element, element] : | array_flow.rb:929:10:929:10 | d [element, element] : | | array_flow.rb:927:9:927:9 | a [element 2] : | array_flow.rb:927:9:927:22 | call to product [element, element] : | | array_flow.rb:927:9:927:9 | a [element 2] : | array_flow.rb:927:9:927:22 | call to product [element, element] : | -| array_flow.rb:927:9:927:22 | call to product [element, element] : | array_flow.rb:928:10:928:10 | d [element, element] : | -| array_flow.rb:927:9:927:22 | call to product [element, element] : | array_flow.rb:928:10:928:10 | d [element, element] : | -| array_flow.rb:927:9:927:22 | call to product [element, element] : | array_flow.rb:929:10:929:10 | d [element, element] : | -| array_flow.rb:927:9:927:22 | call to product [element, element] : | array_flow.rb:929:10:929:10 | d [element, element] : | +| array_flow.rb:927:9:927:22 | call to product [element, element] : | array_flow.rb:927:5:927:5 | d [element, element] : | +| array_flow.rb:927:9:927:22 | call to product [element, element] : | array_flow.rb:927:5:927:5 | d [element, element] : | | array_flow.rb:927:19:927:19 | b [element 1] : | array_flow.rb:927:9:927:22 | call to product [element, element] : | | array_flow.rb:927:19:927:19 | b [element 1] : | array_flow.rb:927:9:927:22 | call to product [element, element] : | | array_flow.rb:927:22:927:22 | c [element 0] : | array_flow.rb:927:9:927:22 | call to product [element, element] : | @@ -1647,22 +2072,28 @@ edges | array_flow.rb:929:10:929:10 | d [element, element] : | array_flow.rb:929:10:929:13 | ...[...] [element] : | | array_flow.rb:929:10:929:13 | ...[...] [element] : | array_flow.rb:929:10:929:16 | ...[...] | | array_flow.rb:929:10:929:13 | ...[...] [element] : | array_flow.rb:929:10:929:16 | ...[...] | -| array_flow.rb:933:10:933:21 | call to source : | array_flow.rb:934:9:934:9 | a [element 0] : | -| array_flow.rb:933:10:933:21 | call to source : | array_flow.rb:934:9:934:9 | a [element 0] : | -| array_flow.rb:933:10:933:21 | call to source : | array_flow.rb:935:10:935:10 | a [element 0] : | -| array_flow.rb:933:10:933:21 | call to source : | array_flow.rb:935:10:935:10 | a [element 0] : | +| array_flow.rb:933:5:933:5 | a [element 0] : | array_flow.rb:934:9:934:9 | a [element 0] : | +| array_flow.rb:933:5:933:5 | a [element 0] : | array_flow.rb:934:9:934:9 | a [element 0] : | +| array_flow.rb:933:5:933:5 | a [element 0] : | array_flow.rb:935:10:935:10 | a [element 0] : | +| array_flow.rb:933:5:933:5 | a [element 0] : | array_flow.rb:935:10:935:10 | a [element 0] : | +| array_flow.rb:933:10:933:21 | call to source : | array_flow.rb:933:5:933:5 | a [element 0] : | +| array_flow.rb:933:10:933:21 | call to source : | array_flow.rb:933:5:933:5 | a [element 0] : | +| array_flow.rb:934:5:934:5 | b [element 0] : | array_flow.rb:937:10:937:10 | b [element 0] : | +| array_flow.rb:934:5:934:5 | b [element 0] : | array_flow.rb:937:10:937:10 | b [element 0] : | +| array_flow.rb:934:5:934:5 | b [element] : | array_flow.rb:937:10:937:10 | b [element] : | +| array_flow.rb:934:5:934:5 | b [element] : | array_flow.rb:937:10:937:10 | b [element] : | +| array_flow.rb:934:5:934:5 | b [element] : | array_flow.rb:938:10:938:10 | b [element] : | +| array_flow.rb:934:5:934:5 | b [element] : | array_flow.rb:938:10:938:10 | b [element] : | | array_flow.rb:934:9:934:9 | [post] a [element] : | array_flow.rb:935:10:935:10 | a [element] : | | array_flow.rb:934:9:934:9 | [post] a [element] : | array_flow.rb:935:10:935:10 | a [element] : | | array_flow.rb:934:9:934:9 | [post] a [element] : | array_flow.rb:936:10:936:10 | a [element] : | | array_flow.rb:934:9:934:9 | [post] a [element] : | array_flow.rb:936:10:936:10 | a [element] : | | array_flow.rb:934:9:934:9 | a [element 0] : | array_flow.rb:934:9:934:44 | call to append [element 0] : | | array_flow.rb:934:9:934:9 | a [element 0] : | array_flow.rb:934:9:934:44 | call to append [element 0] : | -| array_flow.rb:934:9:934:44 | call to append [element 0] : | array_flow.rb:937:10:937:10 | b [element 0] : | -| array_flow.rb:934:9:934:44 | call to append [element 0] : | array_flow.rb:937:10:937:10 | b [element 0] : | -| array_flow.rb:934:9:934:44 | call to append [element] : | array_flow.rb:937:10:937:10 | b [element] : | -| array_flow.rb:934:9:934:44 | call to append [element] : | array_flow.rb:937:10:937:10 | b [element] : | -| array_flow.rb:934:9:934:44 | call to append [element] : | array_flow.rb:938:10:938:10 | b [element] : | -| array_flow.rb:934:9:934:44 | call to append [element] : | array_flow.rb:938:10:938:10 | b [element] : | +| array_flow.rb:934:9:934:44 | call to append [element 0] : | array_flow.rb:934:5:934:5 | b [element 0] : | +| array_flow.rb:934:9:934:44 | call to append [element 0] : | array_flow.rb:934:5:934:5 | b [element 0] : | +| array_flow.rb:934:9:934:44 | call to append [element] : | array_flow.rb:934:5:934:5 | b [element] : | +| array_flow.rb:934:9:934:44 | call to append [element] : | array_flow.rb:934:5:934:5 | b [element] : | | array_flow.rb:934:18:934:29 | call to source : | array_flow.rb:934:9:934:9 | [post] a [element] : | | array_flow.rb:934:18:934:29 | call to source : | array_flow.rb:934:9:934:9 | [post] a [element] : | | array_flow.rb:934:18:934:29 | call to source : | array_flow.rb:934:9:934:44 | call to append [element] : | @@ -1683,12 +2114,16 @@ edges | array_flow.rb:937:10:937:10 | b [element] : | array_flow.rb:937:10:937:13 | ...[...] | | array_flow.rb:938:10:938:10 | b [element] : | array_flow.rb:938:10:938:13 | ...[...] | | array_flow.rb:938:10:938:10 | b [element] : | array_flow.rb:938:10:938:13 | ...[...] | -| array_flow.rb:944:10:944:19 | call to source : | array_flow.rb:945:16:945:16 | c [element 0] : | -| array_flow.rb:944:10:944:19 | call to source : | array_flow.rb:945:16:945:16 | c [element 0] : | -| array_flow.rb:945:16:945:16 | c [element 0] : | array_flow.rb:946:10:946:10 | d [element 2, element 0] : | -| array_flow.rb:945:16:945:16 | c [element 0] : | array_flow.rb:946:10:946:10 | d [element 2, element 0] : | -| array_flow.rb:945:16:945:16 | c [element 0] : | array_flow.rb:947:10:947:10 | d [element 2, element 0] : | -| array_flow.rb:945:16:945:16 | c [element 0] : | array_flow.rb:947:10:947:10 | d [element 2, element 0] : | +| array_flow.rb:944:5:944:5 | c [element 0] : | array_flow.rb:945:16:945:16 | c [element 0] : | +| array_flow.rb:944:5:944:5 | c [element 0] : | array_flow.rb:945:16:945:16 | c [element 0] : | +| array_flow.rb:944:10:944:19 | call to source : | array_flow.rb:944:5:944:5 | c [element 0] : | +| array_flow.rb:944:10:944:19 | call to source : | array_flow.rb:944:5:944:5 | c [element 0] : | +| array_flow.rb:945:5:945:5 | d [element 2, element 0] : | array_flow.rb:946:10:946:10 | d [element 2, element 0] : | +| array_flow.rb:945:5:945:5 | d [element 2, element 0] : | array_flow.rb:946:10:946:10 | d [element 2, element 0] : | +| array_flow.rb:945:5:945:5 | d [element 2, element 0] : | array_flow.rb:947:10:947:10 | d [element 2, element 0] : | +| array_flow.rb:945:5:945:5 | d [element 2, element 0] : | array_flow.rb:947:10:947:10 | d [element 2, element 0] : | +| array_flow.rb:945:16:945:16 | c [element 0] : | array_flow.rb:945:5:945:5 | d [element 2, element 0] : | +| array_flow.rb:945:16:945:16 | c [element 0] : | array_flow.rb:945:5:945:5 | d [element 2, element 0] : | | array_flow.rb:946:10:946:10 | d [element 2, element 0] : | array_flow.rb:946:10:946:22 | call to rassoc [element 0] : | | array_flow.rb:946:10:946:10 | d [element 2, element 0] : | array_flow.rb:946:10:946:22 | call to rassoc [element 0] : | | array_flow.rb:946:10:946:22 | call to rassoc [element 0] : | array_flow.rb:946:10:946:25 | ...[...] | @@ -1697,14 +2132,18 @@ edges | array_flow.rb:947:10:947:10 | d [element 2, element 0] : | array_flow.rb:947:10:947:22 | call to rassoc [element 0] : | | array_flow.rb:947:10:947:22 | call to rassoc [element 0] : | array_flow.rb:947:10:947:25 | ...[...] | | array_flow.rb:947:10:947:22 | call to rassoc [element 0] : | array_flow.rb:947:10:947:25 | ...[...] | -| array_flow.rb:951:10:951:21 | call to source : | array_flow.rb:952:9:952:9 | a [element 0] : | -| array_flow.rb:951:10:951:21 | call to source : | array_flow.rb:952:9:952:9 | a [element 0] : | -| array_flow.rb:951:10:951:21 | call to source : | array_flow.rb:957:9:957:9 | a [element 0] : | -| array_flow.rb:951:10:951:21 | call to source : | array_flow.rb:957:9:957:9 | a [element 0] : | -| array_flow.rb:951:27:951:38 | call to source : | array_flow.rb:952:9:952:9 | a [element 2] : | -| array_flow.rb:951:27:951:38 | call to source : | array_flow.rb:952:9:952:9 | a [element 2] : | -| array_flow.rb:951:27:951:38 | call to source : | array_flow.rb:957:9:957:9 | a [element 2] : | -| array_flow.rb:951:27:951:38 | call to source : | array_flow.rb:957:9:957:9 | a [element 2] : | +| array_flow.rb:951:5:951:5 | a [element 0] : | array_flow.rb:952:9:952:9 | a [element 0] : | +| array_flow.rb:951:5:951:5 | a [element 0] : | array_flow.rb:952:9:952:9 | a [element 0] : | +| array_flow.rb:951:5:951:5 | a [element 0] : | array_flow.rb:957:9:957:9 | a [element 0] : | +| array_flow.rb:951:5:951:5 | a [element 0] : | array_flow.rb:957:9:957:9 | a [element 0] : | +| array_flow.rb:951:5:951:5 | a [element 2] : | array_flow.rb:952:9:952:9 | a [element 2] : | +| array_flow.rb:951:5:951:5 | a [element 2] : | array_flow.rb:952:9:952:9 | a [element 2] : | +| array_flow.rb:951:5:951:5 | a [element 2] : | array_flow.rb:957:9:957:9 | a [element 2] : | +| array_flow.rb:951:5:951:5 | a [element 2] : | array_flow.rb:957:9:957:9 | a [element 2] : | +| array_flow.rb:951:10:951:21 | call to source : | array_flow.rb:951:5:951:5 | a [element 0] : | +| array_flow.rb:951:10:951:21 | call to source : | array_flow.rb:951:5:951:5 | a [element 0] : | +| array_flow.rb:951:27:951:38 | call to source : | array_flow.rb:951:5:951:5 | a [element 2] : | +| array_flow.rb:951:27:951:38 | call to source : | array_flow.rb:951:5:951:5 | a [element 2] : | | array_flow.rb:952:9:952:9 | a [element 0] : | array_flow.rb:952:22:952:22 | x : | | array_flow.rb:952:9:952:9 | a [element 0] : | array_flow.rb:952:22:952:22 | x : | | array_flow.rb:952:9:952:9 | a [element 2] : | array_flow.rb:952:25:952:25 | y : | @@ -1719,20 +2158,28 @@ edges | array_flow.rb:957:9:957:9 | a [element 2] : | array_flow.rb:957:28:957:28 | y : | | array_flow.rb:957:28:957:28 | y : | array_flow.rb:959:14:959:14 | y | | array_flow.rb:957:28:957:28 | y : | array_flow.rb:959:14:959:14 | y | -| array_flow.rb:965:16:965:25 | call to source : | array_flow.rb:966:9:966:9 | a [element 2] : | -| array_flow.rb:965:16:965:25 | call to source : | array_flow.rb:966:9:966:9 | a [element 2] : | +| array_flow.rb:965:5:965:5 | a [element 2] : | array_flow.rb:966:9:966:9 | a [element 2] : | +| array_flow.rb:965:5:965:5 | a [element 2] : | array_flow.rb:966:9:966:9 | a [element 2] : | +| array_flow.rb:965:16:965:25 | call to source : | array_flow.rb:965:5:965:5 | a [element 2] : | +| array_flow.rb:965:16:965:25 | call to source : | array_flow.rb:965:5:965:5 | a [element 2] : | +| array_flow.rb:966:5:966:5 | b [element] : | array_flow.rb:970:10:970:10 | b [element] : | +| array_flow.rb:966:5:966:5 | b [element] : | array_flow.rb:970:10:970:10 | b [element] : | | array_flow.rb:966:9:966:9 | a [element 2] : | array_flow.rb:966:9:969:7 | call to reject [element] : | | array_flow.rb:966:9:966:9 | a [element 2] : | array_flow.rb:966:9:969:7 | call to reject [element] : | | array_flow.rb:966:9:966:9 | a [element 2] : | array_flow.rb:966:22:966:22 | x : | | array_flow.rb:966:9:966:9 | a [element 2] : | array_flow.rb:966:22:966:22 | x : | -| array_flow.rb:966:9:969:7 | call to reject [element] : | array_flow.rb:970:10:970:10 | b [element] : | -| array_flow.rb:966:9:969:7 | call to reject [element] : | array_flow.rb:970:10:970:10 | b [element] : | +| array_flow.rb:966:9:969:7 | call to reject [element] : | array_flow.rb:966:5:966:5 | b [element] : | +| array_flow.rb:966:9:969:7 | call to reject [element] : | array_flow.rb:966:5:966:5 | b [element] : | | array_flow.rb:966:22:966:22 | x : | array_flow.rb:967:14:967:14 | x | | array_flow.rb:966:22:966:22 | x : | array_flow.rb:967:14:967:14 | x | | array_flow.rb:970:10:970:10 | b [element] : | array_flow.rb:970:10:970:13 | ...[...] | | array_flow.rb:970:10:970:10 | b [element] : | array_flow.rb:970:10:970:13 | ...[...] | -| array_flow.rb:974:16:974:25 | call to source : | array_flow.rb:975:9:975:9 | a [element 2] : | -| array_flow.rb:974:16:974:25 | call to source : | array_flow.rb:975:9:975:9 | a [element 2] : | +| array_flow.rb:974:5:974:5 | a [element 2] : | array_flow.rb:975:9:975:9 | a [element 2] : | +| array_flow.rb:974:5:974:5 | a [element 2] : | array_flow.rb:975:9:975:9 | a [element 2] : | +| array_flow.rb:974:16:974:25 | call to source : | array_flow.rb:974:5:974:5 | a [element 2] : | +| array_flow.rb:974:16:974:25 | call to source : | array_flow.rb:974:5:974:5 | a [element 2] : | +| array_flow.rb:975:5:975:5 | b [element] : | array_flow.rb:980:10:980:10 | b [element] : | +| array_flow.rb:975:5:975:5 | b [element] : | array_flow.rb:980:10:980:10 | b [element] : | | array_flow.rb:975:9:975:9 | [post] a [element] : | array_flow.rb:979:10:979:10 | a [element] : | | array_flow.rb:975:9:975:9 | [post] a [element] : | array_flow.rb:979:10:979:10 | a [element] : | | array_flow.rb:975:9:975:9 | a [element 2] : | array_flow.rb:975:9:975:9 | [post] a [element] : | @@ -1741,22 +2188,26 @@ edges | array_flow.rb:975:9:975:9 | a [element 2] : | array_flow.rb:975:9:978:7 | call to reject! [element] : | | array_flow.rb:975:9:975:9 | a [element 2] : | array_flow.rb:975:23:975:23 | x : | | array_flow.rb:975:9:975:9 | a [element 2] : | array_flow.rb:975:23:975:23 | x : | -| array_flow.rb:975:9:978:7 | call to reject! [element] : | array_flow.rb:980:10:980:10 | b [element] : | -| array_flow.rb:975:9:978:7 | call to reject! [element] : | array_flow.rb:980:10:980:10 | b [element] : | +| array_flow.rb:975:9:978:7 | call to reject! [element] : | array_flow.rb:975:5:975:5 | b [element] : | +| array_flow.rb:975:9:978:7 | call to reject! [element] : | array_flow.rb:975:5:975:5 | b [element] : | | array_flow.rb:975:23:975:23 | x : | array_flow.rb:976:14:976:14 | x | | array_flow.rb:975:23:975:23 | x : | array_flow.rb:976:14:976:14 | x | | array_flow.rb:979:10:979:10 | a [element] : | array_flow.rb:979:10:979:13 | ...[...] | | array_flow.rb:979:10:979:10 | a [element] : | array_flow.rb:979:10:979:13 | ...[...] | | array_flow.rb:980:10:980:10 | b [element] : | array_flow.rb:980:10:980:13 | ...[...] | | array_flow.rb:980:10:980:10 | b [element] : | array_flow.rb:980:10:980:13 | ...[...] | -| array_flow.rb:984:16:984:25 | call to source : | array_flow.rb:985:9:985:9 | a [element 2] : | -| array_flow.rb:984:16:984:25 | call to source : | array_flow.rb:985:9:985:9 | a [element 2] : | +| array_flow.rb:984:5:984:5 | a [element 2] : | array_flow.rb:985:9:985:9 | a [element 2] : | +| array_flow.rb:984:5:984:5 | a [element 2] : | array_flow.rb:985:9:985:9 | a [element 2] : | +| array_flow.rb:984:16:984:25 | call to source : | array_flow.rb:984:5:984:5 | a [element 2] : | +| array_flow.rb:984:16:984:25 | call to source : | array_flow.rb:984:5:984:5 | a [element 2] : | +| array_flow.rb:985:5:985:5 | b [element 2] : | array_flow.rb:990:10:990:10 | b [element 2] : | +| array_flow.rb:985:5:985:5 | b [element 2] : | array_flow.rb:990:10:990:10 | b [element 2] : | | array_flow.rb:985:9:985:9 | a [element 2] : | array_flow.rb:985:9:988:7 | call to repeated_combination [element 2] : | | array_flow.rb:985:9:985:9 | a [element 2] : | array_flow.rb:985:9:988:7 | call to repeated_combination [element 2] : | | array_flow.rb:985:9:985:9 | a [element 2] : | array_flow.rb:985:39:985:39 | x [element] : | | array_flow.rb:985:9:985:9 | a [element 2] : | array_flow.rb:985:39:985:39 | x [element] : | -| array_flow.rb:985:9:988:7 | call to repeated_combination [element 2] : | array_flow.rb:990:10:990:10 | b [element 2] : | -| array_flow.rb:985:9:988:7 | call to repeated_combination [element 2] : | array_flow.rb:990:10:990:10 | b [element 2] : | +| array_flow.rb:985:9:988:7 | call to repeated_combination [element 2] : | array_flow.rb:985:5:985:5 | b [element 2] : | +| array_flow.rb:985:9:988:7 | call to repeated_combination [element 2] : | array_flow.rb:985:5:985:5 | b [element 2] : | | array_flow.rb:985:39:985:39 | x [element] : | array_flow.rb:986:14:986:14 | x [element] : | | array_flow.rb:985:39:985:39 | x [element] : | array_flow.rb:986:14:986:14 | x [element] : | | array_flow.rb:985:39:985:39 | x [element] : | array_flow.rb:987:14:987:14 | x [element] : | @@ -1767,14 +2218,18 @@ edges | array_flow.rb:987:14:987:14 | x [element] : | array_flow.rb:987:14:987:17 | ...[...] | | array_flow.rb:990:10:990:10 | b [element 2] : | array_flow.rb:990:10:990:13 | ...[...] | | array_flow.rb:990:10:990:10 | b [element 2] : | array_flow.rb:990:10:990:13 | ...[...] | -| array_flow.rb:994:16:994:25 | call to source : | array_flow.rb:995:9:995:9 | a [element 2] : | -| array_flow.rb:994:16:994:25 | call to source : | array_flow.rb:995:9:995:9 | a [element 2] : | +| array_flow.rb:994:5:994:5 | a [element 2] : | array_flow.rb:995:9:995:9 | a [element 2] : | +| array_flow.rb:994:5:994:5 | a [element 2] : | array_flow.rb:995:9:995:9 | a [element 2] : | +| array_flow.rb:994:16:994:25 | call to source : | array_flow.rb:994:5:994:5 | a [element 2] : | +| array_flow.rb:994:16:994:25 | call to source : | array_flow.rb:994:5:994:5 | a [element 2] : | +| array_flow.rb:995:5:995:5 | b [element 2] : | array_flow.rb:1000:10:1000:10 | b [element 2] : | +| array_flow.rb:995:5:995:5 | b [element 2] : | array_flow.rb:1000:10:1000:10 | b [element 2] : | | array_flow.rb:995:9:995:9 | a [element 2] : | array_flow.rb:995:9:998:7 | call to repeated_permutation [element 2] : | | array_flow.rb:995:9:995:9 | a [element 2] : | array_flow.rb:995:9:998:7 | call to repeated_permutation [element 2] : | | array_flow.rb:995:9:995:9 | a [element 2] : | array_flow.rb:995:39:995:39 | x [element] : | | array_flow.rb:995:9:995:9 | a [element 2] : | array_flow.rb:995:39:995:39 | x [element] : | -| array_flow.rb:995:9:998:7 | call to repeated_permutation [element 2] : | array_flow.rb:1000:10:1000:10 | b [element 2] : | -| array_flow.rb:995:9:998:7 | call to repeated_permutation [element 2] : | array_flow.rb:1000:10:1000:10 | b [element 2] : | +| array_flow.rb:995:9:998:7 | call to repeated_permutation [element 2] : | array_flow.rb:995:5:995:5 | b [element 2] : | +| array_flow.rb:995:9:998:7 | call to repeated_permutation [element 2] : | array_flow.rb:995:5:995:5 | b [element 2] : | | array_flow.rb:995:39:995:39 | x [element] : | array_flow.rb:996:14:996:14 | x [element] : | | array_flow.rb:995:39:995:39 | x [element] : | array_flow.rb:996:14:996:14 | x [element] : | | array_flow.rb:995:39:995:39 | x [element] : | array_flow.rb:997:14:997:14 | x [element] : | @@ -1785,10 +2240,12 @@ edges | array_flow.rb:997:14:997:14 | x [element] : | array_flow.rb:997:14:997:17 | ...[...] | | array_flow.rb:1000:10:1000:10 | b [element 2] : | array_flow.rb:1000:10:1000:13 | ...[...] | | array_flow.rb:1000:10:1000:10 | b [element 2] : | array_flow.rb:1000:10:1000:13 | ...[...] | +| array_flow.rb:1006:5:1006:5 | b [element 0] : | array_flow.rb:1008:10:1008:10 | b [element 0] : | +| array_flow.rb:1006:5:1006:5 | b [element 0] : | array_flow.rb:1008:10:1008:10 | b [element 0] : | | array_flow.rb:1006:9:1006:9 | [post] a [element 0] : | array_flow.rb:1007:10:1007:10 | a [element 0] : | | array_flow.rb:1006:9:1006:9 | [post] a [element 0] : | array_flow.rb:1007:10:1007:10 | a [element 0] : | -| array_flow.rb:1006:9:1006:33 | call to replace [element 0] : | array_flow.rb:1008:10:1008:10 | b [element 0] : | -| array_flow.rb:1006:9:1006:33 | call to replace [element 0] : | array_flow.rb:1008:10:1008:10 | b [element 0] : | +| array_flow.rb:1006:9:1006:33 | call to replace [element 0] : | array_flow.rb:1006:5:1006:5 | b [element 0] : | +| array_flow.rb:1006:9:1006:33 | call to replace [element 0] : | array_flow.rb:1006:5:1006:5 | b [element 0] : | | array_flow.rb:1006:20:1006:31 | call to source : | array_flow.rb:1006:9:1006:9 | [post] a [element 0] : | | array_flow.rb:1006:20:1006:31 | call to source : | array_flow.rb:1006:9:1006:9 | [post] a [element 0] : | | array_flow.rb:1006:20:1006:31 | call to source : | array_flow.rb:1006:9:1006:33 | call to replace [element 0] : | @@ -1797,24 +2254,30 @@ edges | array_flow.rb:1007:10:1007:10 | a [element 0] : | array_flow.rb:1007:10:1007:13 | ...[...] | | array_flow.rb:1008:10:1008:10 | b [element 0] : | array_flow.rb:1008:10:1008:13 | ...[...] | | array_flow.rb:1008:10:1008:10 | b [element 0] : | array_flow.rb:1008:10:1008:13 | ...[...] | -| array_flow.rb:1012:16:1012:28 | call to source : | array_flow.rb:1013:9:1013:9 | a [element 2] : | -| array_flow.rb:1012:16:1012:28 | call to source : | array_flow.rb:1013:9:1013:9 | a [element 2] : | -| array_flow.rb:1012:16:1012:28 | call to source : | array_flow.rb:1018:10:1018:10 | a [element 2] : | -| array_flow.rb:1012:16:1012:28 | call to source : | array_flow.rb:1018:10:1018:10 | a [element 2] : | -| array_flow.rb:1012:31:1012:43 | call to source : | array_flow.rb:1013:9:1013:9 | a [element 3] : | -| array_flow.rb:1012:31:1012:43 | call to source : | array_flow.rb:1013:9:1013:9 | a [element 3] : | -| array_flow.rb:1012:31:1012:43 | call to source : | array_flow.rb:1019:10:1019:10 | a [element 3] : | -| array_flow.rb:1012:31:1012:43 | call to source : | array_flow.rb:1019:10:1019:10 | a [element 3] : | +| array_flow.rb:1012:5:1012:5 | a [element 2] : | array_flow.rb:1013:9:1013:9 | a [element 2] : | +| array_flow.rb:1012:5:1012:5 | a [element 2] : | array_flow.rb:1013:9:1013:9 | a [element 2] : | +| array_flow.rb:1012:5:1012:5 | a [element 2] : | array_flow.rb:1018:10:1018:10 | a [element 2] : | +| array_flow.rb:1012:5:1012:5 | a [element 2] : | array_flow.rb:1018:10:1018:10 | a [element 2] : | +| array_flow.rb:1012:5:1012:5 | a [element 3] : | array_flow.rb:1013:9:1013:9 | a [element 3] : | +| array_flow.rb:1012:5:1012:5 | a [element 3] : | array_flow.rb:1013:9:1013:9 | a [element 3] : | +| array_flow.rb:1012:5:1012:5 | a [element 3] : | array_flow.rb:1019:10:1019:10 | a [element 3] : | +| array_flow.rb:1012:5:1012:5 | a [element 3] : | array_flow.rb:1019:10:1019:10 | a [element 3] : | +| array_flow.rb:1012:16:1012:28 | call to source : | array_flow.rb:1012:5:1012:5 | a [element 2] : | +| array_flow.rb:1012:16:1012:28 | call to source : | array_flow.rb:1012:5:1012:5 | a [element 2] : | +| array_flow.rb:1012:31:1012:43 | call to source : | array_flow.rb:1012:5:1012:5 | a [element 3] : | +| array_flow.rb:1012:31:1012:43 | call to source : | array_flow.rb:1012:5:1012:5 | a [element 3] : | +| array_flow.rb:1013:5:1013:5 | b [element] : | array_flow.rb:1014:10:1014:10 | b [element] : | +| array_flow.rb:1013:5:1013:5 | b [element] : | array_flow.rb:1014:10:1014:10 | b [element] : | +| array_flow.rb:1013:5:1013:5 | b [element] : | array_flow.rb:1015:10:1015:10 | b [element] : | +| array_flow.rb:1013:5:1013:5 | b [element] : | array_flow.rb:1015:10:1015:10 | b [element] : | +| array_flow.rb:1013:5:1013:5 | b [element] : | array_flow.rb:1016:10:1016:10 | b [element] : | +| array_flow.rb:1013:5:1013:5 | b [element] : | array_flow.rb:1016:10:1016:10 | b [element] : | | array_flow.rb:1013:9:1013:9 | a [element 2] : | array_flow.rb:1013:9:1013:17 | call to reverse [element] : | | array_flow.rb:1013:9:1013:9 | a [element 2] : | array_flow.rb:1013:9:1013:17 | call to reverse [element] : | | array_flow.rb:1013:9:1013:9 | a [element 3] : | array_flow.rb:1013:9:1013:17 | call to reverse [element] : | | array_flow.rb:1013:9:1013:9 | a [element 3] : | array_flow.rb:1013:9:1013:17 | call to reverse [element] : | -| array_flow.rb:1013:9:1013:17 | call to reverse [element] : | array_flow.rb:1014:10:1014:10 | b [element] : | -| array_flow.rb:1013:9:1013:17 | call to reverse [element] : | array_flow.rb:1014:10:1014:10 | b [element] : | -| array_flow.rb:1013:9:1013:17 | call to reverse [element] : | array_flow.rb:1015:10:1015:10 | b [element] : | -| array_flow.rb:1013:9:1013:17 | call to reverse [element] : | array_flow.rb:1015:10:1015:10 | b [element] : | -| array_flow.rb:1013:9:1013:17 | call to reverse [element] : | array_flow.rb:1016:10:1016:10 | b [element] : | -| array_flow.rb:1013:9:1013:17 | call to reverse [element] : | array_flow.rb:1016:10:1016:10 | b [element] : | +| array_flow.rb:1013:9:1013:17 | call to reverse [element] : | array_flow.rb:1013:5:1013:5 | b [element] : | +| array_flow.rb:1013:9:1013:17 | call to reverse [element] : | array_flow.rb:1013:5:1013:5 | b [element] : | | array_flow.rb:1014:10:1014:10 | b [element] : | array_flow.rb:1014:10:1014:13 | ...[...] | | array_flow.rb:1014:10:1014:10 | b [element] : | array_flow.rb:1014:10:1014:13 | ...[...] | | array_flow.rb:1015:10:1015:10 | b [element] : | array_flow.rb:1015:10:1015:13 | ...[...] | @@ -1825,14 +2288,24 @@ edges | array_flow.rb:1018:10:1018:10 | a [element 2] : | array_flow.rb:1018:10:1018:13 | ...[...] | | array_flow.rb:1019:10:1019:10 | a [element 3] : | array_flow.rb:1019:10:1019:13 | ...[...] | | array_flow.rb:1019:10:1019:10 | a [element 3] : | array_flow.rb:1019:10:1019:13 | ...[...] | -| array_flow.rb:1023:16:1023:28 | call to source : | array_flow.rb:1024:9:1024:9 | a [element 2] : | -| array_flow.rb:1023:16:1023:28 | call to source : | array_flow.rb:1024:9:1024:9 | a [element 2] : | -| array_flow.rb:1023:16:1023:28 | call to source : | array_flow.rb:1029:10:1029:10 | a [element 2] : | -| array_flow.rb:1023:16:1023:28 | call to source : | array_flow.rb:1029:10:1029:10 | a [element 2] : | -| array_flow.rb:1023:31:1023:43 | call to source : | array_flow.rb:1024:9:1024:9 | a [element 3] : | -| array_flow.rb:1023:31:1023:43 | call to source : | array_flow.rb:1024:9:1024:9 | a [element 3] : | -| array_flow.rb:1023:31:1023:43 | call to source : | array_flow.rb:1030:10:1030:10 | a [element 3] : | -| array_flow.rb:1023:31:1023:43 | call to source : | array_flow.rb:1030:10:1030:10 | a [element 3] : | +| array_flow.rb:1023:5:1023:5 | a [element 2] : | array_flow.rb:1024:9:1024:9 | a [element 2] : | +| array_flow.rb:1023:5:1023:5 | a [element 2] : | array_flow.rb:1024:9:1024:9 | a [element 2] : | +| array_flow.rb:1023:5:1023:5 | a [element 2] : | array_flow.rb:1029:10:1029:10 | a [element 2] : | +| array_flow.rb:1023:5:1023:5 | a [element 2] : | array_flow.rb:1029:10:1029:10 | a [element 2] : | +| array_flow.rb:1023:5:1023:5 | a [element 3] : | array_flow.rb:1024:9:1024:9 | a [element 3] : | +| array_flow.rb:1023:5:1023:5 | a [element 3] : | array_flow.rb:1024:9:1024:9 | a [element 3] : | +| array_flow.rb:1023:5:1023:5 | a [element 3] : | array_flow.rb:1030:10:1030:10 | a [element 3] : | +| array_flow.rb:1023:5:1023:5 | a [element 3] : | array_flow.rb:1030:10:1030:10 | a [element 3] : | +| array_flow.rb:1023:16:1023:28 | call to source : | array_flow.rb:1023:5:1023:5 | a [element 2] : | +| array_flow.rb:1023:16:1023:28 | call to source : | array_flow.rb:1023:5:1023:5 | a [element 2] : | +| array_flow.rb:1023:31:1023:43 | call to source : | array_flow.rb:1023:5:1023:5 | a [element 3] : | +| array_flow.rb:1023:31:1023:43 | call to source : | array_flow.rb:1023:5:1023:5 | a [element 3] : | +| array_flow.rb:1024:5:1024:5 | b [element] : | array_flow.rb:1025:10:1025:10 | b [element] : | +| array_flow.rb:1024:5:1024:5 | b [element] : | array_flow.rb:1025:10:1025:10 | b [element] : | +| array_flow.rb:1024:5:1024:5 | b [element] : | array_flow.rb:1026:10:1026:10 | b [element] : | +| array_flow.rb:1024:5:1024:5 | b [element] : | array_flow.rb:1026:10:1026:10 | b [element] : | +| array_flow.rb:1024:5:1024:5 | b [element] : | array_flow.rb:1027:10:1027:10 | b [element] : | +| array_flow.rb:1024:5:1024:5 | b [element] : | array_flow.rb:1027:10:1027:10 | b [element] : | | array_flow.rb:1024:9:1024:9 | [post] a [element] : | array_flow.rb:1028:10:1028:10 | a [element] : | | array_flow.rb:1024:9:1024:9 | [post] a [element] : | array_flow.rb:1028:10:1028:10 | a [element] : | | array_flow.rb:1024:9:1024:9 | [post] a [element] : | array_flow.rb:1029:10:1029:10 | a [element] : | @@ -1847,12 +2320,8 @@ edges | array_flow.rb:1024:9:1024:9 | a [element 3] : | array_flow.rb:1024:9:1024:9 | [post] a [element] : | | array_flow.rb:1024:9:1024:9 | a [element 3] : | array_flow.rb:1024:9:1024:18 | call to reverse! [element] : | | array_flow.rb:1024:9:1024:9 | a [element 3] : | array_flow.rb:1024:9:1024:18 | call to reverse! [element] : | -| array_flow.rb:1024:9:1024:18 | call to reverse! [element] : | array_flow.rb:1025:10:1025:10 | b [element] : | -| array_flow.rb:1024:9:1024:18 | call to reverse! [element] : | array_flow.rb:1025:10:1025:10 | b [element] : | -| array_flow.rb:1024:9:1024:18 | call to reverse! [element] : | array_flow.rb:1026:10:1026:10 | b [element] : | -| array_flow.rb:1024:9:1024:18 | call to reverse! [element] : | array_flow.rb:1026:10:1026:10 | b [element] : | -| array_flow.rb:1024:9:1024:18 | call to reverse! [element] : | array_flow.rb:1027:10:1027:10 | b [element] : | -| array_flow.rb:1024:9:1024:18 | call to reverse! [element] : | array_flow.rb:1027:10:1027:10 | b [element] : | +| array_flow.rb:1024:9:1024:18 | call to reverse! [element] : | array_flow.rb:1024:5:1024:5 | b [element] : | +| array_flow.rb:1024:9:1024:18 | call to reverse! [element] : | array_flow.rb:1024:5:1024:5 | b [element] : | | array_flow.rb:1025:10:1025:10 | b [element] : | array_flow.rb:1025:10:1025:13 | ...[...] | | array_flow.rb:1025:10:1025:10 | b [element] : | array_flow.rb:1025:10:1025:13 | ...[...] | | array_flow.rb:1026:10:1026:10 | b [element] : | array_flow.rb:1026:10:1026:13 | ...[...] | @@ -1869,66 +2338,84 @@ edges | array_flow.rb:1030:10:1030:10 | a [element 3] : | array_flow.rb:1030:10:1030:13 | ...[...] | | array_flow.rb:1030:10:1030:10 | a [element] : | array_flow.rb:1030:10:1030:13 | ...[...] | | array_flow.rb:1030:10:1030:10 | a [element] : | array_flow.rb:1030:10:1030:13 | ...[...] | -| array_flow.rb:1034:16:1034:26 | call to source : | array_flow.rb:1035:9:1035:9 | a [element 2] : | -| array_flow.rb:1034:16:1034:26 | call to source : | array_flow.rb:1035:9:1035:9 | a [element 2] : | +| array_flow.rb:1034:5:1034:5 | a [element 2] : | array_flow.rb:1035:9:1035:9 | a [element 2] : | +| array_flow.rb:1034:5:1034:5 | a [element 2] : | array_flow.rb:1035:9:1035:9 | a [element 2] : | +| array_flow.rb:1034:16:1034:26 | call to source : | array_flow.rb:1034:5:1034:5 | a [element 2] : | +| array_flow.rb:1034:16:1034:26 | call to source : | array_flow.rb:1034:5:1034:5 | a [element 2] : | +| array_flow.rb:1035:5:1035:5 | b [element 2] : | array_flow.rb:1038:10:1038:10 | b [element 2] : | +| array_flow.rb:1035:5:1035:5 | b [element 2] : | array_flow.rb:1038:10:1038:10 | b [element 2] : | | array_flow.rb:1035:9:1035:9 | a [element 2] : | array_flow.rb:1035:9:1037:7 | call to reverse_each [element 2] : | | array_flow.rb:1035:9:1035:9 | a [element 2] : | array_flow.rb:1035:9:1037:7 | call to reverse_each [element 2] : | | array_flow.rb:1035:9:1035:9 | a [element 2] : | array_flow.rb:1035:28:1035:28 | x : | | array_flow.rb:1035:9:1035:9 | a [element 2] : | array_flow.rb:1035:28:1035:28 | x : | -| array_flow.rb:1035:9:1037:7 | call to reverse_each [element 2] : | array_flow.rb:1038:10:1038:10 | b [element 2] : | -| array_flow.rb:1035:9:1037:7 | call to reverse_each [element 2] : | array_flow.rb:1038:10:1038:10 | b [element 2] : | +| array_flow.rb:1035:9:1037:7 | call to reverse_each [element 2] : | array_flow.rb:1035:5:1035:5 | b [element 2] : | +| array_flow.rb:1035:9:1037:7 | call to reverse_each [element 2] : | array_flow.rb:1035:5:1035:5 | b [element 2] : | | array_flow.rb:1035:28:1035:28 | x : | array_flow.rb:1036:14:1036:14 | x | | array_flow.rb:1035:28:1035:28 | x : | array_flow.rb:1036:14:1036:14 | x | | array_flow.rb:1038:10:1038:10 | b [element 2] : | array_flow.rb:1038:10:1038:13 | ...[...] | | array_flow.rb:1038:10:1038:10 | b [element 2] : | array_flow.rb:1038:10:1038:13 | ...[...] | -| array_flow.rb:1042:16:1042:26 | call to source : | array_flow.rb:1043:5:1043:5 | a [element 2] : | -| array_flow.rb:1042:16:1042:26 | call to source : | array_flow.rb:1043:5:1043:5 | a [element 2] : | +| array_flow.rb:1042:5:1042:5 | a [element 2] : | array_flow.rb:1043:5:1043:5 | a [element 2] : | +| array_flow.rb:1042:5:1042:5 | a [element 2] : | array_flow.rb:1043:5:1043:5 | a [element 2] : | +| array_flow.rb:1042:16:1042:26 | call to source : | array_flow.rb:1042:5:1042:5 | a [element 2] : | +| array_flow.rb:1042:16:1042:26 | call to source : | array_flow.rb:1042:5:1042:5 | a [element 2] : | | array_flow.rb:1043:5:1043:5 | a [element 2] : | array_flow.rb:1043:18:1043:18 | x : | | array_flow.rb:1043:5:1043:5 | a [element 2] : | array_flow.rb:1043:18:1043:18 | x : | | array_flow.rb:1043:18:1043:18 | x : | array_flow.rb:1044:14:1044:14 | x | | array_flow.rb:1043:18:1043:18 | x : | array_flow.rb:1044:14:1044:14 | x | -| array_flow.rb:1052:10:1052:22 | call to source : | array_flow.rb:1054:9:1054:9 | a [element 0] : | -| array_flow.rb:1052:10:1052:22 | call to source : | array_flow.rb:1054:9:1054:9 | a [element 0] : | -| array_flow.rb:1052:10:1052:22 | call to source : | array_flow.rb:1060:9:1060:9 | a [element 0] : | -| array_flow.rb:1052:10:1052:22 | call to source : | array_flow.rb:1060:9:1060:9 | a [element 0] : | -| array_flow.rb:1052:10:1052:22 | call to source : | array_flow.rb:1066:9:1066:9 | a [element 0] : | -| array_flow.rb:1052:10:1052:22 | call to source : | array_flow.rb:1066:9:1066:9 | a [element 0] : | -| array_flow.rb:1052:10:1052:22 | call to source : | array_flow.rb:1072:9:1072:9 | a [element 0] : | -| array_flow.rb:1052:10:1052:22 | call to source : | array_flow.rb:1072:9:1072:9 | a [element 0] : | -| array_flow.rb:1052:28:1052:40 | call to source : | array_flow.rb:1054:9:1054:9 | a [element 2] : | -| array_flow.rb:1052:28:1052:40 | call to source : | array_flow.rb:1054:9:1054:9 | a [element 2] : | -| array_flow.rb:1052:28:1052:40 | call to source : | array_flow.rb:1060:9:1060:9 | a [element 2] : | -| array_flow.rb:1052:28:1052:40 | call to source : | array_flow.rb:1060:9:1060:9 | a [element 2] : | -| array_flow.rb:1052:28:1052:40 | call to source : | array_flow.rb:1066:9:1066:9 | a [element 2] : | -| array_flow.rb:1052:28:1052:40 | call to source : | array_flow.rb:1066:9:1066:9 | a [element 2] : | -| array_flow.rb:1052:28:1052:40 | call to source : | array_flow.rb:1072:9:1072:9 | a [element 2] : | -| array_flow.rb:1052:28:1052:40 | call to source : | array_flow.rb:1072:9:1072:9 | a [element 2] : | -| array_flow.rb:1052:43:1052:55 | call to source : | array_flow.rb:1054:9:1054:9 | a [element 3] : | -| array_flow.rb:1052:43:1052:55 | call to source : | array_flow.rb:1054:9:1054:9 | a [element 3] : | -| array_flow.rb:1052:43:1052:55 | call to source : | array_flow.rb:1060:9:1060:9 | a [element 3] : | -| array_flow.rb:1052:43:1052:55 | call to source : | array_flow.rb:1060:9:1060:9 | a [element 3] : | -| array_flow.rb:1052:43:1052:55 | call to source : | array_flow.rb:1066:9:1066:9 | a [element 3] : | -| array_flow.rb:1052:43:1052:55 | call to source : | array_flow.rb:1066:9:1066:9 | a [element 3] : | -| array_flow.rb:1052:43:1052:55 | call to source : | array_flow.rb:1072:9:1072:9 | a [element 3] : | -| array_flow.rb:1052:43:1052:55 | call to source : | array_flow.rb:1072:9:1072:9 | a [element 3] : | +| array_flow.rb:1052:5:1052:5 | a [element 0] : | array_flow.rb:1054:9:1054:9 | a [element 0] : | +| array_flow.rb:1052:5:1052:5 | a [element 0] : | array_flow.rb:1054:9:1054:9 | a [element 0] : | +| array_flow.rb:1052:5:1052:5 | a [element 0] : | array_flow.rb:1060:9:1060:9 | a [element 0] : | +| array_flow.rb:1052:5:1052:5 | a [element 0] : | array_flow.rb:1060:9:1060:9 | a [element 0] : | +| array_flow.rb:1052:5:1052:5 | a [element 0] : | array_flow.rb:1066:9:1066:9 | a [element 0] : | +| array_flow.rb:1052:5:1052:5 | a [element 0] : | array_flow.rb:1066:9:1066:9 | a [element 0] : | +| array_flow.rb:1052:5:1052:5 | a [element 0] : | array_flow.rb:1072:9:1072:9 | a [element 0] : | +| array_flow.rb:1052:5:1052:5 | a [element 0] : | array_flow.rb:1072:9:1072:9 | a [element 0] : | +| array_flow.rb:1052:5:1052:5 | a [element 2] : | array_flow.rb:1054:9:1054:9 | a [element 2] : | +| array_flow.rb:1052:5:1052:5 | a [element 2] : | array_flow.rb:1054:9:1054:9 | a [element 2] : | +| array_flow.rb:1052:5:1052:5 | a [element 2] : | array_flow.rb:1060:9:1060:9 | a [element 2] : | +| array_flow.rb:1052:5:1052:5 | a [element 2] : | array_flow.rb:1060:9:1060:9 | a [element 2] : | +| array_flow.rb:1052:5:1052:5 | a [element 2] : | array_flow.rb:1066:9:1066:9 | a [element 2] : | +| array_flow.rb:1052:5:1052:5 | a [element 2] : | array_flow.rb:1066:9:1066:9 | a [element 2] : | +| array_flow.rb:1052:5:1052:5 | a [element 2] : | array_flow.rb:1072:9:1072:9 | a [element 2] : | +| array_flow.rb:1052:5:1052:5 | a [element 2] : | array_flow.rb:1072:9:1072:9 | a [element 2] : | +| array_flow.rb:1052:5:1052:5 | a [element 3] : | array_flow.rb:1054:9:1054:9 | a [element 3] : | +| array_flow.rb:1052:5:1052:5 | a [element 3] : | array_flow.rb:1054:9:1054:9 | a [element 3] : | +| array_flow.rb:1052:5:1052:5 | a [element 3] : | array_flow.rb:1060:9:1060:9 | a [element 3] : | +| array_flow.rb:1052:5:1052:5 | a [element 3] : | array_flow.rb:1060:9:1060:9 | a [element 3] : | +| array_flow.rb:1052:5:1052:5 | a [element 3] : | array_flow.rb:1066:9:1066:9 | a [element 3] : | +| array_flow.rb:1052:5:1052:5 | a [element 3] : | array_flow.rb:1066:9:1066:9 | a [element 3] : | +| array_flow.rb:1052:5:1052:5 | a [element 3] : | array_flow.rb:1072:9:1072:9 | a [element 3] : | +| array_flow.rb:1052:5:1052:5 | a [element 3] : | array_flow.rb:1072:9:1072:9 | a [element 3] : | +| array_flow.rb:1052:10:1052:22 | call to source : | array_flow.rb:1052:5:1052:5 | a [element 0] : | +| array_flow.rb:1052:10:1052:22 | call to source : | array_flow.rb:1052:5:1052:5 | a [element 0] : | +| array_flow.rb:1052:28:1052:40 | call to source : | array_flow.rb:1052:5:1052:5 | a [element 2] : | +| array_flow.rb:1052:28:1052:40 | call to source : | array_flow.rb:1052:5:1052:5 | a [element 2] : | +| array_flow.rb:1052:43:1052:55 | call to source : | array_flow.rb:1052:5:1052:5 | a [element 3] : | +| array_flow.rb:1052:43:1052:55 | call to source : | array_flow.rb:1052:5:1052:5 | a [element 3] : | +| array_flow.rb:1054:5:1054:5 | b [element 1] : | array_flow.rb:1056:10:1056:10 | b [element 1] : | +| array_flow.rb:1054:5:1054:5 | b [element 1] : | array_flow.rb:1056:10:1056:10 | b [element 1] : | +| array_flow.rb:1054:5:1054:5 | b [element 2] : | array_flow.rb:1057:10:1057:10 | b [element 2] : | +| array_flow.rb:1054:5:1054:5 | b [element 2] : | array_flow.rb:1057:10:1057:10 | b [element 2] : | +| array_flow.rb:1054:5:1054:5 | b [element] : | array_flow.rb:1055:10:1055:10 | b [element] : | +| array_flow.rb:1054:5:1054:5 | b [element] : | array_flow.rb:1055:10:1055:10 | b [element] : | +| array_flow.rb:1054:5:1054:5 | b [element] : | array_flow.rb:1056:10:1056:10 | b [element] : | +| array_flow.rb:1054:5:1054:5 | b [element] : | array_flow.rb:1056:10:1056:10 | b [element] : | +| array_flow.rb:1054:5:1054:5 | b [element] : | array_flow.rb:1057:10:1057:10 | b [element] : | +| array_flow.rb:1054:5:1054:5 | b [element] : | array_flow.rb:1057:10:1057:10 | b [element] : | +| array_flow.rb:1054:5:1054:5 | b [element] : | array_flow.rb:1058:10:1058:10 | b [element] : | +| array_flow.rb:1054:5:1054:5 | b [element] : | array_flow.rb:1058:10:1058:10 | b [element] : | | array_flow.rb:1054:9:1054:9 | a [element 0] : | array_flow.rb:1054:9:1054:16 | call to rotate [element] : | | array_flow.rb:1054:9:1054:9 | a [element 0] : | array_flow.rb:1054:9:1054:16 | call to rotate [element] : | | array_flow.rb:1054:9:1054:9 | a [element 2] : | array_flow.rb:1054:9:1054:16 | call to rotate [element 1] : | | array_flow.rb:1054:9:1054:9 | a [element 2] : | array_flow.rb:1054:9:1054:16 | call to rotate [element 1] : | | array_flow.rb:1054:9:1054:9 | a [element 3] : | array_flow.rb:1054:9:1054:16 | call to rotate [element 2] : | | array_flow.rb:1054:9:1054:9 | a [element 3] : | array_flow.rb:1054:9:1054:16 | call to rotate [element 2] : | -| array_flow.rb:1054:9:1054:16 | call to rotate [element 1] : | array_flow.rb:1056:10:1056:10 | b [element 1] : | -| array_flow.rb:1054:9:1054:16 | call to rotate [element 1] : | array_flow.rb:1056:10:1056:10 | b [element 1] : | -| array_flow.rb:1054:9:1054:16 | call to rotate [element 2] : | array_flow.rb:1057:10:1057:10 | b [element 2] : | -| array_flow.rb:1054:9:1054:16 | call to rotate [element 2] : | array_flow.rb:1057:10:1057:10 | b [element 2] : | -| array_flow.rb:1054:9:1054:16 | call to rotate [element] : | array_flow.rb:1055:10:1055:10 | b [element] : | -| array_flow.rb:1054:9:1054:16 | call to rotate [element] : | array_flow.rb:1055:10:1055:10 | b [element] : | -| array_flow.rb:1054:9:1054:16 | call to rotate [element] : | array_flow.rb:1056:10:1056:10 | b [element] : | -| array_flow.rb:1054:9:1054:16 | call to rotate [element] : | array_flow.rb:1056:10:1056:10 | b [element] : | -| array_flow.rb:1054:9:1054:16 | call to rotate [element] : | array_flow.rb:1057:10:1057:10 | b [element] : | -| array_flow.rb:1054:9:1054:16 | call to rotate [element] : | array_flow.rb:1057:10:1057:10 | b [element] : | -| array_flow.rb:1054:9:1054:16 | call to rotate [element] : | array_flow.rb:1058:10:1058:10 | b [element] : | -| array_flow.rb:1054:9:1054:16 | call to rotate [element] : | array_flow.rb:1058:10:1058:10 | b [element] : | +| array_flow.rb:1054:9:1054:16 | call to rotate [element 1] : | array_flow.rb:1054:5:1054:5 | b [element 1] : | +| array_flow.rb:1054:9:1054:16 | call to rotate [element 1] : | array_flow.rb:1054:5:1054:5 | b [element 1] : | +| array_flow.rb:1054:9:1054:16 | call to rotate [element 2] : | array_flow.rb:1054:5:1054:5 | b [element 2] : | +| array_flow.rb:1054:9:1054:16 | call to rotate [element 2] : | array_flow.rb:1054:5:1054:5 | b [element 2] : | +| array_flow.rb:1054:9:1054:16 | call to rotate [element] : | array_flow.rb:1054:5:1054:5 | b [element] : | +| array_flow.rb:1054:9:1054:16 | call to rotate [element] : | array_flow.rb:1054:5:1054:5 | b [element] : | | array_flow.rb:1055:10:1055:10 | b [element] : | array_flow.rb:1055:10:1055:13 | ...[...] | | array_flow.rb:1055:10:1055:10 | b [element] : | array_flow.rb:1055:10:1055:13 | ...[...] | | array_flow.rb:1056:10:1056:10 | b [element 1] : | array_flow.rb:1056:10:1056:13 | ...[...] | @@ -1941,24 +2428,30 @@ edges | array_flow.rb:1057:10:1057:10 | b [element] : | array_flow.rb:1057:10:1057:13 | ...[...] | | array_flow.rb:1058:10:1058:10 | b [element] : | array_flow.rb:1058:10:1058:13 | ...[...] | | array_flow.rb:1058:10:1058:10 | b [element] : | array_flow.rb:1058:10:1058:13 | ...[...] | +| array_flow.rb:1060:5:1060:5 | b [element 0] : | array_flow.rb:1061:10:1061:10 | b [element 0] : | +| array_flow.rb:1060:5:1060:5 | b [element 0] : | array_flow.rb:1061:10:1061:10 | b [element 0] : | +| array_flow.rb:1060:5:1060:5 | b [element 1] : | array_flow.rb:1062:10:1062:10 | b [element 1] : | +| array_flow.rb:1060:5:1060:5 | b [element 1] : | array_flow.rb:1062:10:1062:10 | b [element 1] : | +| array_flow.rb:1060:5:1060:5 | b [element] : | array_flow.rb:1061:10:1061:10 | b [element] : | +| array_flow.rb:1060:5:1060:5 | b [element] : | array_flow.rb:1061:10:1061:10 | b [element] : | +| array_flow.rb:1060:5:1060:5 | b [element] : | array_flow.rb:1062:10:1062:10 | b [element] : | +| array_flow.rb:1060:5:1060:5 | b [element] : | array_flow.rb:1062:10:1062:10 | b [element] : | +| array_flow.rb:1060:5:1060:5 | b [element] : | array_flow.rb:1063:10:1063:10 | b [element] : | +| array_flow.rb:1060:5:1060:5 | b [element] : | array_flow.rb:1063:10:1063:10 | b [element] : | +| array_flow.rb:1060:5:1060:5 | b [element] : | array_flow.rb:1064:10:1064:10 | b [element] : | +| array_flow.rb:1060:5:1060:5 | b [element] : | array_flow.rb:1064:10:1064:10 | b [element] : | | array_flow.rb:1060:9:1060:9 | a [element 0] : | array_flow.rb:1060:9:1060:19 | call to rotate [element] : | | array_flow.rb:1060:9:1060:9 | a [element 0] : | array_flow.rb:1060:9:1060:19 | call to rotate [element] : | | array_flow.rb:1060:9:1060:9 | a [element 2] : | array_flow.rb:1060:9:1060:19 | call to rotate [element 0] : | | array_flow.rb:1060:9:1060:9 | a [element 2] : | array_flow.rb:1060:9:1060:19 | call to rotate [element 0] : | | array_flow.rb:1060:9:1060:9 | a [element 3] : | array_flow.rb:1060:9:1060:19 | call to rotate [element 1] : | | array_flow.rb:1060:9:1060:9 | a [element 3] : | array_flow.rb:1060:9:1060:19 | call to rotate [element 1] : | -| array_flow.rb:1060:9:1060:19 | call to rotate [element 0] : | array_flow.rb:1061:10:1061:10 | b [element 0] : | -| array_flow.rb:1060:9:1060:19 | call to rotate [element 0] : | array_flow.rb:1061:10:1061:10 | b [element 0] : | -| array_flow.rb:1060:9:1060:19 | call to rotate [element 1] : | array_flow.rb:1062:10:1062:10 | b [element 1] : | -| array_flow.rb:1060:9:1060:19 | call to rotate [element 1] : | array_flow.rb:1062:10:1062:10 | b [element 1] : | -| array_flow.rb:1060:9:1060:19 | call to rotate [element] : | array_flow.rb:1061:10:1061:10 | b [element] : | -| array_flow.rb:1060:9:1060:19 | call to rotate [element] : | array_flow.rb:1061:10:1061:10 | b [element] : | -| array_flow.rb:1060:9:1060:19 | call to rotate [element] : | array_flow.rb:1062:10:1062:10 | b [element] : | -| array_flow.rb:1060:9:1060:19 | call to rotate [element] : | array_flow.rb:1062:10:1062:10 | b [element] : | -| array_flow.rb:1060:9:1060:19 | call to rotate [element] : | array_flow.rb:1063:10:1063:10 | b [element] : | -| array_flow.rb:1060:9:1060:19 | call to rotate [element] : | array_flow.rb:1063:10:1063:10 | b [element] : | -| array_flow.rb:1060:9:1060:19 | call to rotate [element] : | array_flow.rb:1064:10:1064:10 | b [element] : | -| array_flow.rb:1060:9:1060:19 | call to rotate [element] : | array_flow.rb:1064:10:1064:10 | b [element] : | +| array_flow.rb:1060:9:1060:19 | call to rotate [element 0] : | array_flow.rb:1060:5:1060:5 | b [element 0] : | +| array_flow.rb:1060:9:1060:19 | call to rotate [element 0] : | array_flow.rb:1060:5:1060:5 | b [element 0] : | +| array_flow.rb:1060:9:1060:19 | call to rotate [element 1] : | array_flow.rb:1060:5:1060:5 | b [element 1] : | +| array_flow.rb:1060:9:1060:19 | call to rotate [element 1] : | array_flow.rb:1060:5:1060:5 | b [element 1] : | +| array_flow.rb:1060:9:1060:19 | call to rotate [element] : | array_flow.rb:1060:5:1060:5 | b [element] : | +| array_flow.rb:1060:9:1060:19 | call to rotate [element] : | array_flow.rb:1060:5:1060:5 | b [element] : | | array_flow.rb:1061:10:1061:10 | b [element 0] : | array_flow.rb:1061:10:1061:13 | ...[...] | | array_flow.rb:1061:10:1061:10 | b [element 0] : | array_flow.rb:1061:10:1061:13 | ...[...] | | array_flow.rb:1061:10:1061:10 | b [element] : | array_flow.rb:1061:10:1061:13 | ...[...] | @@ -1971,38 +2464,46 @@ edges | array_flow.rb:1063:10:1063:10 | b [element] : | array_flow.rb:1063:10:1063:13 | ...[...] | | array_flow.rb:1064:10:1064:10 | b [element] : | array_flow.rb:1064:10:1064:13 | ...[...] | | array_flow.rb:1064:10:1064:10 | b [element] : | array_flow.rb:1064:10:1064:13 | ...[...] | +| array_flow.rb:1066:5:1066:5 | b [element 0] : | array_flow.rb:1067:10:1067:10 | b [element 0] : | +| array_flow.rb:1066:5:1066:5 | b [element 0] : | array_flow.rb:1067:10:1067:10 | b [element 0] : | +| array_flow.rb:1066:5:1066:5 | b [element 2] : | array_flow.rb:1069:10:1069:10 | b [element 2] : | +| array_flow.rb:1066:5:1066:5 | b [element 2] : | array_flow.rb:1069:10:1069:10 | b [element 2] : | +| array_flow.rb:1066:5:1066:5 | b [element 3] : | array_flow.rb:1070:10:1070:10 | b [element 3] : | +| array_flow.rb:1066:5:1066:5 | b [element 3] : | array_flow.rb:1070:10:1070:10 | b [element 3] : | | array_flow.rb:1066:9:1066:9 | a [element 0] : | array_flow.rb:1066:9:1066:19 | call to rotate [element 0] : | | array_flow.rb:1066:9:1066:9 | a [element 0] : | array_flow.rb:1066:9:1066:19 | call to rotate [element 0] : | | array_flow.rb:1066:9:1066:9 | a [element 2] : | array_flow.rb:1066:9:1066:19 | call to rotate [element 2] : | | array_flow.rb:1066:9:1066:9 | a [element 2] : | array_flow.rb:1066:9:1066:19 | call to rotate [element 2] : | | array_flow.rb:1066:9:1066:9 | a [element 3] : | array_flow.rb:1066:9:1066:19 | call to rotate [element 3] : | | array_flow.rb:1066:9:1066:9 | a [element 3] : | array_flow.rb:1066:9:1066:19 | call to rotate [element 3] : | -| array_flow.rb:1066:9:1066:19 | call to rotate [element 0] : | array_flow.rb:1067:10:1067:10 | b [element 0] : | -| array_flow.rb:1066:9:1066:19 | call to rotate [element 0] : | array_flow.rb:1067:10:1067:10 | b [element 0] : | -| array_flow.rb:1066:9:1066:19 | call to rotate [element 2] : | array_flow.rb:1069:10:1069:10 | b [element 2] : | -| array_flow.rb:1066:9:1066:19 | call to rotate [element 2] : | array_flow.rb:1069:10:1069:10 | b [element 2] : | -| array_flow.rb:1066:9:1066:19 | call to rotate [element 3] : | array_flow.rb:1070:10:1070:10 | b [element 3] : | -| array_flow.rb:1066:9:1066:19 | call to rotate [element 3] : | array_flow.rb:1070:10:1070:10 | b [element 3] : | +| array_flow.rb:1066:9:1066:19 | call to rotate [element 0] : | array_flow.rb:1066:5:1066:5 | b [element 0] : | +| array_flow.rb:1066:9:1066:19 | call to rotate [element 0] : | array_flow.rb:1066:5:1066:5 | b [element 0] : | +| array_flow.rb:1066:9:1066:19 | call to rotate [element 2] : | array_flow.rb:1066:5:1066:5 | b [element 2] : | +| array_flow.rb:1066:9:1066:19 | call to rotate [element 2] : | array_flow.rb:1066:5:1066:5 | b [element 2] : | +| array_flow.rb:1066:9:1066:19 | call to rotate [element 3] : | array_flow.rb:1066:5:1066:5 | b [element 3] : | +| array_flow.rb:1066:9:1066:19 | call to rotate [element 3] : | array_flow.rb:1066:5:1066:5 | b [element 3] : | | array_flow.rb:1067:10:1067:10 | b [element 0] : | array_flow.rb:1067:10:1067:13 | ...[...] | | array_flow.rb:1067:10:1067:10 | b [element 0] : | array_flow.rb:1067:10:1067:13 | ...[...] | | array_flow.rb:1069:10:1069:10 | b [element 2] : | array_flow.rb:1069:10:1069:13 | ...[...] | | array_flow.rb:1069:10:1069:10 | b [element 2] : | array_flow.rb:1069:10:1069:13 | ...[...] | | array_flow.rb:1070:10:1070:10 | b [element 3] : | array_flow.rb:1070:10:1070:13 | ...[...] | | array_flow.rb:1070:10:1070:10 | b [element 3] : | array_flow.rb:1070:10:1070:13 | ...[...] | +| array_flow.rb:1072:5:1072:5 | b [element] : | array_flow.rb:1073:10:1073:10 | b [element] : | +| array_flow.rb:1072:5:1072:5 | b [element] : | array_flow.rb:1073:10:1073:10 | b [element] : | +| array_flow.rb:1072:5:1072:5 | b [element] : | array_flow.rb:1074:10:1074:10 | b [element] : | +| array_flow.rb:1072:5:1072:5 | b [element] : | array_flow.rb:1074:10:1074:10 | b [element] : | +| array_flow.rb:1072:5:1072:5 | b [element] : | array_flow.rb:1075:10:1075:10 | b [element] : | +| array_flow.rb:1072:5:1072:5 | b [element] : | array_flow.rb:1075:10:1075:10 | b [element] : | +| array_flow.rb:1072:5:1072:5 | b [element] : | array_flow.rb:1076:10:1076:10 | b [element] : | +| array_flow.rb:1072:5:1072:5 | b [element] : | array_flow.rb:1076:10:1076:10 | b [element] : | | array_flow.rb:1072:9:1072:9 | a [element 0] : | array_flow.rb:1072:9:1072:19 | call to rotate [element] : | | array_flow.rb:1072:9:1072:9 | a [element 0] : | array_flow.rb:1072:9:1072:19 | call to rotate [element] : | | array_flow.rb:1072:9:1072:9 | a [element 2] : | array_flow.rb:1072:9:1072:19 | call to rotate [element] : | | array_flow.rb:1072:9:1072:9 | a [element 2] : | array_flow.rb:1072:9:1072:19 | call to rotate [element] : | | array_flow.rb:1072:9:1072:9 | a [element 3] : | array_flow.rb:1072:9:1072:19 | call to rotate [element] : | | array_flow.rb:1072:9:1072:9 | a [element 3] : | array_flow.rb:1072:9:1072:19 | call to rotate [element] : | -| array_flow.rb:1072:9:1072:19 | call to rotate [element] : | array_flow.rb:1073:10:1073:10 | b [element] : | -| array_flow.rb:1072:9:1072:19 | call to rotate [element] : | array_flow.rb:1073:10:1073:10 | b [element] : | -| array_flow.rb:1072:9:1072:19 | call to rotate [element] : | array_flow.rb:1074:10:1074:10 | b [element] : | -| array_flow.rb:1072:9:1072:19 | call to rotate [element] : | array_flow.rb:1074:10:1074:10 | b [element] : | -| array_flow.rb:1072:9:1072:19 | call to rotate [element] : | array_flow.rb:1075:10:1075:10 | b [element] : | -| array_flow.rb:1072:9:1072:19 | call to rotate [element] : | array_flow.rb:1075:10:1075:10 | b [element] : | -| array_flow.rb:1072:9:1072:19 | call to rotate [element] : | array_flow.rb:1076:10:1076:10 | b [element] : | -| array_flow.rb:1072:9:1072:19 | call to rotate [element] : | array_flow.rb:1076:10:1076:10 | b [element] : | +| array_flow.rb:1072:9:1072:19 | call to rotate [element] : | array_flow.rb:1072:5:1072:5 | b [element] : | +| array_flow.rb:1072:9:1072:19 | call to rotate [element] : | array_flow.rb:1072:5:1072:5 | b [element] : | | array_flow.rb:1073:10:1073:10 | b [element] : | array_flow.rb:1073:10:1073:13 | ...[...] | | array_flow.rb:1073:10:1073:10 | b [element] : | array_flow.rb:1073:10:1073:13 | ...[...] | | array_flow.rb:1074:10:1074:10 | b [element] : | array_flow.rb:1074:10:1074:13 | ...[...] | @@ -2011,12 +2512,30 @@ edges | array_flow.rb:1075:10:1075:10 | b [element] : | array_flow.rb:1075:10:1075:13 | ...[...] | | array_flow.rb:1076:10:1076:10 | b [element] : | array_flow.rb:1076:10:1076:13 | ...[...] | | array_flow.rb:1076:10:1076:10 | b [element] : | array_flow.rb:1076:10:1076:13 | ...[...] | -| array_flow.rb:1084:10:1084:22 | call to source : | array_flow.rb:1085:9:1085:9 | a [element 0] : | -| array_flow.rb:1084:10:1084:22 | call to source : | array_flow.rb:1085:9:1085:9 | a [element 0] : | -| array_flow.rb:1084:28:1084:40 | call to source : | array_flow.rb:1085:9:1085:9 | a [element 2] : | -| array_flow.rb:1084:28:1084:40 | call to source : | array_flow.rb:1085:9:1085:9 | a [element 2] : | -| array_flow.rb:1084:43:1084:55 | call to source : | array_flow.rb:1085:9:1085:9 | a [element 3] : | -| array_flow.rb:1084:43:1084:55 | call to source : | array_flow.rb:1085:9:1085:9 | a [element 3] : | +| array_flow.rb:1084:5:1084:5 | a [element 0] : | array_flow.rb:1085:9:1085:9 | a [element 0] : | +| array_flow.rb:1084:5:1084:5 | a [element 0] : | array_flow.rb:1085:9:1085:9 | a [element 0] : | +| array_flow.rb:1084:5:1084:5 | a [element 2] : | array_flow.rb:1085:9:1085:9 | a [element 2] : | +| array_flow.rb:1084:5:1084:5 | a [element 2] : | array_flow.rb:1085:9:1085:9 | a [element 2] : | +| array_flow.rb:1084:5:1084:5 | a [element 3] : | array_flow.rb:1085:9:1085:9 | a [element 3] : | +| array_flow.rb:1084:5:1084:5 | a [element 3] : | array_flow.rb:1085:9:1085:9 | a [element 3] : | +| array_flow.rb:1084:10:1084:22 | call to source : | array_flow.rb:1084:5:1084:5 | a [element 0] : | +| array_flow.rb:1084:10:1084:22 | call to source : | array_flow.rb:1084:5:1084:5 | a [element 0] : | +| array_flow.rb:1084:28:1084:40 | call to source : | array_flow.rb:1084:5:1084:5 | a [element 2] : | +| array_flow.rb:1084:28:1084:40 | call to source : | array_flow.rb:1084:5:1084:5 | a [element 2] : | +| array_flow.rb:1084:43:1084:55 | call to source : | array_flow.rb:1084:5:1084:5 | a [element 3] : | +| array_flow.rb:1084:43:1084:55 | call to source : | array_flow.rb:1084:5:1084:5 | a [element 3] : | +| array_flow.rb:1085:5:1085:5 | b [element 1] : | array_flow.rb:1091:10:1091:10 | b [element 1] : | +| array_flow.rb:1085:5:1085:5 | b [element 1] : | array_flow.rb:1091:10:1091:10 | b [element 1] : | +| array_flow.rb:1085:5:1085:5 | b [element 2] : | array_flow.rb:1092:10:1092:10 | b [element 2] : | +| array_flow.rb:1085:5:1085:5 | b [element 2] : | array_flow.rb:1092:10:1092:10 | b [element 2] : | +| array_flow.rb:1085:5:1085:5 | b [element] : | array_flow.rb:1090:10:1090:10 | b [element] : | +| array_flow.rb:1085:5:1085:5 | b [element] : | array_flow.rb:1090:10:1090:10 | b [element] : | +| array_flow.rb:1085:5:1085:5 | b [element] : | array_flow.rb:1091:10:1091:10 | b [element] : | +| array_flow.rb:1085:5:1085:5 | b [element] : | array_flow.rb:1091:10:1091:10 | b [element] : | +| array_flow.rb:1085:5:1085:5 | b [element] : | array_flow.rb:1092:10:1092:10 | b [element] : | +| array_flow.rb:1085:5:1085:5 | b [element] : | array_flow.rb:1092:10:1092:10 | b [element] : | +| array_flow.rb:1085:5:1085:5 | b [element] : | array_flow.rb:1093:10:1093:10 | b [element] : | +| array_flow.rb:1085:5:1085:5 | b [element] : | array_flow.rb:1093:10:1093:10 | b [element] : | | array_flow.rb:1085:9:1085:9 | [post] a [element 1] : | array_flow.rb:1087:10:1087:10 | a [element 1] : | | array_flow.rb:1085:9:1085:9 | [post] a [element 1] : | array_flow.rb:1087:10:1087:10 | a [element 1] : | | array_flow.rb:1085:9:1085:9 | [post] a [element 2] : | array_flow.rb:1088:10:1088:10 | a [element 2] : | @@ -2041,18 +2560,12 @@ edges | array_flow.rb:1085:9:1085:9 | a [element 3] : | array_flow.rb:1085:9:1085:9 | [post] a [element 2] : | | array_flow.rb:1085:9:1085:9 | a [element 3] : | array_flow.rb:1085:9:1085:17 | call to rotate! [element 2] : | | array_flow.rb:1085:9:1085:9 | a [element 3] : | array_flow.rb:1085:9:1085:17 | call to rotate! [element 2] : | -| array_flow.rb:1085:9:1085:17 | call to rotate! [element 1] : | array_flow.rb:1091:10:1091:10 | b [element 1] : | -| array_flow.rb:1085:9:1085:17 | call to rotate! [element 1] : | array_flow.rb:1091:10:1091:10 | b [element 1] : | -| array_flow.rb:1085:9:1085:17 | call to rotate! [element 2] : | array_flow.rb:1092:10:1092:10 | b [element 2] : | -| array_flow.rb:1085:9:1085:17 | call to rotate! [element 2] : | array_flow.rb:1092:10:1092:10 | b [element 2] : | -| array_flow.rb:1085:9:1085:17 | call to rotate! [element] : | array_flow.rb:1090:10:1090:10 | b [element] : | -| array_flow.rb:1085:9:1085:17 | call to rotate! [element] : | array_flow.rb:1090:10:1090:10 | b [element] : | -| array_flow.rb:1085:9:1085:17 | call to rotate! [element] : | array_flow.rb:1091:10:1091:10 | b [element] : | -| array_flow.rb:1085:9:1085:17 | call to rotate! [element] : | array_flow.rb:1091:10:1091:10 | b [element] : | -| array_flow.rb:1085:9:1085:17 | call to rotate! [element] : | array_flow.rb:1092:10:1092:10 | b [element] : | -| array_flow.rb:1085:9:1085:17 | call to rotate! [element] : | array_flow.rb:1092:10:1092:10 | b [element] : | -| array_flow.rb:1085:9:1085:17 | call to rotate! [element] : | array_flow.rb:1093:10:1093:10 | b [element] : | -| array_flow.rb:1085:9:1085:17 | call to rotate! [element] : | array_flow.rb:1093:10:1093:10 | b [element] : | +| array_flow.rb:1085:9:1085:17 | call to rotate! [element 1] : | array_flow.rb:1085:5:1085:5 | b [element 1] : | +| array_flow.rb:1085:9:1085:17 | call to rotate! [element 1] : | array_flow.rb:1085:5:1085:5 | b [element 1] : | +| array_flow.rb:1085:9:1085:17 | call to rotate! [element 2] : | array_flow.rb:1085:5:1085:5 | b [element 2] : | +| array_flow.rb:1085:9:1085:17 | call to rotate! [element 2] : | array_flow.rb:1085:5:1085:5 | b [element 2] : | +| array_flow.rb:1085:9:1085:17 | call to rotate! [element] : | array_flow.rb:1085:5:1085:5 | b [element] : | +| array_flow.rb:1085:9:1085:17 | call to rotate! [element] : | array_flow.rb:1085:5:1085:5 | b [element] : | | array_flow.rb:1086:10:1086:10 | a [element] : | array_flow.rb:1086:10:1086:13 | ...[...] | | array_flow.rb:1086:10:1086:10 | a [element] : | array_flow.rb:1086:10:1086:13 | ...[...] | | array_flow.rb:1087:10:1087:10 | a [element 1] : | array_flow.rb:1087:10:1087:13 | ...[...] | @@ -2077,12 +2590,30 @@ edges | array_flow.rb:1092:10:1092:10 | b [element] : | array_flow.rb:1092:10:1092:13 | ...[...] | | array_flow.rb:1093:10:1093:10 | b [element] : | array_flow.rb:1093:10:1093:13 | ...[...] | | array_flow.rb:1093:10:1093:10 | b [element] : | array_flow.rb:1093:10:1093:13 | ...[...] | -| array_flow.rb:1095:10:1095:22 | call to source : | array_flow.rb:1096:9:1096:9 | a [element 0] : | -| array_flow.rb:1095:10:1095:22 | call to source : | array_flow.rb:1096:9:1096:9 | a [element 0] : | -| array_flow.rb:1095:28:1095:40 | call to source : | array_flow.rb:1096:9:1096:9 | a [element 2] : | -| array_flow.rb:1095:28:1095:40 | call to source : | array_flow.rb:1096:9:1096:9 | a [element 2] : | -| array_flow.rb:1095:43:1095:55 | call to source : | array_flow.rb:1096:9:1096:9 | a [element 3] : | -| array_flow.rb:1095:43:1095:55 | call to source : | array_flow.rb:1096:9:1096:9 | a [element 3] : | +| array_flow.rb:1095:5:1095:5 | a [element 0] : | array_flow.rb:1096:9:1096:9 | a [element 0] : | +| array_flow.rb:1095:5:1095:5 | a [element 0] : | array_flow.rb:1096:9:1096:9 | a [element 0] : | +| array_flow.rb:1095:5:1095:5 | a [element 2] : | array_flow.rb:1096:9:1096:9 | a [element 2] : | +| array_flow.rb:1095:5:1095:5 | a [element 2] : | array_flow.rb:1096:9:1096:9 | a [element 2] : | +| array_flow.rb:1095:5:1095:5 | a [element 3] : | array_flow.rb:1096:9:1096:9 | a [element 3] : | +| array_flow.rb:1095:5:1095:5 | a [element 3] : | array_flow.rb:1096:9:1096:9 | a [element 3] : | +| array_flow.rb:1095:10:1095:22 | call to source : | array_flow.rb:1095:5:1095:5 | a [element 0] : | +| array_flow.rb:1095:10:1095:22 | call to source : | array_flow.rb:1095:5:1095:5 | a [element 0] : | +| array_flow.rb:1095:28:1095:40 | call to source : | array_flow.rb:1095:5:1095:5 | a [element 2] : | +| array_flow.rb:1095:28:1095:40 | call to source : | array_flow.rb:1095:5:1095:5 | a [element 2] : | +| array_flow.rb:1095:43:1095:55 | call to source : | array_flow.rb:1095:5:1095:5 | a [element 3] : | +| array_flow.rb:1095:43:1095:55 | call to source : | array_flow.rb:1095:5:1095:5 | a [element 3] : | +| array_flow.rb:1096:5:1096:5 | b [element 0] : | array_flow.rb:1101:10:1101:10 | b [element 0] : | +| array_flow.rb:1096:5:1096:5 | b [element 0] : | array_flow.rb:1101:10:1101:10 | b [element 0] : | +| array_flow.rb:1096:5:1096:5 | b [element 1] : | array_flow.rb:1102:10:1102:10 | b [element 1] : | +| array_flow.rb:1096:5:1096:5 | b [element 1] : | array_flow.rb:1102:10:1102:10 | b [element 1] : | +| array_flow.rb:1096:5:1096:5 | b [element] : | array_flow.rb:1101:10:1101:10 | b [element] : | +| array_flow.rb:1096:5:1096:5 | b [element] : | array_flow.rb:1101:10:1101:10 | b [element] : | +| array_flow.rb:1096:5:1096:5 | b [element] : | array_flow.rb:1102:10:1102:10 | b [element] : | +| array_flow.rb:1096:5:1096:5 | b [element] : | array_flow.rb:1102:10:1102:10 | b [element] : | +| array_flow.rb:1096:5:1096:5 | b [element] : | array_flow.rb:1103:10:1103:10 | b [element] : | +| array_flow.rb:1096:5:1096:5 | b [element] : | array_flow.rb:1103:10:1103:10 | b [element] : | +| array_flow.rb:1096:5:1096:5 | b [element] : | array_flow.rb:1104:10:1104:10 | b [element] : | +| array_flow.rb:1096:5:1096:5 | b [element] : | array_flow.rb:1104:10:1104:10 | b [element] : | | array_flow.rb:1096:9:1096:9 | [post] a [element 0] : | array_flow.rb:1097:10:1097:10 | a [element 0] : | | array_flow.rb:1096:9:1096:9 | [post] a [element 0] : | array_flow.rb:1097:10:1097:10 | a [element 0] : | | array_flow.rb:1096:9:1096:9 | [post] a [element 1] : | array_flow.rb:1098:10:1098:10 | a [element 1] : | @@ -2107,18 +2638,12 @@ edges | array_flow.rb:1096:9:1096:9 | a [element 3] : | array_flow.rb:1096:9:1096:9 | [post] a [element 1] : | | array_flow.rb:1096:9:1096:9 | a [element 3] : | array_flow.rb:1096:9:1096:20 | call to rotate! [element 1] : | | array_flow.rb:1096:9:1096:9 | a [element 3] : | array_flow.rb:1096:9:1096:20 | call to rotate! [element 1] : | -| array_flow.rb:1096:9:1096:20 | call to rotate! [element 0] : | array_flow.rb:1101:10:1101:10 | b [element 0] : | -| array_flow.rb:1096:9:1096:20 | call to rotate! [element 0] : | array_flow.rb:1101:10:1101:10 | b [element 0] : | -| array_flow.rb:1096:9:1096:20 | call to rotate! [element 1] : | array_flow.rb:1102:10:1102:10 | b [element 1] : | -| array_flow.rb:1096:9:1096:20 | call to rotate! [element 1] : | array_flow.rb:1102:10:1102:10 | b [element 1] : | -| array_flow.rb:1096:9:1096:20 | call to rotate! [element] : | array_flow.rb:1101:10:1101:10 | b [element] : | -| array_flow.rb:1096:9:1096:20 | call to rotate! [element] : | array_flow.rb:1101:10:1101:10 | b [element] : | -| array_flow.rb:1096:9:1096:20 | call to rotate! [element] : | array_flow.rb:1102:10:1102:10 | b [element] : | -| array_flow.rb:1096:9:1096:20 | call to rotate! [element] : | array_flow.rb:1102:10:1102:10 | b [element] : | -| array_flow.rb:1096:9:1096:20 | call to rotate! [element] : | array_flow.rb:1103:10:1103:10 | b [element] : | -| array_flow.rb:1096:9:1096:20 | call to rotate! [element] : | array_flow.rb:1103:10:1103:10 | b [element] : | -| array_flow.rb:1096:9:1096:20 | call to rotate! [element] : | array_flow.rb:1104:10:1104:10 | b [element] : | -| array_flow.rb:1096:9:1096:20 | call to rotate! [element] : | array_flow.rb:1104:10:1104:10 | b [element] : | +| array_flow.rb:1096:9:1096:20 | call to rotate! [element 0] : | array_flow.rb:1096:5:1096:5 | b [element 0] : | +| array_flow.rb:1096:9:1096:20 | call to rotate! [element 0] : | array_flow.rb:1096:5:1096:5 | b [element 0] : | +| array_flow.rb:1096:9:1096:20 | call to rotate! [element 1] : | array_flow.rb:1096:5:1096:5 | b [element 1] : | +| array_flow.rb:1096:9:1096:20 | call to rotate! [element 1] : | array_flow.rb:1096:5:1096:5 | b [element 1] : | +| array_flow.rb:1096:9:1096:20 | call to rotate! [element] : | array_flow.rb:1096:5:1096:5 | b [element] : | +| array_flow.rb:1096:9:1096:20 | call to rotate! [element] : | array_flow.rb:1096:5:1096:5 | b [element] : | | array_flow.rb:1097:10:1097:10 | a [element 0] : | array_flow.rb:1097:10:1097:13 | ...[...] | | array_flow.rb:1097:10:1097:10 | a [element 0] : | array_flow.rb:1097:10:1097:13 | ...[...] | | array_flow.rb:1097:10:1097:10 | a [element] : | array_flow.rb:1097:10:1097:13 | ...[...] | @@ -2143,12 +2668,24 @@ edges | array_flow.rb:1103:10:1103:10 | b [element] : | array_flow.rb:1103:10:1103:13 | ...[...] | | array_flow.rb:1104:10:1104:10 | b [element] : | array_flow.rb:1104:10:1104:13 | ...[...] | | array_flow.rb:1104:10:1104:10 | b [element] : | array_flow.rb:1104:10:1104:13 | ...[...] | -| array_flow.rb:1106:10:1106:22 | call to source : | array_flow.rb:1107:9:1107:9 | a [element 0] : | -| array_flow.rb:1106:10:1106:22 | call to source : | array_flow.rb:1107:9:1107:9 | a [element 0] : | -| array_flow.rb:1106:28:1106:40 | call to source : | array_flow.rb:1107:9:1107:9 | a [element 2] : | -| array_flow.rb:1106:28:1106:40 | call to source : | array_flow.rb:1107:9:1107:9 | a [element 2] : | -| array_flow.rb:1106:43:1106:55 | call to source : | array_flow.rb:1107:9:1107:9 | a [element 3] : | -| array_flow.rb:1106:43:1106:55 | call to source : | array_flow.rb:1107:9:1107:9 | a [element 3] : | +| array_flow.rb:1106:5:1106:5 | a [element 0] : | array_flow.rb:1107:9:1107:9 | a [element 0] : | +| array_flow.rb:1106:5:1106:5 | a [element 0] : | array_flow.rb:1107:9:1107:9 | a [element 0] : | +| array_flow.rb:1106:5:1106:5 | a [element 2] : | array_flow.rb:1107:9:1107:9 | a [element 2] : | +| array_flow.rb:1106:5:1106:5 | a [element 2] : | array_flow.rb:1107:9:1107:9 | a [element 2] : | +| array_flow.rb:1106:5:1106:5 | a [element 3] : | array_flow.rb:1107:9:1107:9 | a [element 3] : | +| array_flow.rb:1106:5:1106:5 | a [element 3] : | array_flow.rb:1107:9:1107:9 | a [element 3] : | +| array_flow.rb:1106:10:1106:22 | call to source : | array_flow.rb:1106:5:1106:5 | a [element 0] : | +| array_flow.rb:1106:10:1106:22 | call to source : | array_flow.rb:1106:5:1106:5 | a [element 0] : | +| array_flow.rb:1106:28:1106:40 | call to source : | array_flow.rb:1106:5:1106:5 | a [element 2] : | +| array_flow.rb:1106:28:1106:40 | call to source : | array_flow.rb:1106:5:1106:5 | a [element 2] : | +| array_flow.rb:1106:43:1106:55 | call to source : | array_flow.rb:1106:5:1106:5 | a [element 3] : | +| array_flow.rb:1106:43:1106:55 | call to source : | array_flow.rb:1106:5:1106:5 | a [element 3] : | +| array_flow.rb:1107:5:1107:5 | b [element 0] : | array_flow.rb:1112:10:1112:10 | b [element 0] : | +| array_flow.rb:1107:5:1107:5 | b [element 0] : | array_flow.rb:1112:10:1112:10 | b [element 0] : | +| array_flow.rb:1107:5:1107:5 | b [element 2] : | array_flow.rb:1114:10:1114:10 | b [element 2] : | +| array_flow.rb:1107:5:1107:5 | b [element 2] : | array_flow.rb:1114:10:1114:10 | b [element 2] : | +| array_flow.rb:1107:5:1107:5 | b [element 3] : | array_flow.rb:1115:10:1115:10 | b [element 3] : | +| array_flow.rb:1107:5:1107:5 | b [element 3] : | array_flow.rb:1115:10:1115:10 | b [element 3] : | | array_flow.rb:1107:9:1107:9 | [post] a [element 0] : | array_flow.rb:1108:10:1108:10 | a [element 0] : | | array_flow.rb:1107:9:1107:9 | [post] a [element 0] : | array_flow.rb:1108:10:1108:10 | a [element 0] : | | array_flow.rb:1107:9:1107:9 | [post] a [element 2] : | array_flow.rb:1110:10:1110:10 | a [element 2] : | @@ -2167,12 +2704,12 @@ edges | array_flow.rb:1107:9:1107:9 | a [element 3] : | array_flow.rb:1107:9:1107:9 | [post] a [element 3] : | | array_flow.rb:1107:9:1107:9 | a [element 3] : | array_flow.rb:1107:9:1107:20 | call to rotate! [element 3] : | | array_flow.rb:1107:9:1107:9 | a [element 3] : | array_flow.rb:1107:9:1107:20 | call to rotate! [element 3] : | -| array_flow.rb:1107:9:1107:20 | call to rotate! [element 0] : | array_flow.rb:1112:10:1112:10 | b [element 0] : | -| array_flow.rb:1107:9:1107:20 | call to rotate! [element 0] : | array_flow.rb:1112:10:1112:10 | b [element 0] : | -| array_flow.rb:1107:9:1107:20 | call to rotate! [element 2] : | array_flow.rb:1114:10:1114:10 | b [element 2] : | -| array_flow.rb:1107:9:1107:20 | call to rotate! [element 2] : | array_flow.rb:1114:10:1114:10 | b [element 2] : | -| array_flow.rb:1107:9:1107:20 | call to rotate! [element 3] : | array_flow.rb:1115:10:1115:10 | b [element 3] : | -| array_flow.rb:1107:9:1107:20 | call to rotate! [element 3] : | array_flow.rb:1115:10:1115:10 | b [element 3] : | +| array_flow.rb:1107:9:1107:20 | call to rotate! [element 0] : | array_flow.rb:1107:5:1107:5 | b [element 0] : | +| array_flow.rb:1107:9:1107:20 | call to rotate! [element 0] : | array_flow.rb:1107:5:1107:5 | b [element 0] : | +| array_flow.rb:1107:9:1107:20 | call to rotate! [element 2] : | array_flow.rb:1107:5:1107:5 | b [element 2] : | +| array_flow.rb:1107:9:1107:20 | call to rotate! [element 2] : | array_flow.rb:1107:5:1107:5 | b [element 2] : | +| array_flow.rb:1107:9:1107:20 | call to rotate! [element 3] : | array_flow.rb:1107:5:1107:5 | b [element 3] : | +| array_flow.rb:1107:9:1107:20 | call to rotate! [element 3] : | array_flow.rb:1107:5:1107:5 | b [element 3] : | | array_flow.rb:1108:10:1108:10 | a [element 0] : | array_flow.rb:1108:10:1108:13 | ...[...] | | array_flow.rb:1108:10:1108:10 | a [element 0] : | array_flow.rb:1108:10:1108:13 | ...[...] | | array_flow.rb:1110:10:1110:10 | a [element 2] : | array_flow.rb:1110:10:1110:13 | ...[...] | @@ -2185,12 +2722,26 @@ edges | array_flow.rb:1114:10:1114:10 | b [element 2] : | array_flow.rb:1114:10:1114:13 | ...[...] | | array_flow.rb:1115:10:1115:10 | b [element 3] : | array_flow.rb:1115:10:1115:13 | ...[...] | | array_flow.rb:1115:10:1115:10 | b [element 3] : | array_flow.rb:1115:10:1115:13 | ...[...] | -| array_flow.rb:1117:10:1117:22 | call to source : | array_flow.rb:1118:9:1118:9 | a [element 0] : | -| array_flow.rb:1117:10:1117:22 | call to source : | array_flow.rb:1118:9:1118:9 | a [element 0] : | -| array_flow.rb:1117:28:1117:40 | call to source : | array_flow.rb:1118:9:1118:9 | a [element 2] : | -| array_flow.rb:1117:28:1117:40 | call to source : | array_flow.rb:1118:9:1118:9 | a [element 2] : | -| array_flow.rb:1117:43:1117:55 | call to source : | array_flow.rb:1118:9:1118:9 | a [element 3] : | -| array_flow.rb:1117:43:1117:55 | call to source : | array_flow.rb:1118:9:1118:9 | a [element 3] : | +| array_flow.rb:1117:5:1117:5 | a [element 0] : | array_flow.rb:1118:9:1118:9 | a [element 0] : | +| array_flow.rb:1117:5:1117:5 | a [element 0] : | array_flow.rb:1118:9:1118:9 | a [element 0] : | +| array_flow.rb:1117:5:1117:5 | a [element 2] : | array_flow.rb:1118:9:1118:9 | a [element 2] : | +| array_flow.rb:1117:5:1117:5 | a [element 2] : | array_flow.rb:1118:9:1118:9 | a [element 2] : | +| array_flow.rb:1117:5:1117:5 | a [element 3] : | array_flow.rb:1118:9:1118:9 | a [element 3] : | +| array_flow.rb:1117:5:1117:5 | a [element 3] : | array_flow.rb:1118:9:1118:9 | a [element 3] : | +| array_flow.rb:1117:10:1117:22 | call to source : | array_flow.rb:1117:5:1117:5 | a [element 0] : | +| array_flow.rb:1117:10:1117:22 | call to source : | array_flow.rb:1117:5:1117:5 | a [element 0] : | +| array_flow.rb:1117:28:1117:40 | call to source : | array_flow.rb:1117:5:1117:5 | a [element 2] : | +| array_flow.rb:1117:28:1117:40 | call to source : | array_flow.rb:1117:5:1117:5 | a [element 2] : | +| array_flow.rb:1117:43:1117:55 | call to source : | array_flow.rb:1117:5:1117:5 | a [element 3] : | +| array_flow.rb:1117:43:1117:55 | call to source : | array_flow.rb:1117:5:1117:5 | a [element 3] : | +| array_flow.rb:1118:5:1118:5 | b [element] : | array_flow.rb:1123:10:1123:10 | b [element] : | +| array_flow.rb:1118:5:1118:5 | b [element] : | array_flow.rb:1123:10:1123:10 | b [element] : | +| array_flow.rb:1118:5:1118:5 | b [element] : | array_flow.rb:1124:10:1124:10 | b [element] : | +| array_flow.rb:1118:5:1118:5 | b [element] : | array_flow.rb:1124:10:1124:10 | b [element] : | +| array_flow.rb:1118:5:1118:5 | b [element] : | array_flow.rb:1125:10:1125:10 | b [element] : | +| array_flow.rb:1118:5:1118:5 | b [element] : | array_flow.rb:1125:10:1125:10 | b [element] : | +| array_flow.rb:1118:5:1118:5 | b [element] : | array_flow.rb:1126:10:1126:10 | b [element] : | +| array_flow.rb:1118:5:1118:5 | b [element] : | array_flow.rb:1126:10:1126:10 | b [element] : | | array_flow.rb:1118:9:1118:9 | [post] a [element] : | array_flow.rb:1119:10:1119:10 | a [element] : | | array_flow.rb:1118:9:1118:9 | [post] a [element] : | array_flow.rb:1119:10:1119:10 | a [element] : | | array_flow.rb:1118:9:1118:9 | [post] a [element] : | array_flow.rb:1120:10:1120:10 | a [element] : | @@ -2211,14 +2762,8 @@ edges | array_flow.rb:1118:9:1118:9 | a [element 3] : | array_flow.rb:1118:9:1118:9 | [post] a [element] : | | array_flow.rb:1118:9:1118:9 | a [element 3] : | array_flow.rb:1118:9:1118:20 | call to rotate! [element] : | | array_flow.rb:1118:9:1118:9 | a [element 3] : | array_flow.rb:1118:9:1118:20 | call to rotate! [element] : | -| array_flow.rb:1118:9:1118:20 | call to rotate! [element] : | array_flow.rb:1123:10:1123:10 | b [element] : | -| array_flow.rb:1118:9:1118:20 | call to rotate! [element] : | array_flow.rb:1123:10:1123:10 | b [element] : | -| array_flow.rb:1118:9:1118:20 | call to rotate! [element] : | array_flow.rb:1124:10:1124:10 | b [element] : | -| array_flow.rb:1118:9:1118:20 | call to rotate! [element] : | array_flow.rb:1124:10:1124:10 | b [element] : | -| array_flow.rb:1118:9:1118:20 | call to rotate! [element] : | array_flow.rb:1125:10:1125:10 | b [element] : | -| array_flow.rb:1118:9:1118:20 | call to rotate! [element] : | array_flow.rb:1125:10:1125:10 | b [element] : | -| array_flow.rb:1118:9:1118:20 | call to rotate! [element] : | array_flow.rb:1126:10:1126:10 | b [element] : | -| array_flow.rb:1118:9:1118:20 | call to rotate! [element] : | array_flow.rb:1126:10:1126:10 | b [element] : | +| array_flow.rb:1118:9:1118:20 | call to rotate! [element] : | array_flow.rb:1118:5:1118:5 | b [element] : | +| array_flow.rb:1118:9:1118:20 | call to rotate! [element] : | array_flow.rb:1118:5:1118:5 | b [element] : | | array_flow.rb:1119:10:1119:10 | a [element] : | array_flow.rb:1119:10:1119:13 | ...[...] | | array_flow.rb:1119:10:1119:10 | a [element] : | array_flow.rb:1119:10:1119:13 | ...[...] | | array_flow.rb:1120:10:1120:10 | a [element] : | array_flow.rb:1120:10:1120:13 | ...[...] | @@ -2235,20 +2780,28 @@ edges | array_flow.rb:1125:10:1125:10 | b [element] : | array_flow.rb:1125:10:1125:13 | ...[...] | | array_flow.rb:1126:10:1126:10 | b [element] : | array_flow.rb:1126:10:1126:13 | ...[...] | | array_flow.rb:1126:10:1126:10 | b [element] : | array_flow.rb:1126:10:1126:13 | ...[...] | -| array_flow.rb:1130:19:1130:29 | call to source : | array_flow.rb:1131:9:1131:9 | a [element 3] : | -| array_flow.rb:1130:19:1130:29 | call to source : | array_flow.rb:1131:9:1131:9 | a [element 3] : | +| array_flow.rb:1130:5:1130:5 | a [element 3] : | array_flow.rb:1131:9:1131:9 | a [element 3] : | +| array_flow.rb:1130:5:1130:5 | a [element 3] : | array_flow.rb:1131:9:1131:9 | a [element 3] : | +| array_flow.rb:1130:19:1130:29 | call to source : | array_flow.rb:1130:5:1130:5 | a [element 3] : | +| array_flow.rb:1130:19:1130:29 | call to source : | array_flow.rb:1130:5:1130:5 | a [element 3] : | +| array_flow.rb:1131:5:1131:5 | b [element] : | array_flow.rb:1134:10:1134:10 | b [element] : | +| array_flow.rb:1131:5:1131:5 | b [element] : | array_flow.rb:1134:10:1134:10 | b [element] : | | array_flow.rb:1131:9:1131:9 | a [element 3] : | array_flow.rb:1131:9:1133:7 | call to select [element] : | | array_flow.rb:1131:9:1131:9 | a [element 3] : | array_flow.rb:1131:9:1133:7 | call to select [element] : | | array_flow.rb:1131:9:1131:9 | a [element 3] : | array_flow.rb:1131:22:1131:22 | x : | | array_flow.rb:1131:9:1131:9 | a [element 3] : | array_flow.rb:1131:22:1131:22 | x : | -| array_flow.rb:1131:9:1133:7 | call to select [element] : | array_flow.rb:1134:10:1134:10 | b [element] : | -| array_flow.rb:1131:9:1133:7 | call to select [element] : | array_flow.rb:1134:10:1134:10 | b [element] : | +| array_flow.rb:1131:9:1133:7 | call to select [element] : | array_flow.rb:1131:5:1131:5 | b [element] : | +| array_flow.rb:1131:9:1133:7 | call to select [element] : | array_flow.rb:1131:5:1131:5 | b [element] : | | array_flow.rb:1131:22:1131:22 | x : | array_flow.rb:1132:14:1132:14 | x | | array_flow.rb:1131:22:1131:22 | x : | array_flow.rb:1132:14:1132:14 | x | | array_flow.rb:1134:10:1134:10 | b [element] : | array_flow.rb:1134:10:1134:13 | ...[...] | | array_flow.rb:1134:10:1134:10 | b [element] : | array_flow.rb:1134:10:1134:13 | ...[...] | -| array_flow.rb:1138:16:1138:26 | call to source : | array_flow.rb:1139:9:1139:9 | a [element 2] : | -| array_flow.rb:1138:16:1138:26 | call to source : | array_flow.rb:1139:9:1139:9 | a [element 2] : | +| array_flow.rb:1138:5:1138:5 | a [element 2] : | array_flow.rb:1139:9:1139:9 | a [element 2] : | +| array_flow.rb:1138:5:1138:5 | a [element 2] : | array_flow.rb:1139:9:1139:9 | a [element 2] : | +| array_flow.rb:1138:16:1138:26 | call to source : | array_flow.rb:1138:5:1138:5 | a [element 2] : | +| array_flow.rb:1138:16:1138:26 | call to source : | array_flow.rb:1138:5:1138:5 | a [element 2] : | +| array_flow.rb:1139:5:1139:5 | b [element] : | array_flow.rb:1144:10:1144:10 | b [element] : | +| array_flow.rb:1139:5:1139:5 | b [element] : | array_flow.rb:1144:10:1144:10 | b [element] : | | array_flow.rb:1139:9:1139:9 | [post] a [element] : | array_flow.rb:1143:10:1143:10 | a [element] : | | array_flow.rb:1139:9:1139:9 | [post] a [element] : | array_flow.rb:1143:10:1143:10 | a [element] : | | array_flow.rb:1139:9:1139:9 | a [element 2] : | array_flow.rb:1139:9:1139:9 | [post] a [element] : | @@ -2257,52 +2810,72 @@ edges | array_flow.rb:1139:9:1139:9 | a [element 2] : | array_flow.rb:1139:9:1142:7 | call to select! [element] : | | array_flow.rb:1139:9:1139:9 | a [element 2] : | array_flow.rb:1139:23:1139:23 | x : | | array_flow.rb:1139:9:1139:9 | a [element 2] : | array_flow.rb:1139:23:1139:23 | x : | -| array_flow.rb:1139:9:1142:7 | call to select! [element] : | array_flow.rb:1144:10:1144:10 | b [element] : | -| array_flow.rb:1139:9:1142:7 | call to select! [element] : | array_flow.rb:1144:10:1144:10 | b [element] : | +| array_flow.rb:1139:9:1142:7 | call to select! [element] : | array_flow.rb:1139:5:1139:5 | b [element] : | +| array_flow.rb:1139:9:1142:7 | call to select! [element] : | array_flow.rb:1139:5:1139:5 | b [element] : | | array_flow.rb:1139:23:1139:23 | x : | array_flow.rb:1140:14:1140:14 | x | | array_flow.rb:1139:23:1139:23 | x : | array_flow.rb:1140:14:1140:14 | x | | array_flow.rb:1143:10:1143:10 | a [element] : | array_flow.rb:1143:10:1143:13 | ...[...] | | array_flow.rb:1143:10:1143:10 | a [element] : | array_flow.rb:1143:10:1143:13 | ...[...] | | array_flow.rb:1144:10:1144:10 | b [element] : | array_flow.rb:1144:10:1144:13 | ...[...] | | array_flow.rb:1144:10:1144:10 | b [element] : | array_flow.rb:1144:10:1144:13 | ...[...] | -| array_flow.rb:1148:10:1148:22 | call to source : | array_flow.rb:1149:9:1149:9 | a [element 0] : | -| array_flow.rb:1148:10:1148:22 | call to source : | array_flow.rb:1149:9:1149:9 | a [element 0] : | -| array_flow.rb:1148:28:1148:40 | call to source : | array_flow.rb:1149:9:1149:9 | a [element 2] : | -| array_flow.rb:1148:28:1148:40 | call to source : | array_flow.rb:1149:9:1149:9 | a [element 2] : | +| array_flow.rb:1148:5:1148:5 | a [element 0] : | array_flow.rb:1149:9:1149:9 | a [element 0] : | +| array_flow.rb:1148:5:1148:5 | a [element 0] : | array_flow.rb:1149:9:1149:9 | a [element 0] : | +| array_flow.rb:1148:5:1148:5 | a [element 2] : | array_flow.rb:1149:9:1149:9 | a [element 2] : | +| array_flow.rb:1148:5:1148:5 | a [element 2] : | array_flow.rb:1149:9:1149:9 | a [element 2] : | +| array_flow.rb:1148:10:1148:22 | call to source : | array_flow.rb:1148:5:1148:5 | a [element 0] : | +| array_flow.rb:1148:10:1148:22 | call to source : | array_flow.rb:1148:5:1148:5 | a [element 0] : | +| array_flow.rb:1148:28:1148:40 | call to source : | array_flow.rb:1148:5:1148:5 | a [element 2] : | +| array_flow.rb:1148:28:1148:40 | call to source : | array_flow.rb:1148:5:1148:5 | a [element 2] : | +| array_flow.rb:1149:5:1149:5 | b : | array_flow.rb:1150:10:1150:10 | b | +| array_flow.rb:1149:5:1149:5 | b : | array_flow.rb:1150:10:1150:10 | b | | array_flow.rb:1149:9:1149:9 | [post] a [element 1] : | array_flow.rb:1152:10:1152:10 | a [element 1] : | | array_flow.rb:1149:9:1149:9 | [post] a [element 1] : | array_flow.rb:1152:10:1152:10 | a [element 1] : | | array_flow.rb:1149:9:1149:9 | a [element 0] : | array_flow.rb:1149:9:1149:15 | call to shift : | | array_flow.rb:1149:9:1149:9 | a [element 0] : | array_flow.rb:1149:9:1149:15 | call to shift : | | array_flow.rb:1149:9:1149:9 | a [element 2] : | array_flow.rb:1149:9:1149:9 | [post] a [element 1] : | | array_flow.rb:1149:9:1149:9 | a [element 2] : | array_flow.rb:1149:9:1149:9 | [post] a [element 1] : | -| array_flow.rb:1149:9:1149:15 | call to shift : | array_flow.rb:1150:10:1150:10 | b | -| array_flow.rb:1149:9:1149:15 | call to shift : | array_flow.rb:1150:10:1150:10 | b | +| array_flow.rb:1149:9:1149:15 | call to shift : | array_flow.rb:1149:5:1149:5 | b : | +| array_flow.rb:1149:9:1149:15 | call to shift : | array_flow.rb:1149:5:1149:5 | b : | | array_flow.rb:1152:10:1152:10 | a [element 1] : | array_flow.rb:1152:10:1152:13 | ...[...] | | array_flow.rb:1152:10:1152:10 | a [element 1] : | array_flow.rb:1152:10:1152:13 | ...[...] | -| array_flow.rb:1155:10:1155:22 | call to source : | array_flow.rb:1156:9:1156:9 | a [element 0] : | -| array_flow.rb:1155:10:1155:22 | call to source : | array_flow.rb:1156:9:1156:9 | a [element 0] : | -| array_flow.rb:1155:28:1155:40 | call to source : | array_flow.rb:1156:9:1156:9 | a [element 2] : | -| array_flow.rb:1155:28:1155:40 | call to source : | array_flow.rb:1156:9:1156:9 | a [element 2] : | +| array_flow.rb:1155:5:1155:5 | a [element 0] : | array_flow.rb:1156:9:1156:9 | a [element 0] : | +| array_flow.rb:1155:5:1155:5 | a [element 0] : | array_flow.rb:1156:9:1156:9 | a [element 0] : | +| array_flow.rb:1155:5:1155:5 | a [element 2] : | array_flow.rb:1156:9:1156:9 | a [element 2] : | +| array_flow.rb:1155:5:1155:5 | a [element 2] : | array_flow.rb:1156:9:1156:9 | a [element 2] : | +| array_flow.rb:1155:10:1155:22 | call to source : | array_flow.rb:1155:5:1155:5 | a [element 0] : | +| array_flow.rb:1155:10:1155:22 | call to source : | array_flow.rb:1155:5:1155:5 | a [element 0] : | +| array_flow.rb:1155:28:1155:40 | call to source : | array_flow.rb:1155:5:1155:5 | a [element 2] : | +| array_flow.rb:1155:28:1155:40 | call to source : | array_flow.rb:1155:5:1155:5 | a [element 2] : | +| array_flow.rb:1156:5:1156:5 | b [element 0] : | array_flow.rb:1157:10:1157:10 | b [element 0] : | +| array_flow.rb:1156:5:1156:5 | b [element 0] : | array_flow.rb:1157:10:1157:10 | b [element 0] : | | array_flow.rb:1156:9:1156:9 | [post] a [element 0] : | array_flow.rb:1159:10:1159:10 | a [element 0] : | | array_flow.rb:1156:9:1156:9 | [post] a [element 0] : | array_flow.rb:1159:10:1159:10 | a [element 0] : | | array_flow.rb:1156:9:1156:9 | a [element 0] : | array_flow.rb:1156:9:1156:18 | call to shift [element 0] : | | array_flow.rb:1156:9:1156:9 | a [element 0] : | array_flow.rb:1156:9:1156:18 | call to shift [element 0] : | | array_flow.rb:1156:9:1156:9 | a [element 2] : | array_flow.rb:1156:9:1156:9 | [post] a [element 0] : | | array_flow.rb:1156:9:1156:9 | a [element 2] : | array_flow.rb:1156:9:1156:9 | [post] a [element 0] : | -| array_flow.rb:1156:9:1156:18 | call to shift [element 0] : | array_flow.rb:1157:10:1157:10 | b [element 0] : | -| array_flow.rb:1156:9:1156:18 | call to shift [element 0] : | array_flow.rb:1157:10:1157:10 | b [element 0] : | +| array_flow.rb:1156:9:1156:18 | call to shift [element 0] : | array_flow.rb:1156:5:1156:5 | b [element 0] : | +| array_flow.rb:1156:9:1156:18 | call to shift [element 0] : | array_flow.rb:1156:5:1156:5 | b [element 0] : | | array_flow.rb:1157:10:1157:10 | b [element 0] : | array_flow.rb:1157:10:1157:13 | ...[...] | | array_flow.rb:1157:10:1157:10 | b [element 0] : | array_flow.rb:1157:10:1157:13 | ...[...] | | array_flow.rb:1159:10:1159:10 | a [element 0] : | array_flow.rb:1159:10:1159:13 | ...[...] | | array_flow.rb:1159:10:1159:10 | a [element 0] : | array_flow.rb:1159:10:1159:13 | ...[...] | -| array_flow.rb:1163:10:1163:22 | call to source : | array_flow.rb:1164:9:1164:9 | a [element 0] : | -| array_flow.rb:1163:10:1163:22 | call to source : | array_flow.rb:1164:9:1164:9 | a [element 0] : | -| array_flow.rb:1163:10:1163:22 | call to source : | array_flow.rb:1167:10:1167:10 | a [element 0] : | -| array_flow.rb:1163:10:1163:22 | call to source : | array_flow.rb:1167:10:1167:10 | a [element 0] : | -| array_flow.rb:1163:28:1163:40 | call to source : | array_flow.rb:1164:9:1164:9 | a [element 2] : | -| array_flow.rb:1163:28:1163:40 | call to source : | array_flow.rb:1164:9:1164:9 | a [element 2] : | -| array_flow.rb:1163:28:1163:40 | call to source : | array_flow.rb:1169:10:1169:10 | a [element 2] : | -| array_flow.rb:1163:28:1163:40 | call to source : | array_flow.rb:1169:10:1169:10 | a [element 2] : | +| array_flow.rb:1163:5:1163:5 | a [element 0] : | array_flow.rb:1164:9:1164:9 | a [element 0] : | +| array_flow.rb:1163:5:1163:5 | a [element 0] : | array_flow.rb:1164:9:1164:9 | a [element 0] : | +| array_flow.rb:1163:5:1163:5 | a [element 0] : | array_flow.rb:1167:10:1167:10 | a [element 0] : | +| array_flow.rb:1163:5:1163:5 | a [element 0] : | array_flow.rb:1167:10:1167:10 | a [element 0] : | +| array_flow.rb:1163:5:1163:5 | a [element 2] : | array_flow.rb:1164:9:1164:9 | a [element 2] : | +| array_flow.rb:1163:5:1163:5 | a [element 2] : | array_flow.rb:1164:9:1164:9 | a [element 2] : | +| array_flow.rb:1163:5:1163:5 | a [element 2] : | array_flow.rb:1169:10:1169:10 | a [element 2] : | +| array_flow.rb:1163:5:1163:5 | a [element 2] : | array_flow.rb:1169:10:1169:10 | a [element 2] : | +| array_flow.rb:1163:10:1163:22 | call to source : | array_flow.rb:1163:5:1163:5 | a [element 0] : | +| array_flow.rb:1163:10:1163:22 | call to source : | array_flow.rb:1163:5:1163:5 | a [element 0] : | +| array_flow.rb:1163:28:1163:40 | call to source : | array_flow.rb:1163:5:1163:5 | a [element 2] : | +| array_flow.rb:1163:28:1163:40 | call to source : | array_flow.rb:1163:5:1163:5 | a [element 2] : | +| array_flow.rb:1164:5:1164:5 | b [element] : | array_flow.rb:1165:10:1165:10 | b [element] : | +| array_flow.rb:1164:5:1164:5 | b [element] : | array_flow.rb:1165:10:1165:10 | b [element] : | +| array_flow.rb:1164:5:1164:5 | b [element] : | array_flow.rb:1166:10:1166:10 | b [element] : | +| array_flow.rb:1164:5:1164:5 | b [element] : | array_flow.rb:1166:10:1166:10 | b [element] : | | array_flow.rb:1164:9:1164:9 | [post] a [element] : | array_flow.rb:1167:10:1167:10 | a [element] : | | array_flow.rb:1164:9:1164:9 | [post] a [element] : | array_flow.rb:1167:10:1167:10 | a [element] : | | array_flow.rb:1164:9:1164:9 | [post] a [element] : | array_flow.rb:1168:10:1168:10 | a [element] : | @@ -2317,10 +2890,8 @@ edges | array_flow.rb:1164:9:1164:9 | a [element 2] : | array_flow.rb:1164:9:1164:9 | [post] a [element] : | | array_flow.rb:1164:9:1164:9 | a [element 2] : | array_flow.rb:1164:9:1164:18 | call to shift [element] : | | array_flow.rb:1164:9:1164:9 | a [element 2] : | array_flow.rb:1164:9:1164:18 | call to shift [element] : | -| array_flow.rb:1164:9:1164:18 | call to shift [element] : | array_flow.rb:1165:10:1165:10 | b [element] : | -| array_flow.rb:1164:9:1164:18 | call to shift [element] : | array_flow.rb:1165:10:1165:10 | b [element] : | -| array_flow.rb:1164:9:1164:18 | call to shift [element] : | array_flow.rb:1166:10:1166:10 | b [element] : | -| array_flow.rb:1164:9:1164:18 | call to shift [element] : | array_flow.rb:1166:10:1166:10 | b [element] : | +| array_flow.rb:1164:9:1164:18 | call to shift [element] : | array_flow.rb:1164:5:1164:5 | b [element] : | +| array_flow.rb:1164:9:1164:18 | call to shift [element] : | array_flow.rb:1164:5:1164:5 | b [element] : | | array_flow.rb:1165:10:1165:10 | b [element] : | array_flow.rb:1165:10:1165:13 | ...[...] | | array_flow.rb:1165:10:1165:10 | b [element] : | array_flow.rb:1165:10:1165:13 | ...[...] | | array_flow.rb:1166:10:1166:10 | b [element] : | array_flow.rb:1166:10:1166:13 | ...[...] | @@ -2335,18 +2906,22 @@ edges | array_flow.rb:1169:10:1169:10 | a [element 2] : | array_flow.rb:1169:10:1169:13 | ...[...] | | array_flow.rb:1169:10:1169:10 | a [element] : | array_flow.rb:1169:10:1169:13 | ...[...] | | array_flow.rb:1169:10:1169:10 | a [element] : | array_flow.rb:1169:10:1169:13 | ...[...] | -| array_flow.rb:1173:16:1173:26 | call to source : | array_flow.rb:1174:9:1174:9 | a [element 2] : | -| array_flow.rb:1173:16:1173:26 | call to source : | array_flow.rb:1174:9:1174:9 | a [element 2] : | -| array_flow.rb:1173:16:1173:26 | call to source : | array_flow.rb:1177:10:1177:10 | a [element 2] : | -| array_flow.rb:1173:16:1173:26 | call to source : | array_flow.rb:1177:10:1177:10 | a [element 2] : | +| array_flow.rb:1173:5:1173:5 | a [element 2] : | array_flow.rb:1174:9:1174:9 | a [element 2] : | +| array_flow.rb:1173:5:1173:5 | a [element 2] : | array_flow.rb:1174:9:1174:9 | a [element 2] : | +| array_flow.rb:1173:5:1173:5 | a [element 2] : | array_flow.rb:1177:10:1177:10 | a [element 2] : | +| array_flow.rb:1173:5:1173:5 | a [element 2] : | array_flow.rb:1177:10:1177:10 | a [element 2] : | +| array_flow.rb:1173:16:1173:26 | call to source : | array_flow.rb:1173:5:1173:5 | a [element 2] : | +| array_flow.rb:1173:16:1173:26 | call to source : | array_flow.rb:1173:5:1173:5 | a [element 2] : | +| array_flow.rb:1174:5:1174:5 | b [element] : | array_flow.rb:1178:10:1178:10 | b [element] : | +| array_flow.rb:1174:5:1174:5 | b [element] : | array_flow.rb:1178:10:1178:10 | b [element] : | +| array_flow.rb:1174:5:1174:5 | b [element] : | array_flow.rb:1179:10:1179:10 | b [element] : | +| array_flow.rb:1174:5:1174:5 | b [element] : | array_flow.rb:1179:10:1179:10 | b [element] : | +| array_flow.rb:1174:5:1174:5 | b [element] : | array_flow.rb:1180:10:1180:10 | b [element] : | +| array_flow.rb:1174:5:1174:5 | b [element] : | array_flow.rb:1180:10:1180:10 | b [element] : | | array_flow.rb:1174:9:1174:9 | a [element 2] : | array_flow.rb:1174:9:1174:17 | call to shuffle [element] : | | array_flow.rb:1174:9:1174:9 | a [element 2] : | array_flow.rb:1174:9:1174:17 | call to shuffle [element] : | -| array_flow.rb:1174:9:1174:17 | call to shuffle [element] : | array_flow.rb:1178:10:1178:10 | b [element] : | -| array_flow.rb:1174:9:1174:17 | call to shuffle [element] : | array_flow.rb:1178:10:1178:10 | b [element] : | -| array_flow.rb:1174:9:1174:17 | call to shuffle [element] : | array_flow.rb:1179:10:1179:10 | b [element] : | -| array_flow.rb:1174:9:1174:17 | call to shuffle [element] : | array_flow.rb:1179:10:1179:10 | b [element] : | -| array_flow.rb:1174:9:1174:17 | call to shuffle [element] : | array_flow.rb:1180:10:1180:10 | b [element] : | -| array_flow.rb:1174:9:1174:17 | call to shuffle [element] : | array_flow.rb:1180:10:1180:10 | b [element] : | +| array_flow.rb:1174:9:1174:17 | call to shuffle [element] : | array_flow.rb:1174:5:1174:5 | b [element] : | +| array_flow.rb:1174:9:1174:17 | call to shuffle [element] : | array_flow.rb:1174:5:1174:5 | b [element] : | | array_flow.rb:1177:10:1177:10 | a [element 2] : | array_flow.rb:1177:10:1177:13 | ...[...] | | array_flow.rb:1177:10:1177:10 | a [element 2] : | array_flow.rb:1177:10:1177:13 | ...[...] | | array_flow.rb:1178:10:1178:10 | b [element] : | array_flow.rb:1178:10:1178:13 | ...[...] | @@ -2355,10 +2930,18 @@ edges | array_flow.rb:1179:10:1179:10 | b [element] : | array_flow.rb:1179:10:1179:13 | ...[...] | | array_flow.rb:1180:10:1180:10 | b [element] : | array_flow.rb:1180:10:1180:13 | ...[...] | | array_flow.rb:1180:10:1180:10 | b [element] : | array_flow.rb:1180:10:1180:13 | ...[...] | -| array_flow.rb:1184:16:1184:26 | call to source : | array_flow.rb:1185:9:1185:9 | a [element 2] : | -| array_flow.rb:1184:16:1184:26 | call to source : | array_flow.rb:1185:9:1185:9 | a [element 2] : | -| array_flow.rb:1184:16:1184:26 | call to source : | array_flow.rb:1188:10:1188:10 | a [element 2] : | -| array_flow.rb:1184:16:1184:26 | call to source : | array_flow.rb:1188:10:1188:10 | a [element 2] : | +| array_flow.rb:1184:5:1184:5 | a [element 2] : | array_flow.rb:1185:9:1185:9 | a [element 2] : | +| array_flow.rb:1184:5:1184:5 | a [element 2] : | array_flow.rb:1185:9:1185:9 | a [element 2] : | +| array_flow.rb:1184:5:1184:5 | a [element 2] : | array_flow.rb:1188:10:1188:10 | a [element 2] : | +| array_flow.rb:1184:5:1184:5 | a [element 2] : | array_flow.rb:1188:10:1188:10 | a [element 2] : | +| array_flow.rb:1184:16:1184:26 | call to source : | array_flow.rb:1184:5:1184:5 | a [element 2] : | +| array_flow.rb:1184:16:1184:26 | call to source : | array_flow.rb:1184:5:1184:5 | a [element 2] : | +| array_flow.rb:1185:5:1185:5 | b [element] : | array_flow.rb:1189:10:1189:10 | b [element] : | +| array_flow.rb:1185:5:1185:5 | b [element] : | array_flow.rb:1189:10:1189:10 | b [element] : | +| array_flow.rb:1185:5:1185:5 | b [element] : | array_flow.rb:1190:10:1190:10 | b [element] : | +| array_flow.rb:1185:5:1185:5 | b [element] : | array_flow.rb:1190:10:1190:10 | b [element] : | +| array_flow.rb:1185:5:1185:5 | b [element] : | array_flow.rb:1191:10:1191:10 | b [element] : | +| array_flow.rb:1185:5:1185:5 | b [element] : | array_flow.rb:1191:10:1191:10 | b [element] : | | array_flow.rb:1185:9:1185:9 | [post] a [element] : | array_flow.rb:1186:10:1186:10 | a [element] : | | array_flow.rb:1185:9:1185:9 | [post] a [element] : | array_flow.rb:1186:10:1186:10 | a [element] : | | array_flow.rb:1185:9:1185:9 | [post] a [element] : | array_flow.rb:1187:10:1187:10 | a [element] : | @@ -2369,12 +2952,8 @@ edges | array_flow.rb:1185:9:1185:9 | a [element 2] : | array_flow.rb:1185:9:1185:9 | [post] a [element] : | | array_flow.rb:1185:9:1185:9 | a [element 2] : | array_flow.rb:1185:9:1185:18 | call to shuffle! [element] : | | array_flow.rb:1185:9:1185:9 | a [element 2] : | array_flow.rb:1185:9:1185:18 | call to shuffle! [element] : | -| array_flow.rb:1185:9:1185:18 | call to shuffle! [element] : | array_flow.rb:1189:10:1189:10 | b [element] : | -| array_flow.rb:1185:9:1185:18 | call to shuffle! [element] : | array_flow.rb:1189:10:1189:10 | b [element] : | -| array_flow.rb:1185:9:1185:18 | call to shuffle! [element] : | array_flow.rb:1190:10:1190:10 | b [element] : | -| array_flow.rb:1185:9:1185:18 | call to shuffle! [element] : | array_flow.rb:1190:10:1190:10 | b [element] : | -| array_flow.rb:1185:9:1185:18 | call to shuffle! [element] : | array_flow.rb:1191:10:1191:10 | b [element] : | -| array_flow.rb:1185:9:1185:18 | call to shuffle! [element] : | array_flow.rb:1191:10:1191:10 | b [element] : | +| array_flow.rb:1185:9:1185:18 | call to shuffle! [element] : | array_flow.rb:1185:5:1185:5 | b [element] : | +| array_flow.rb:1185:9:1185:18 | call to shuffle! [element] : | array_flow.rb:1185:5:1185:5 | b [element] : | | array_flow.rb:1186:10:1186:10 | a [element] : | array_flow.rb:1186:10:1186:13 | ...[...] | | array_flow.rb:1186:10:1186:10 | a [element] : | array_flow.rb:1186:10:1186:13 | ...[...] | | array_flow.rb:1187:10:1187:10 | a [element] : | array_flow.rb:1187:10:1187:13 | ...[...] | @@ -2389,52 +2968,65 @@ edges | array_flow.rb:1190:10:1190:10 | b [element] : | array_flow.rb:1190:10:1190:13 | ...[...] | | array_flow.rb:1191:10:1191:10 | b [element] : | array_flow.rb:1191:10:1191:13 | ...[...] | | array_flow.rb:1191:10:1191:10 | b [element] : | array_flow.rb:1191:10:1191:13 | ...[...] | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1200:9:1200:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1200:9:1200:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1203:9:1203:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1203:9:1203:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1209:9:1209:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1209:9:1209:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1214:9:1214:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1214:9:1214:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1218:9:1218:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1218:9:1218:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1223:9:1223:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1223:9:1223:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1228:9:1228:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1228:9:1228:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1232:9:1232:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1232:9:1232:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1236:9:1236:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1236:9:1236:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1241:9:1241:9 | a [element 2] : | -| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1241:9:1241:9 | a [element 2] : | -| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1197:9:1197:9 | a [element 4] : | -| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1197:9:1197:9 | a [element 4] : | -| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1200:9:1200:9 | a [element 4] : | -| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1200:9:1200:9 | a [element 4] : | -| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1203:9:1203:9 | a [element 4] : | -| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1203:9:1203:9 | a [element 4] : | -| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1209:9:1209:9 | a [element 4] : | -| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1209:9:1209:9 | a [element 4] : | -| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1214:9:1214:9 | a [element 4] : | -| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1214:9:1214:9 | a [element 4] : | -| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1228:9:1228:9 | a [element 4] : | -| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1228:9:1228:9 | a [element 4] : | -| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1232:9:1232:9 | a [element 4] : | -| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1232:9:1232:9 | a [element 4] : | -| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1241:9:1241:9 | a [element 4] : | -| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1241:9:1241:9 | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1200:9:1200:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1200:9:1200:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1203:9:1203:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1203:9:1203:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1209:9:1209:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1209:9:1209:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1214:9:1214:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1214:9:1214:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1218:9:1218:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1218:9:1218:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1223:9:1223:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1223:9:1223:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1228:9:1228:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1228:9:1228:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1232:9:1232:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1232:9:1232:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1236:9:1236:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1236:9:1236:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1241:9:1241:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | array_flow.rb:1241:9:1241:9 | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | array_flow.rb:1197:9:1197:9 | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | array_flow.rb:1197:9:1197:9 | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | array_flow.rb:1200:9:1200:9 | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | array_flow.rb:1200:9:1200:9 | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | array_flow.rb:1203:9:1203:9 | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | array_flow.rb:1203:9:1203:9 | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | array_flow.rb:1209:9:1209:9 | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | array_flow.rb:1209:9:1209:9 | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | array_flow.rb:1214:9:1214:9 | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | array_flow.rb:1214:9:1214:9 | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | array_flow.rb:1228:9:1228:9 | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | array_flow.rb:1228:9:1228:9 | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | array_flow.rb:1232:9:1232:9 | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | array_flow.rb:1232:9:1232:9 | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | array_flow.rb:1241:9:1241:9 | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | array_flow.rb:1241:9:1241:9 | a [element 4] : | +| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1195:5:1195:5 | a [element 2] : | +| array_flow.rb:1195:16:1195:28 | call to source : | array_flow.rb:1195:5:1195:5 | a [element 2] : | +| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1195:5:1195:5 | a [element 4] : | +| array_flow.rb:1195:34:1195:46 | call to source : | array_flow.rb:1195:5:1195:5 | a [element 4] : | +| array_flow.rb:1197:5:1197:5 | b : | array_flow.rb:1198:10:1198:10 | b | +| array_flow.rb:1197:5:1197:5 | b : | array_flow.rb:1198:10:1198:10 | b | | array_flow.rb:1197:9:1197:9 | a [element 4] : | array_flow.rb:1197:9:1197:17 | call to slice : | | array_flow.rb:1197:9:1197:9 | a [element 4] : | array_flow.rb:1197:9:1197:17 | call to slice : | -| array_flow.rb:1197:9:1197:17 | call to slice : | array_flow.rb:1198:10:1198:10 | b | -| array_flow.rb:1197:9:1197:17 | call to slice : | array_flow.rb:1198:10:1198:10 | b | +| array_flow.rb:1197:9:1197:17 | call to slice : | array_flow.rb:1197:5:1197:5 | b : | +| array_flow.rb:1197:9:1197:17 | call to slice : | array_flow.rb:1197:5:1197:5 | b : | +| array_flow.rb:1200:5:1200:5 | b : | array_flow.rb:1201:10:1201:10 | b | +| array_flow.rb:1200:5:1200:5 | b : | array_flow.rb:1201:10:1201:10 | b | | array_flow.rb:1200:9:1200:9 | a [element 2] : | array_flow.rb:1200:9:1200:19 | call to slice : | | array_flow.rb:1200:9:1200:9 | a [element 2] : | array_flow.rb:1200:9:1200:19 | call to slice : | | array_flow.rb:1200:9:1200:9 | a [element 4] : | array_flow.rb:1200:9:1200:19 | call to slice : | | array_flow.rb:1200:9:1200:9 | a [element 4] : | array_flow.rb:1200:9:1200:19 | call to slice : | -| array_flow.rb:1200:9:1200:19 | call to slice : | array_flow.rb:1201:10:1201:10 | b | -| array_flow.rb:1200:9:1200:19 | call to slice : | array_flow.rb:1201:10:1201:10 | b | +| array_flow.rb:1200:9:1200:19 | call to slice : | array_flow.rb:1200:5:1200:5 | b : | +| array_flow.rb:1200:9:1200:19 | call to slice : | array_flow.rb:1200:5:1200:5 | b : | +| array_flow.rb:1203:5:1203:5 | b : | array_flow.rb:1205:10:1205:10 | b | +| array_flow.rb:1203:5:1203:5 | b : | array_flow.rb:1205:10:1205:10 | b | +| array_flow.rb:1203:5:1203:5 | b : | array_flow.rb:1207:10:1207:10 | b : | +| array_flow.rb:1203:5:1203:5 | b [element] : | array_flow.rb:1207:10:1207:10 | b [element] : | +| array_flow.rb:1203:5:1203:5 | b [element] : | array_flow.rb:1207:10:1207:10 | b [element] : | | array_flow.rb:1203:9:1203:9 | a [element 2] : | array_flow.rb:1203:9:1203:17 | call to slice : | | array_flow.rb:1203:9:1203:9 | a [element 2] : | array_flow.rb:1203:9:1203:17 | call to slice : | | array_flow.rb:1203:9:1203:9 | a [element 2] : | array_flow.rb:1203:9:1203:17 | call to slice [element] : | @@ -2443,114 +3035,146 @@ edges | array_flow.rb:1203:9:1203:9 | a [element 4] : | array_flow.rb:1203:9:1203:17 | call to slice : | | array_flow.rb:1203:9:1203:9 | a [element 4] : | array_flow.rb:1203:9:1203:17 | call to slice [element] : | | array_flow.rb:1203:9:1203:9 | a [element 4] : | array_flow.rb:1203:9:1203:17 | call to slice [element] : | -| array_flow.rb:1203:9:1203:17 | call to slice : | array_flow.rb:1205:10:1205:10 | b | -| array_flow.rb:1203:9:1203:17 | call to slice : | array_flow.rb:1205:10:1205:10 | b | -| array_flow.rb:1203:9:1203:17 | call to slice : | array_flow.rb:1207:10:1207:10 | b : | -| array_flow.rb:1203:9:1203:17 | call to slice [element] : | array_flow.rb:1207:10:1207:10 | b [element] : | -| array_flow.rb:1203:9:1203:17 | call to slice [element] : | array_flow.rb:1207:10:1207:10 | b [element] : | +| array_flow.rb:1203:9:1203:17 | call to slice : | array_flow.rb:1203:5:1203:5 | b : | +| array_flow.rb:1203:9:1203:17 | call to slice : | array_flow.rb:1203:5:1203:5 | b : | +| array_flow.rb:1203:9:1203:17 | call to slice [element] : | array_flow.rb:1203:5:1203:5 | b [element] : | +| array_flow.rb:1203:9:1203:17 | call to slice [element] : | array_flow.rb:1203:5:1203:5 | b [element] : | | array_flow.rb:1207:10:1207:10 | b : | array_flow.rb:1207:10:1207:13 | ...[...] | | array_flow.rb:1207:10:1207:10 | b [element] : | array_flow.rb:1207:10:1207:13 | ...[...] | | array_flow.rb:1207:10:1207:10 | b [element] : | array_flow.rb:1207:10:1207:13 | ...[...] | +| array_flow.rb:1209:5:1209:5 | b [element 0] : | array_flow.rb:1210:10:1210:10 | b [element 0] : | +| array_flow.rb:1209:5:1209:5 | b [element 0] : | array_flow.rb:1210:10:1210:10 | b [element 0] : | +| array_flow.rb:1209:5:1209:5 | b [element 2] : | array_flow.rb:1212:10:1212:10 | b [element 2] : | +| array_flow.rb:1209:5:1209:5 | b [element 2] : | array_flow.rb:1212:10:1212:10 | b [element 2] : | | array_flow.rb:1209:9:1209:9 | a [element 2] : | array_flow.rb:1209:9:1209:21 | call to slice [element 0] : | | array_flow.rb:1209:9:1209:9 | a [element 2] : | array_flow.rb:1209:9:1209:21 | call to slice [element 0] : | | array_flow.rb:1209:9:1209:9 | a [element 4] : | array_flow.rb:1209:9:1209:21 | call to slice [element 2] : | | array_flow.rb:1209:9:1209:9 | a [element 4] : | array_flow.rb:1209:9:1209:21 | call to slice [element 2] : | -| array_flow.rb:1209:9:1209:21 | call to slice [element 0] : | array_flow.rb:1210:10:1210:10 | b [element 0] : | -| array_flow.rb:1209:9:1209:21 | call to slice [element 0] : | array_flow.rb:1210:10:1210:10 | b [element 0] : | -| array_flow.rb:1209:9:1209:21 | call to slice [element 2] : | array_flow.rb:1212:10:1212:10 | b [element 2] : | -| array_flow.rb:1209:9:1209:21 | call to slice [element 2] : | array_flow.rb:1212:10:1212:10 | b [element 2] : | +| array_flow.rb:1209:9:1209:21 | call to slice [element 0] : | array_flow.rb:1209:5:1209:5 | b [element 0] : | +| array_flow.rb:1209:9:1209:21 | call to slice [element 0] : | array_flow.rb:1209:5:1209:5 | b [element 0] : | +| array_flow.rb:1209:9:1209:21 | call to slice [element 2] : | array_flow.rb:1209:5:1209:5 | b [element 2] : | +| array_flow.rb:1209:9:1209:21 | call to slice [element 2] : | array_flow.rb:1209:5:1209:5 | b [element 2] : | | array_flow.rb:1210:10:1210:10 | b [element 0] : | array_flow.rb:1210:10:1210:13 | ...[...] | | array_flow.rb:1210:10:1210:10 | b [element 0] : | array_flow.rb:1210:10:1210:13 | ...[...] | | array_flow.rb:1212:10:1212:10 | b [element 2] : | array_flow.rb:1212:10:1212:13 | ...[...] | | array_flow.rb:1212:10:1212:10 | b [element 2] : | array_flow.rb:1212:10:1212:13 | ...[...] | +| array_flow.rb:1214:5:1214:5 | b [element] : | array_flow.rb:1215:10:1215:10 | b [element] : | +| array_flow.rb:1214:5:1214:5 | b [element] : | array_flow.rb:1215:10:1215:10 | b [element] : | +| array_flow.rb:1214:5:1214:5 | b [element] : | array_flow.rb:1216:10:1216:10 | b [element] : | +| array_flow.rb:1214:5:1214:5 | b [element] : | array_flow.rb:1216:10:1216:10 | b [element] : | | array_flow.rb:1214:9:1214:9 | a [element 2] : | array_flow.rb:1214:9:1214:21 | call to slice [element] : | | array_flow.rb:1214:9:1214:9 | a [element 2] : | array_flow.rb:1214:9:1214:21 | call to slice [element] : | | array_flow.rb:1214:9:1214:9 | a [element 4] : | array_flow.rb:1214:9:1214:21 | call to slice [element] : | | array_flow.rb:1214:9:1214:9 | a [element 4] : | array_flow.rb:1214:9:1214:21 | call to slice [element] : | -| array_flow.rb:1214:9:1214:21 | call to slice [element] : | array_flow.rb:1215:10:1215:10 | b [element] : | -| array_flow.rb:1214:9:1214:21 | call to slice [element] : | array_flow.rb:1215:10:1215:10 | b [element] : | -| array_flow.rb:1214:9:1214:21 | call to slice [element] : | array_flow.rb:1216:10:1216:10 | b [element] : | -| array_flow.rb:1214:9:1214:21 | call to slice [element] : | array_flow.rb:1216:10:1216:10 | b [element] : | +| array_flow.rb:1214:9:1214:21 | call to slice [element] : | array_flow.rb:1214:5:1214:5 | b [element] : | +| array_flow.rb:1214:9:1214:21 | call to slice [element] : | array_flow.rb:1214:5:1214:5 | b [element] : | | array_flow.rb:1215:10:1215:10 | b [element] : | array_flow.rb:1215:10:1215:13 | ...[...] | | array_flow.rb:1215:10:1215:10 | b [element] : | array_flow.rb:1215:10:1215:13 | ...[...] | | array_flow.rb:1216:10:1216:10 | b [element] : | array_flow.rb:1216:10:1216:13 | ...[...] | | array_flow.rb:1216:10:1216:10 | b [element] : | array_flow.rb:1216:10:1216:13 | ...[...] | +| array_flow.rb:1218:5:1218:5 | b [element 0] : | array_flow.rb:1219:10:1219:10 | b [element 0] : | +| array_flow.rb:1218:5:1218:5 | b [element 0] : | array_flow.rb:1219:10:1219:10 | b [element 0] : | | array_flow.rb:1218:9:1218:9 | a [element 2] : | array_flow.rb:1218:9:1218:21 | call to slice [element 0] : | | array_flow.rb:1218:9:1218:9 | a [element 2] : | array_flow.rb:1218:9:1218:21 | call to slice [element 0] : | -| array_flow.rb:1218:9:1218:21 | call to slice [element 0] : | array_flow.rb:1219:10:1219:10 | b [element 0] : | -| array_flow.rb:1218:9:1218:21 | call to slice [element 0] : | array_flow.rb:1219:10:1219:10 | b [element 0] : | +| array_flow.rb:1218:9:1218:21 | call to slice [element 0] : | array_flow.rb:1218:5:1218:5 | b [element 0] : | +| array_flow.rb:1218:9:1218:21 | call to slice [element 0] : | array_flow.rb:1218:5:1218:5 | b [element 0] : | | array_flow.rb:1219:10:1219:10 | b [element 0] : | array_flow.rb:1219:10:1219:13 | ...[...] | | array_flow.rb:1219:10:1219:10 | b [element 0] : | array_flow.rb:1219:10:1219:13 | ...[...] | +| array_flow.rb:1223:5:1223:5 | b [element 0] : | array_flow.rb:1224:10:1224:10 | b [element 0] : | +| array_flow.rb:1223:5:1223:5 | b [element 0] : | array_flow.rb:1224:10:1224:10 | b [element 0] : | | array_flow.rb:1223:9:1223:9 | a [element 2] : | array_flow.rb:1223:9:1223:22 | call to slice [element 0] : | | array_flow.rb:1223:9:1223:9 | a [element 2] : | array_flow.rb:1223:9:1223:22 | call to slice [element 0] : | -| array_flow.rb:1223:9:1223:22 | call to slice [element 0] : | array_flow.rb:1224:10:1224:10 | b [element 0] : | -| array_flow.rb:1223:9:1223:22 | call to slice [element 0] : | array_flow.rb:1224:10:1224:10 | b [element 0] : | +| array_flow.rb:1223:9:1223:22 | call to slice [element 0] : | array_flow.rb:1223:5:1223:5 | b [element 0] : | +| array_flow.rb:1223:9:1223:22 | call to slice [element 0] : | array_flow.rb:1223:5:1223:5 | b [element 0] : | | array_flow.rb:1224:10:1224:10 | b [element 0] : | array_flow.rb:1224:10:1224:13 | ...[...] | | array_flow.rb:1224:10:1224:10 | b [element 0] : | array_flow.rb:1224:10:1224:13 | ...[...] | +| array_flow.rb:1228:5:1228:5 | b [element] : | array_flow.rb:1229:10:1229:10 | b [element] : | +| array_flow.rb:1228:5:1228:5 | b [element] : | array_flow.rb:1229:10:1229:10 | b [element] : | +| array_flow.rb:1228:5:1228:5 | b [element] : | array_flow.rb:1230:10:1230:10 | b [element] : | +| array_flow.rb:1228:5:1228:5 | b [element] : | array_flow.rb:1230:10:1230:10 | b [element] : | | array_flow.rb:1228:9:1228:9 | a [element 2] : | array_flow.rb:1228:9:1228:21 | call to slice [element] : | | array_flow.rb:1228:9:1228:9 | a [element 2] : | array_flow.rb:1228:9:1228:21 | call to slice [element] : | | array_flow.rb:1228:9:1228:9 | a [element 4] : | array_flow.rb:1228:9:1228:21 | call to slice [element] : | | array_flow.rb:1228:9:1228:9 | a [element 4] : | array_flow.rb:1228:9:1228:21 | call to slice [element] : | -| array_flow.rb:1228:9:1228:21 | call to slice [element] : | array_flow.rb:1229:10:1229:10 | b [element] : | -| array_flow.rb:1228:9:1228:21 | call to slice [element] : | array_flow.rb:1229:10:1229:10 | b [element] : | -| array_flow.rb:1228:9:1228:21 | call to slice [element] : | array_flow.rb:1230:10:1230:10 | b [element] : | -| array_flow.rb:1228:9:1228:21 | call to slice [element] : | array_flow.rb:1230:10:1230:10 | b [element] : | +| array_flow.rb:1228:9:1228:21 | call to slice [element] : | array_flow.rb:1228:5:1228:5 | b [element] : | +| array_flow.rb:1228:9:1228:21 | call to slice [element] : | array_flow.rb:1228:5:1228:5 | b [element] : | | array_flow.rb:1229:10:1229:10 | b [element] : | array_flow.rb:1229:10:1229:13 | ...[...] | | array_flow.rb:1229:10:1229:10 | b [element] : | array_flow.rb:1229:10:1229:13 | ...[...] | | array_flow.rb:1230:10:1230:10 | b [element] : | array_flow.rb:1230:10:1230:13 | ...[...] | | array_flow.rb:1230:10:1230:10 | b [element] : | array_flow.rb:1230:10:1230:13 | ...[...] | +| array_flow.rb:1232:5:1232:5 | b [element] : | array_flow.rb:1233:10:1233:10 | b [element] : | +| array_flow.rb:1232:5:1232:5 | b [element] : | array_flow.rb:1233:10:1233:10 | b [element] : | +| array_flow.rb:1232:5:1232:5 | b [element] : | array_flow.rb:1234:10:1234:10 | b [element] : | +| array_flow.rb:1232:5:1232:5 | b [element] : | array_flow.rb:1234:10:1234:10 | b [element] : | | array_flow.rb:1232:9:1232:9 | a [element 2] : | array_flow.rb:1232:9:1232:24 | call to slice [element] : | | array_flow.rb:1232:9:1232:9 | a [element 2] : | array_flow.rb:1232:9:1232:24 | call to slice [element] : | | array_flow.rb:1232:9:1232:9 | a [element 4] : | array_flow.rb:1232:9:1232:24 | call to slice [element] : | | array_flow.rb:1232:9:1232:9 | a [element 4] : | array_flow.rb:1232:9:1232:24 | call to slice [element] : | -| array_flow.rb:1232:9:1232:24 | call to slice [element] : | array_flow.rb:1233:10:1233:10 | b [element] : | -| array_flow.rb:1232:9:1232:24 | call to slice [element] : | array_flow.rb:1233:10:1233:10 | b [element] : | -| array_flow.rb:1232:9:1232:24 | call to slice [element] : | array_flow.rb:1234:10:1234:10 | b [element] : | -| array_flow.rb:1232:9:1232:24 | call to slice [element] : | array_flow.rb:1234:10:1234:10 | b [element] : | +| array_flow.rb:1232:9:1232:24 | call to slice [element] : | array_flow.rb:1232:5:1232:5 | b [element] : | +| array_flow.rb:1232:9:1232:24 | call to slice [element] : | array_flow.rb:1232:5:1232:5 | b [element] : | | array_flow.rb:1233:10:1233:10 | b [element] : | array_flow.rb:1233:10:1233:13 | ...[...] | | array_flow.rb:1233:10:1233:10 | b [element] : | array_flow.rb:1233:10:1233:13 | ...[...] | | array_flow.rb:1234:10:1234:10 | b [element] : | array_flow.rb:1234:10:1234:13 | ...[...] | | array_flow.rb:1234:10:1234:10 | b [element] : | array_flow.rb:1234:10:1234:13 | ...[...] | +| array_flow.rb:1236:5:1236:5 | b [element 2] : | array_flow.rb:1239:10:1239:10 | b [element 2] : | +| array_flow.rb:1236:5:1236:5 | b [element 2] : | array_flow.rb:1239:10:1239:10 | b [element 2] : | | array_flow.rb:1236:9:1236:9 | a [element 2] : | array_flow.rb:1236:9:1236:20 | call to slice [element 2] : | | array_flow.rb:1236:9:1236:9 | a [element 2] : | array_flow.rb:1236:9:1236:20 | call to slice [element 2] : | -| array_flow.rb:1236:9:1236:20 | call to slice [element 2] : | array_flow.rb:1239:10:1239:10 | b [element 2] : | -| array_flow.rb:1236:9:1236:20 | call to slice [element 2] : | array_flow.rb:1239:10:1239:10 | b [element 2] : | +| array_flow.rb:1236:9:1236:20 | call to slice [element 2] : | array_flow.rb:1236:5:1236:5 | b [element 2] : | +| array_flow.rb:1236:9:1236:20 | call to slice [element 2] : | array_flow.rb:1236:5:1236:5 | b [element 2] : | | array_flow.rb:1239:10:1239:10 | b [element 2] : | array_flow.rb:1239:10:1239:13 | ...[...] | | array_flow.rb:1239:10:1239:10 | b [element 2] : | array_flow.rb:1239:10:1239:13 | ...[...] | +| array_flow.rb:1241:5:1241:5 | b [element] : | array_flow.rb:1242:10:1242:10 | b [element] : | +| array_flow.rb:1241:5:1241:5 | b [element] : | array_flow.rb:1242:10:1242:10 | b [element] : | +| array_flow.rb:1241:5:1241:5 | b [element] : | array_flow.rb:1243:10:1243:10 | b [element] : | +| array_flow.rb:1241:5:1241:5 | b [element] : | array_flow.rb:1243:10:1243:10 | b [element] : | +| array_flow.rb:1241:5:1241:5 | b [element] : | array_flow.rb:1244:10:1244:10 | b [element] : | +| array_flow.rb:1241:5:1241:5 | b [element] : | array_flow.rb:1244:10:1244:10 | b [element] : | | array_flow.rb:1241:9:1241:9 | a [element 2] : | array_flow.rb:1241:9:1241:20 | call to slice [element] : | | array_flow.rb:1241:9:1241:9 | a [element 2] : | array_flow.rb:1241:9:1241:20 | call to slice [element] : | | array_flow.rb:1241:9:1241:9 | a [element 4] : | array_flow.rb:1241:9:1241:20 | call to slice [element] : | | array_flow.rb:1241:9:1241:9 | a [element 4] : | array_flow.rb:1241:9:1241:20 | call to slice [element] : | -| array_flow.rb:1241:9:1241:20 | call to slice [element] : | array_flow.rb:1242:10:1242:10 | b [element] : | -| array_flow.rb:1241:9:1241:20 | call to slice [element] : | array_flow.rb:1242:10:1242:10 | b [element] : | -| array_flow.rb:1241:9:1241:20 | call to slice [element] : | array_flow.rb:1243:10:1243:10 | b [element] : | -| array_flow.rb:1241:9:1241:20 | call to slice [element] : | array_flow.rb:1243:10:1243:10 | b [element] : | -| array_flow.rb:1241:9:1241:20 | call to slice [element] : | array_flow.rb:1244:10:1244:10 | b [element] : | -| array_flow.rb:1241:9:1241:20 | call to slice [element] : | array_flow.rb:1244:10:1244:10 | b [element] : | +| array_flow.rb:1241:9:1241:20 | call to slice [element] : | array_flow.rb:1241:5:1241:5 | b [element] : | +| array_flow.rb:1241:9:1241:20 | call to slice [element] : | array_flow.rb:1241:5:1241:5 | b [element] : | | array_flow.rb:1242:10:1242:10 | b [element] : | array_flow.rb:1242:10:1242:13 | ...[...] | | array_flow.rb:1242:10:1242:10 | b [element] : | array_flow.rb:1242:10:1242:13 | ...[...] | | array_flow.rb:1243:10:1243:10 | b [element] : | array_flow.rb:1243:10:1243:13 | ...[...] | | array_flow.rb:1243:10:1243:10 | b [element] : | array_flow.rb:1243:10:1243:13 | ...[...] | | array_flow.rb:1244:10:1244:10 | b [element] : | array_flow.rb:1244:10:1244:13 | ...[...] | | array_flow.rb:1244:10:1244:10 | b [element] : | array_flow.rb:1244:10:1244:13 | ...[...] | -| array_flow.rb:1248:16:1248:28 | call to source : | array_flow.rb:1249:9:1249:9 | a [element 2] : | -| array_flow.rb:1248:16:1248:28 | call to source : | array_flow.rb:1249:9:1249:9 | a [element 2] : | -| array_flow.rb:1248:34:1248:46 | call to source : | array_flow.rb:1249:9:1249:9 | a [element 4] : | -| array_flow.rb:1248:34:1248:46 | call to source : | array_flow.rb:1249:9:1249:9 | a [element 4] : | +| array_flow.rb:1248:5:1248:5 | a [element 2] : | array_flow.rb:1249:9:1249:9 | a [element 2] : | +| array_flow.rb:1248:5:1248:5 | a [element 2] : | array_flow.rb:1249:9:1249:9 | a [element 2] : | +| array_flow.rb:1248:5:1248:5 | a [element 4] : | array_flow.rb:1249:9:1249:9 | a [element 4] : | +| array_flow.rb:1248:5:1248:5 | a [element 4] : | array_flow.rb:1249:9:1249:9 | a [element 4] : | +| array_flow.rb:1248:16:1248:28 | call to source : | array_flow.rb:1248:5:1248:5 | a [element 2] : | +| array_flow.rb:1248:16:1248:28 | call to source : | array_flow.rb:1248:5:1248:5 | a [element 2] : | +| array_flow.rb:1248:34:1248:46 | call to source : | array_flow.rb:1248:5:1248:5 | a [element 4] : | +| array_flow.rb:1248:34:1248:46 | call to source : | array_flow.rb:1248:5:1248:5 | a [element 4] : | +| array_flow.rb:1249:5:1249:5 | b : | array_flow.rb:1250:10:1250:10 | b | +| array_flow.rb:1249:5:1249:5 | b : | array_flow.rb:1250:10:1250:10 | b | | array_flow.rb:1249:9:1249:9 | [post] a [element 3] : | array_flow.rb:1254:10:1254:10 | a [element 3] : | | array_flow.rb:1249:9:1249:9 | [post] a [element 3] : | array_flow.rb:1254:10:1254:10 | a [element 3] : | | array_flow.rb:1249:9:1249:9 | a [element 2] : | array_flow.rb:1249:9:1249:19 | call to slice! : | | array_flow.rb:1249:9:1249:9 | a [element 2] : | array_flow.rb:1249:9:1249:19 | call to slice! : | | array_flow.rb:1249:9:1249:9 | a [element 4] : | array_flow.rb:1249:9:1249:9 | [post] a [element 3] : | | array_flow.rb:1249:9:1249:9 | a [element 4] : | array_flow.rb:1249:9:1249:9 | [post] a [element 3] : | -| array_flow.rb:1249:9:1249:19 | call to slice! : | array_flow.rb:1250:10:1250:10 | b | -| array_flow.rb:1249:9:1249:19 | call to slice! : | array_flow.rb:1250:10:1250:10 | b | +| array_flow.rb:1249:9:1249:19 | call to slice! : | array_flow.rb:1249:5:1249:5 | b : | +| array_flow.rb:1249:9:1249:19 | call to slice! : | array_flow.rb:1249:5:1249:5 | b : | | array_flow.rb:1254:10:1254:10 | a [element 3] : | array_flow.rb:1254:10:1254:13 | ...[...] | | array_flow.rb:1254:10:1254:10 | a [element 3] : | array_flow.rb:1254:10:1254:13 | ...[...] | -| array_flow.rb:1256:16:1256:28 | call to source : | array_flow.rb:1257:9:1257:9 | a [element 2] : | -| array_flow.rb:1256:16:1256:28 | call to source : | array_flow.rb:1257:9:1257:9 | a [element 2] : | -| array_flow.rb:1256:34:1256:46 | call to source : | array_flow.rb:1257:9:1257:9 | a [element 4] : | -| array_flow.rb:1256:34:1256:46 | call to source : | array_flow.rb:1257:9:1257:9 | a [element 4] : | +| array_flow.rb:1256:5:1256:5 | a [element 2] : | array_flow.rb:1257:9:1257:9 | a [element 2] : | +| array_flow.rb:1256:5:1256:5 | a [element 2] : | array_flow.rb:1257:9:1257:9 | a [element 2] : | +| array_flow.rb:1256:5:1256:5 | a [element 4] : | array_flow.rb:1257:9:1257:9 | a [element 4] : | +| array_flow.rb:1256:5:1256:5 | a [element 4] : | array_flow.rb:1257:9:1257:9 | a [element 4] : | +| array_flow.rb:1256:16:1256:28 | call to source : | array_flow.rb:1256:5:1256:5 | a [element 2] : | +| array_flow.rb:1256:16:1256:28 | call to source : | array_flow.rb:1256:5:1256:5 | a [element 2] : | +| array_flow.rb:1256:34:1256:46 | call to source : | array_flow.rb:1256:5:1256:5 | a [element 4] : | +| array_flow.rb:1256:34:1256:46 | call to source : | array_flow.rb:1256:5:1256:5 | a [element 4] : | +| array_flow.rb:1257:5:1257:5 | b : | array_flow.rb:1263:10:1263:10 | b | +| array_flow.rb:1257:5:1257:5 | b : | array_flow.rb:1263:10:1263:10 | b | +| array_flow.rb:1257:5:1257:5 | b : | array_flow.rb:1265:10:1265:10 | b : | +| array_flow.rb:1257:5:1257:5 | b [element] : | array_flow.rb:1265:10:1265:10 | b [element] : | +| array_flow.rb:1257:5:1257:5 | b [element] : | array_flow.rb:1265:10:1265:10 | b [element] : | | array_flow.rb:1257:9:1257:9 | [post] a [element] : | array_flow.rb:1258:10:1258:10 | a [element] : | | array_flow.rb:1257:9:1257:9 | [post] a [element] : | array_flow.rb:1258:10:1258:10 | a [element] : | | array_flow.rb:1257:9:1257:9 | [post] a [element] : | array_flow.rb:1259:10:1259:10 | a [element] : | @@ -2571,11 +3195,10 @@ edges | array_flow.rb:1257:9:1257:9 | a [element 4] : | array_flow.rb:1257:9:1257:19 | call to slice! : | | array_flow.rb:1257:9:1257:9 | a [element 4] : | array_flow.rb:1257:9:1257:19 | call to slice! [element] : | | array_flow.rb:1257:9:1257:9 | a [element 4] : | array_flow.rb:1257:9:1257:19 | call to slice! [element] : | -| array_flow.rb:1257:9:1257:19 | call to slice! : | array_flow.rb:1263:10:1263:10 | b | -| array_flow.rb:1257:9:1257:19 | call to slice! : | array_flow.rb:1263:10:1263:10 | b | -| array_flow.rb:1257:9:1257:19 | call to slice! : | array_flow.rb:1265:10:1265:10 | b : | -| array_flow.rb:1257:9:1257:19 | call to slice! [element] : | array_flow.rb:1265:10:1265:10 | b [element] : | -| array_flow.rb:1257:9:1257:19 | call to slice! [element] : | array_flow.rb:1265:10:1265:10 | b [element] : | +| array_flow.rb:1257:9:1257:19 | call to slice! : | array_flow.rb:1257:5:1257:5 | b : | +| array_flow.rb:1257:9:1257:19 | call to slice! : | array_flow.rb:1257:5:1257:5 | b : | +| array_flow.rb:1257:9:1257:19 | call to slice! [element] : | array_flow.rb:1257:5:1257:5 | b [element] : | +| array_flow.rb:1257:9:1257:19 | call to slice! [element] : | array_flow.rb:1257:5:1257:5 | b [element] : | | array_flow.rb:1258:10:1258:10 | a [element] : | array_flow.rb:1258:10:1258:13 | ...[...] | | array_flow.rb:1258:10:1258:10 | a [element] : | array_flow.rb:1258:10:1258:13 | ...[...] | | array_flow.rb:1259:10:1259:10 | a [element] : | array_flow.rb:1259:10:1259:13 | ...[...] | @@ -2587,58 +3210,88 @@ edges | array_flow.rb:1265:10:1265:10 | b : | array_flow.rb:1265:10:1265:13 | ...[...] | | array_flow.rb:1265:10:1265:10 | b [element] : | array_flow.rb:1265:10:1265:13 | ...[...] | | array_flow.rb:1265:10:1265:10 | b [element] : | array_flow.rb:1265:10:1265:13 | ...[...] | -| array_flow.rb:1267:16:1267:28 | call to source : | array_flow.rb:1268:9:1268:9 | a [element 2] : | -| array_flow.rb:1267:16:1267:28 | call to source : | array_flow.rb:1268:9:1268:9 | a [element 2] : | -| array_flow.rb:1267:34:1267:46 | call to source : | array_flow.rb:1268:9:1268:9 | a [element 4] : | -| array_flow.rb:1267:34:1267:46 | call to source : | array_flow.rb:1268:9:1268:9 | a [element 4] : | +| array_flow.rb:1267:5:1267:5 | a [element 2] : | array_flow.rb:1268:9:1268:9 | a [element 2] : | +| array_flow.rb:1267:5:1267:5 | a [element 2] : | array_flow.rb:1268:9:1268:9 | a [element 2] : | +| array_flow.rb:1267:5:1267:5 | a [element 4] : | array_flow.rb:1268:9:1268:9 | a [element 4] : | +| array_flow.rb:1267:5:1267:5 | a [element 4] : | array_flow.rb:1268:9:1268:9 | a [element 4] : | +| array_flow.rb:1267:16:1267:28 | call to source : | array_flow.rb:1267:5:1267:5 | a [element 2] : | +| array_flow.rb:1267:16:1267:28 | call to source : | array_flow.rb:1267:5:1267:5 | a [element 2] : | +| array_flow.rb:1267:34:1267:46 | call to source : | array_flow.rb:1267:5:1267:5 | a [element 4] : | +| array_flow.rb:1267:34:1267:46 | call to source : | array_flow.rb:1267:5:1267:5 | a [element 4] : | +| array_flow.rb:1268:5:1268:5 | b [element 0] : | array_flow.rb:1269:10:1269:10 | b [element 0] : | +| array_flow.rb:1268:5:1268:5 | b [element 0] : | array_flow.rb:1269:10:1269:10 | b [element 0] : | +| array_flow.rb:1268:5:1268:5 | b [element 2] : | array_flow.rb:1271:10:1271:10 | b [element 2] : | +| array_flow.rb:1268:5:1268:5 | b [element 2] : | array_flow.rb:1271:10:1271:10 | b [element 2] : | | array_flow.rb:1268:9:1268:9 | a [element 2] : | array_flow.rb:1268:9:1268:22 | call to slice! [element 0] : | | array_flow.rb:1268:9:1268:9 | a [element 2] : | array_flow.rb:1268:9:1268:22 | call to slice! [element 0] : | | array_flow.rb:1268:9:1268:9 | a [element 4] : | array_flow.rb:1268:9:1268:22 | call to slice! [element 2] : | | array_flow.rb:1268:9:1268:9 | a [element 4] : | array_flow.rb:1268:9:1268:22 | call to slice! [element 2] : | -| array_flow.rb:1268:9:1268:22 | call to slice! [element 0] : | array_flow.rb:1269:10:1269:10 | b [element 0] : | -| array_flow.rb:1268:9:1268:22 | call to slice! [element 0] : | array_flow.rb:1269:10:1269:10 | b [element 0] : | -| array_flow.rb:1268:9:1268:22 | call to slice! [element 2] : | array_flow.rb:1271:10:1271:10 | b [element 2] : | -| array_flow.rb:1268:9:1268:22 | call to slice! [element 2] : | array_flow.rb:1271:10:1271:10 | b [element 2] : | +| array_flow.rb:1268:9:1268:22 | call to slice! [element 0] : | array_flow.rb:1268:5:1268:5 | b [element 0] : | +| array_flow.rb:1268:9:1268:22 | call to slice! [element 0] : | array_flow.rb:1268:5:1268:5 | b [element 0] : | +| array_flow.rb:1268:9:1268:22 | call to slice! [element 2] : | array_flow.rb:1268:5:1268:5 | b [element 2] : | +| array_flow.rb:1268:9:1268:22 | call to slice! [element 2] : | array_flow.rb:1268:5:1268:5 | b [element 2] : | | array_flow.rb:1269:10:1269:10 | b [element 0] : | array_flow.rb:1269:10:1269:13 | ...[...] | | array_flow.rb:1269:10:1269:10 | b [element 0] : | array_flow.rb:1269:10:1269:13 | ...[...] | | array_flow.rb:1271:10:1271:10 | b [element 2] : | array_flow.rb:1271:10:1271:13 | ...[...] | | array_flow.rb:1271:10:1271:10 | b [element 2] : | array_flow.rb:1271:10:1271:13 | ...[...] | -| array_flow.rb:1278:16:1278:28 | call to source : | array_flow.rb:1279:9:1279:9 | a [element 2] : | -| array_flow.rb:1278:16:1278:28 | call to source : | array_flow.rb:1279:9:1279:9 | a [element 2] : | -| array_flow.rb:1278:34:1278:46 | call to source : | array_flow.rb:1279:9:1279:9 | a [element 4] : | -| array_flow.rb:1278:34:1278:46 | call to source : | array_flow.rb:1279:9:1279:9 | a [element 4] : | +| array_flow.rb:1278:5:1278:5 | a [element 2] : | array_flow.rb:1279:9:1279:9 | a [element 2] : | +| array_flow.rb:1278:5:1278:5 | a [element 2] : | array_flow.rb:1279:9:1279:9 | a [element 2] : | +| array_flow.rb:1278:5:1278:5 | a [element 4] : | array_flow.rb:1279:9:1279:9 | a [element 4] : | +| array_flow.rb:1278:5:1278:5 | a [element 4] : | array_flow.rb:1279:9:1279:9 | a [element 4] : | +| array_flow.rb:1278:16:1278:28 | call to source : | array_flow.rb:1278:5:1278:5 | a [element 2] : | +| array_flow.rb:1278:16:1278:28 | call to source : | array_flow.rb:1278:5:1278:5 | a [element 2] : | +| array_flow.rb:1278:34:1278:46 | call to source : | array_flow.rb:1278:5:1278:5 | a [element 4] : | +| array_flow.rb:1278:34:1278:46 | call to source : | array_flow.rb:1278:5:1278:5 | a [element 4] : | +| array_flow.rb:1279:5:1279:5 | b [element 0] : | array_flow.rb:1280:10:1280:10 | b [element 0] : | +| array_flow.rb:1279:5:1279:5 | b [element 0] : | array_flow.rb:1280:10:1280:10 | b [element 0] : | | array_flow.rb:1279:9:1279:9 | [post] a [element 2] : | array_flow.rb:1285:10:1285:10 | a [element 2] : | | array_flow.rb:1279:9:1279:9 | [post] a [element 2] : | array_flow.rb:1285:10:1285:10 | a [element 2] : | | array_flow.rb:1279:9:1279:9 | a [element 2] : | array_flow.rb:1279:9:1279:22 | call to slice! [element 0] : | | array_flow.rb:1279:9:1279:9 | a [element 2] : | array_flow.rb:1279:9:1279:22 | call to slice! [element 0] : | | array_flow.rb:1279:9:1279:9 | a [element 4] : | array_flow.rb:1279:9:1279:9 | [post] a [element 2] : | | array_flow.rb:1279:9:1279:9 | a [element 4] : | array_flow.rb:1279:9:1279:9 | [post] a [element 2] : | -| array_flow.rb:1279:9:1279:22 | call to slice! [element 0] : | array_flow.rb:1280:10:1280:10 | b [element 0] : | -| array_flow.rb:1279:9:1279:22 | call to slice! [element 0] : | array_flow.rb:1280:10:1280:10 | b [element 0] : | +| array_flow.rb:1279:9:1279:22 | call to slice! [element 0] : | array_flow.rb:1279:5:1279:5 | b [element 0] : | +| array_flow.rb:1279:9:1279:22 | call to slice! [element 0] : | array_flow.rb:1279:5:1279:5 | b [element 0] : | | array_flow.rb:1280:10:1280:10 | b [element 0] : | array_flow.rb:1280:10:1280:13 | ...[...] | | array_flow.rb:1280:10:1280:10 | b [element 0] : | array_flow.rb:1280:10:1280:13 | ...[...] | | array_flow.rb:1285:10:1285:10 | a [element 2] : | array_flow.rb:1285:10:1285:13 | ...[...] | | array_flow.rb:1285:10:1285:10 | a [element 2] : | array_flow.rb:1285:10:1285:13 | ...[...] | -| array_flow.rb:1289:16:1289:28 | call to source : | array_flow.rb:1290:9:1290:9 | a [element 2] : | -| array_flow.rb:1289:16:1289:28 | call to source : | array_flow.rb:1290:9:1290:9 | a [element 2] : | -| array_flow.rb:1289:34:1289:46 | call to source : | array_flow.rb:1290:9:1290:9 | a [element 4] : | -| array_flow.rb:1289:34:1289:46 | call to source : | array_flow.rb:1290:9:1290:9 | a [element 4] : | +| array_flow.rb:1289:5:1289:5 | a [element 2] : | array_flow.rb:1290:9:1290:9 | a [element 2] : | +| array_flow.rb:1289:5:1289:5 | a [element 2] : | array_flow.rb:1290:9:1290:9 | a [element 2] : | +| array_flow.rb:1289:5:1289:5 | a [element 4] : | array_flow.rb:1290:9:1290:9 | a [element 4] : | +| array_flow.rb:1289:5:1289:5 | a [element 4] : | array_flow.rb:1290:9:1290:9 | a [element 4] : | +| array_flow.rb:1289:16:1289:28 | call to source : | array_flow.rb:1289:5:1289:5 | a [element 2] : | +| array_flow.rb:1289:16:1289:28 | call to source : | array_flow.rb:1289:5:1289:5 | a [element 2] : | +| array_flow.rb:1289:34:1289:46 | call to source : | array_flow.rb:1289:5:1289:5 | a [element 4] : | +| array_flow.rb:1289:34:1289:46 | call to source : | array_flow.rb:1289:5:1289:5 | a [element 4] : | +| array_flow.rb:1290:5:1290:5 | b [element 0] : | array_flow.rb:1291:10:1291:10 | b [element 0] : | +| array_flow.rb:1290:5:1290:5 | b [element 0] : | array_flow.rb:1291:10:1291:10 | b [element 0] : | | array_flow.rb:1290:9:1290:9 | [post] a [element 2] : | array_flow.rb:1296:10:1296:10 | a [element 2] : | | array_flow.rb:1290:9:1290:9 | [post] a [element 2] : | array_flow.rb:1296:10:1296:10 | a [element 2] : | | array_flow.rb:1290:9:1290:9 | a [element 2] : | array_flow.rb:1290:9:1290:23 | call to slice! [element 0] : | | array_flow.rb:1290:9:1290:9 | a [element 2] : | array_flow.rb:1290:9:1290:23 | call to slice! [element 0] : | | array_flow.rb:1290:9:1290:9 | a [element 4] : | array_flow.rb:1290:9:1290:9 | [post] a [element 2] : | | array_flow.rb:1290:9:1290:9 | a [element 4] : | array_flow.rb:1290:9:1290:9 | [post] a [element 2] : | -| array_flow.rb:1290:9:1290:23 | call to slice! [element 0] : | array_flow.rb:1291:10:1291:10 | b [element 0] : | -| array_flow.rb:1290:9:1290:23 | call to slice! [element 0] : | array_flow.rb:1291:10:1291:10 | b [element 0] : | +| array_flow.rb:1290:9:1290:23 | call to slice! [element 0] : | array_flow.rb:1290:5:1290:5 | b [element 0] : | +| array_flow.rb:1290:9:1290:23 | call to slice! [element 0] : | array_flow.rb:1290:5:1290:5 | b [element 0] : | | array_flow.rb:1291:10:1291:10 | b [element 0] : | array_flow.rb:1291:10:1291:13 | ...[...] | | array_flow.rb:1291:10:1291:10 | b [element 0] : | array_flow.rb:1291:10:1291:13 | ...[...] | | array_flow.rb:1296:10:1296:10 | a [element 2] : | array_flow.rb:1296:10:1296:13 | ...[...] | | array_flow.rb:1296:10:1296:10 | a [element 2] : | array_flow.rb:1296:10:1296:13 | ...[...] | -| array_flow.rb:1300:16:1300:28 | call to source : | array_flow.rb:1301:9:1301:9 | a [element 2] : | -| array_flow.rb:1300:16:1300:28 | call to source : | array_flow.rb:1301:9:1301:9 | a [element 2] : | -| array_flow.rb:1300:34:1300:46 | call to source : | array_flow.rb:1301:9:1301:9 | a [element 4] : | -| array_flow.rb:1300:34:1300:46 | call to source : | array_flow.rb:1301:9:1301:9 | a [element 4] : | +| array_flow.rb:1300:5:1300:5 | a [element 2] : | array_flow.rb:1301:9:1301:9 | a [element 2] : | +| array_flow.rb:1300:5:1300:5 | a [element 2] : | array_flow.rb:1301:9:1301:9 | a [element 2] : | +| array_flow.rb:1300:5:1300:5 | a [element 4] : | array_flow.rb:1301:9:1301:9 | a [element 4] : | +| array_flow.rb:1300:5:1300:5 | a [element 4] : | array_flow.rb:1301:9:1301:9 | a [element 4] : | +| array_flow.rb:1300:16:1300:28 | call to source : | array_flow.rb:1300:5:1300:5 | a [element 2] : | +| array_flow.rb:1300:16:1300:28 | call to source : | array_flow.rb:1300:5:1300:5 | a [element 2] : | +| array_flow.rb:1300:34:1300:46 | call to source : | array_flow.rb:1300:5:1300:5 | a [element 4] : | +| array_flow.rb:1300:34:1300:46 | call to source : | array_flow.rb:1300:5:1300:5 | a [element 4] : | +| array_flow.rb:1301:5:1301:5 | b [element] : | array_flow.rb:1302:10:1302:10 | b [element] : | +| array_flow.rb:1301:5:1301:5 | b [element] : | array_flow.rb:1302:10:1302:10 | b [element] : | +| array_flow.rb:1301:5:1301:5 | b [element] : | array_flow.rb:1303:10:1303:10 | b [element] : | +| array_flow.rb:1301:5:1301:5 | b [element] : | array_flow.rb:1303:10:1303:10 | b [element] : | +| array_flow.rb:1301:5:1301:5 | b [element] : | array_flow.rb:1304:10:1304:10 | b [element] : | +| array_flow.rb:1301:5:1301:5 | b [element] : | array_flow.rb:1304:10:1304:10 | b [element] : | | array_flow.rb:1301:9:1301:9 | [post] a [element] : | array_flow.rb:1305:10:1305:10 | a [element] : | | array_flow.rb:1301:9:1301:9 | [post] a [element] : | array_flow.rb:1305:10:1305:10 | a [element] : | | array_flow.rb:1301:9:1301:9 | [post] a [element] : | array_flow.rb:1306:10:1306:10 | a [element] : | @@ -2653,12 +3306,8 @@ edges | array_flow.rb:1301:9:1301:9 | a [element 4] : | array_flow.rb:1301:9:1301:9 | [post] a [element] : | | array_flow.rb:1301:9:1301:9 | a [element 4] : | array_flow.rb:1301:9:1301:22 | call to slice! [element] : | | array_flow.rb:1301:9:1301:9 | a [element 4] : | array_flow.rb:1301:9:1301:22 | call to slice! [element] : | -| array_flow.rb:1301:9:1301:22 | call to slice! [element] : | array_flow.rb:1302:10:1302:10 | b [element] : | -| array_flow.rb:1301:9:1301:22 | call to slice! [element] : | array_flow.rb:1302:10:1302:10 | b [element] : | -| array_flow.rb:1301:9:1301:22 | call to slice! [element] : | array_flow.rb:1303:10:1303:10 | b [element] : | -| array_flow.rb:1301:9:1301:22 | call to slice! [element] : | array_flow.rb:1303:10:1303:10 | b [element] : | -| array_flow.rb:1301:9:1301:22 | call to slice! [element] : | array_flow.rb:1304:10:1304:10 | b [element] : | -| array_flow.rb:1301:9:1301:22 | call to slice! [element] : | array_flow.rb:1304:10:1304:10 | b [element] : | +| array_flow.rb:1301:9:1301:22 | call to slice! [element] : | array_flow.rb:1301:5:1301:5 | b [element] : | +| array_flow.rb:1301:9:1301:22 | call to slice! [element] : | array_flow.rb:1301:5:1301:5 | b [element] : | | array_flow.rb:1302:10:1302:10 | b [element] : | array_flow.rb:1302:10:1302:13 | ...[...] | | array_flow.rb:1302:10:1302:10 | b [element] : | array_flow.rb:1302:10:1302:13 | ...[...] | | array_flow.rb:1303:10:1303:10 | b [element] : | array_flow.rb:1303:10:1303:13 | ...[...] | @@ -2671,10 +3320,20 @@ edges | array_flow.rb:1306:10:1306:10 | a [element] : | array_flow.rb:1306:10:1306:13 | ...[...] | | array_flow.rb:1307:10:1307:10 | a [element] : | array_flow.rb:1307:10:1307:13 | ...[...] | | array_flow.rb:1307:10:1307:10 | a [element] : | array_flow.rb:1307:10:1307:13 | ...[...] | -| array_flow.rb:1309:16:1309:28 | call to source : | array_flow.rb:1310:9:1310:9 | a [element 2] : | -| array_flow.rb:1309:16:1309:28 | call to source : | array_flow.rb:1310:9:1310:9 | a [element 2] : | -| array_flow.rb:1309:34:1309:46 | call to source : | array_flow.rb:1310:9:1310:9 | a [element 4] : | -| array_flow.rb:1309:34:1309:46 | call to source : | array_flow.rb:1310:9:1310:9 | a [element 4] : | +| array_flow.rb:1309:5:1309:5 | a [element 2] : | array_flow.rb:1310:9:1310:9 | a [element 2] : | +| array_flow.rb:1309:5:1309:5 | a [element 2] : | array_flow.rb:1310:9:1310:9 | a [element 2] : | +| array_flow.rb:1309:5:1309:5 | a [element 4] : | array_flow.rb:1310:9:1310:9 | a [element 4] : | +| array_flow.rb:1309:5:1309:5 | a [element 4] : | array_flow.rb:1310:9:1310:9 | a [element 4] : | +| array_flow.rb:1309:16:1309:28 | call to source : | array_flow.rb:1309:5:1309:5 | a [element 2] : | +| array_flow.rb:1309:16:1309:28 | call to source : | array_flow.rb:1309:5:1309:5 | a [element 2] : | +| array_flow.rb:1309:34:1309:46 | call to source : | array_flow.rb:1309:5:1309:5 | a [element 4] : | +| array_flow.rb:1309:34:1309:46 | call to source : | array_flow.rb:1309:5:1309:5 | a [element 4] : | +| array_flow.rb:1310:5:1310:5 | b [element] : | array_flow.rb:1311:10:1311:10 | b [element] : | +| array_flow.rb:1310:5:1310:5 | b [element] : | array_flow.rb:1311:10:1311:10 | b [element] : | +| array_flow.rb:1310:5:1310:5 | b [element] : | array_flow.rb:1312:10:1312:10 | b [element] : | +| array_flow.rb:1310:5:1310:5 | b [element] : | array_flow.rb:1312:10:1312:10 | b [element] : | +| array_flow.rb:1310:5:1310:5 | b [element] : | array_flow.rb:1313:10:1313:10 | b [element] : | +| array_flow.rb:1310:5:1310:5 | b [element] : | array_flow.rb:1313:10:1313:10 | b [element] : | | array_flow.rb:1310:9:1310:9 | [post] a [element] : | array_flow.rb:1314:10:1314:10 | a [element] : | | array_flow.rb:1310:9:1310:9 | [post] a [element] : | array_flow.rb:1314:10:1314:10 | a [element] : | | array_flow.rb:1310:9:1310:9 | [post] a [element] : | array_flow.rb:1315:10:1315:10 | a [element] : | @@ -2689,12 +3348,8 @@ edges | array_flow.rb:1310:9:1310:9 | a [element 4] : | array_flow.rb:1310:9:1310:9 | [post] a [element] : | | array_flow.rb:1310:9:1310:9 | a [element 4] : | array_flow.rb:1310:9:1310:22 | call to slice! [element] : | | array_flow.rb:1310:9:1310:9 | a [element 4] : | array_flow.rb:1310:9:1310:22 | call to slice! [element] : | -| array_flow.rb:1310:9:1310:22 | call to slice! [element] : | array_flow.rb:1311:10:1311:10 | b [element] : | -| array_flow.rb:1310:9:1310:22 | call to slice! [element] : | array_flow.rb:1311:10:1311:10 | b [element] : | -| array_flow.rb:1310:9:1310:22 | call to slice! [element] : | array_flow.rb:1312:10:1312:10 | b [element] : | -| array_flow.rb:1310:9:1310:22 | call to slice! [element] : | array_flow.rb:1312:10:1312:10 | b [element] : | -| array_flow.rb:1310:9:1310:22 | call to slice! [element] : | array_flow.rb:1313:10:1313:10 | b [element] : | -| array_flow.rb:1310:9:1310:22 | call to slice! [element] : | array_flow.rb:1313:10:1313:10 | b [element] : | +| array_flow.rb:1310:9:1310:22 | call to slice! [element] : | array_flow.rb:1310:5:1310:5 | b [element] : | +| array_flow.rb:1310:9:1310:22 | call to slice! [element] : | array_flow.rb:1310:5:1310:5 | b [element] : | | array_flow.rb:1311:10:1311:10 | b [element] : | array_flow.rb:1311:10:1311:13 | ...[...] | | array_flow.rb:1311:10:1311:10 | b [element] : | array_flow.rb:1311:10:1311:13 | ...[...] | | array_flow.rb:1312:10:1312:10 | b [element] : | array_flow.rb:1312:10:1312:13 | ...[...] | @@ -2707,10 +3362,20 @@ edges | array_flow.rb:1315:10:1315:10 | a [element] : | array_flow.rb:1315:10:1315:13 | ...[...] | | array_flow.rb:1316:10:1316:10 | a [element] : | array_flow.rb:1316:10:1316:13 | ...[...] | | array_flow.rb:1316:10:1316:10 | a [element] : | array_flow.rb:1316:10:1316:13 | ...[...] | -| array_flow.rb:1318:16:1318:28 | call to source : | array_flow.rb:1319:9:1319:9 | a [element 2] : | -| array_flow.rb:1318:16:1318:28 | call to source : | array_flow.rb:1319:9:1319:9 | a [element 2] : | -| array_flow.rb:1318:34:1318:46 | call to source : | array_flow.rb:1319:9:1319:9 | a [element 4] : | -| array_flow.rb:1318:34:1318:46 | call to source : | array_flow.rb:1319:9:1319:9 | a [element 4] : | +| array_flow.rb:1318:5:1318:5 | a [element 2] : | array_flow.rb:1319:9:1319:9 | a [element 2] : | +| array_flow.rb:1318:5:1318:5 | a [element 2] : | array_flow.rb:1319:9:1319:9 | a [element 2] : | +| array_flow.rb:1318:5:1318:5 | a [element 4] : | array_flow.rb:1319:9:1319:9 | a [element 4] : | +| array_flow.rb:1318:5:1318:5 | a [element 4] : | array_flow.rb:1319:9:1319:9 | a [element 4] : | +| array_flow.rb:1318:16:1318:28 | call to source : | array_flow.rb:1318:5:1318:5 | a [element 2] : | +| array_flow.rb:1318:16:1318:28 | call to source : | array_flow.rb:1318:5:1318:5 | a [element 2] : | +| array_flow.rb:1318:34:1318:46 | call to source : | array_flow.rb:1318:5:1318:5 | a [element 4] : | +| array_flow.rb:1318:34:1318:46 | call to source : | array_flow.rb:1318:5:1318:5 | a [element 4] : | +| array_flow.rb:1319:5:1319:5 | b [element] : | array_flow.rb:1320:10:1320:10 | b [element] : | +| array_flow.rb:1319:5:1319:5 | b [element] : | array_flow.rb:1320:10:1320:10 | b [element] : | +| array_flow.rb:1319:5:1319:5 | b [element] : | array_flow.rb:1321:10:1321:10 | b [element] : | +| array_flow.rb:1319:5:1319:5 | b [element] : | array_flow.rb:1321:10:1321:10 | b [element] : | +| array_flow.rb:1319:5:1319:5 | b [element] : | array_flow.rb:1322:10:1322:10 | b [element] : | +| array_flow.rb:1319:5:1319:5 | b [element] : | array_flow.rb:1322:10:1322:10 | b [element] : | | array_flow.rb:1319:9:1319:9 | [post] a [element] : | array_flow.rb:1323:10:1323:10 | a [element] : | | array_flow.rb:1319:9:1319:9 | [post] a [element] : | array_flow.rb:1323:10:1323:10 | a [element] : | | array_flow.rb:1319:9:1319:9 | [post] a [element] : | array_flow.rb:1324:10:1324:10 | a [element] : | @@ -2725,12 +3390,8 @@ edges | array_flow.rb:1319:9:1319:9 | a [element 4] : | array_flow.rb:1319:9:1319:9 | [post] a [element] : | | array_flow.rb:1319:9:1319:9 | a [element 4] : | array_flow.rb:1319:9:1319:25 | call to slice! [element] : | | array_flow.rb:1319:9:1319:9 | a [element 4] : | array_flow.rb:1319:9:1319:25 | call to slice! [element] : | -| array_flow.rb:1319:9:1319:25 | call to slice! [element] : | array_flow.rb:1320:10:1320:10 | b [element] : | -| array_flow.rb:1319:9:1319:25 | call to slice! [element] : | array_flow.rb:1320:10:1320:10 | b [element] : | -| array_flow.rb:1319:9:1319:25 | call to slice! [element] : | array_flow.rb:1321:10:1321:10 | b [element] : | -| array_flow.rb:1319:9:1319:25 | call to slice! [element] : | array_flow.rb:1321:10:1321:10 | b [element] : | -| array_flow.rb:1319:9:1319:25 | call to slice! [element] : | array_flow.rb:1322:10:1322:10 | b [element] : | -| array_flow.rb:1319:9:1319:25 | call to slice! [element] : | array_flow.rb:1322:10:1322:10 | b [element] : | +| array_flow.rb:1319:9:1319:25 | call to slice! [element] : | array_flow.rb:1319:5:1319:5 | b [element] : | +| array_flow.rb:1319:9:1319:25 | call to slice! [element] : | array_flow.rb:1319:5:1319:5 | b [element] : | | array_flow.rb:1320:10:1320:10 | b [element] : | array_flow.rb:1320:10:1320:13 | ...[...] | | array_flow.rb:1320:10:1320:10 | b [element] : | array_flow.rb:1320:10:1320:13 | ...[...] | | array_flow.rb:1321:10:1321:10 | b [element] : | array_flow.rb:1321:10:1321:13 | ...[...] | @@ -2743,26 +3404,42 @@ edges | array_flow.rb:1324:10:1324:10 | a [element] : | array_flow.rb:1324:10:1324:13 | ...[...] | | array_flow.rb:1325:10:1325:10 | a [element] : | array_flow.rb:1325:10:1325:13 | ...[...] | | array_flow.rb:1325:10:1325:10 | a [element] : | array_flow.rb:1325:10:1325:13 | ...[...] | -| array_flow.rb:1327:16:1327:28 | call to source : | array_flow.rb:1328:9:1328:9 | a [element 2] : | -| array_flow.rb:1327:16:1327:28 | call to source : | array_flow.rb:1328:9:1328:9 | a [element 2] : | -| array_flow.rb:1327:34:1327:46 | call to source : | array_flow.rb:1328:9:1328:9 | a [element 4] : | -| array_flow.rb:1327:34:1327:46 | call to source : | array_flow.rb:1328:9:1328:9 | a [element 4] : | +| array_flow.rb:1327:5:1327:5 | a [element 2] : | array_flow.rb:1328:9:1328:9 | a [element 2] : | +| array_flow.rb:1327:5:1327:5 | a [element 2] : | array_flow.rb:1328:9:1328:9 | a [element 2] : | +| array_flow.rb:1327:5:1327:5 | a [element 4] : | array_flow.rb:1328:9:1328:9 | a [element 4] : | +| array_flow.rb:1327:5:1327:5 | a [element 4] : | array_flow.rb:1328:9:1328:9 | a [element 4] : | +| array_flow.rb:1327:16:1327:28 | call to source : | array_flow.rb:1327:5:1327:5 | a [element 2] : | +| array_flow.rb:1327:16:1327:28 | call to source : | array_flow.rb:1327:5:1327:5 | a [element 2] : | +| array_flow.rb:1327:34:1327:46 | call to source : | array_flow.rb:1327:5:1327:5 | a [element 4] : | +| array_flow.rb:1327:34:1327:46 | call to source : | array_flow.rb:1327:5:1327:5 | a [element 4] : | +| array_flow.rb:1328:5:1328:5 | b [element 2] : | array_flow.rb:1331:10:1331:10 | b [element 2] : | +| array_flow.rb:1328:5:1328:5 | b [element 2] : | array_flow.rb:1331:10:1331:10 | b [element 2] : | | array_flow.rb:1328:9:1328:9 | [post] a [element 1] : | array_flow.rb:1333:10:1333:10 | a [element 1] : | | array_flow.rb:1328:9:1328:9 | [post] a [element 1] : | array_flow.rb:1333:10:1333:10 | a [element 1] : | | array_flow.rb:1328:9:1328:9 | a [element 2] : | array_flow.rb:1328:9:1328:21 | call to slice! [element 2] : | | array_flow.rb:1328:9:1328:9 | a [element 2] : | array_flow.rb:1328:9:1328:21 | call to slice! [element 2] : | | array_flow.rb:1328:9:1328:9 | a [element 4] : | array_flow.rb:1328:9:1328:9 | [post] a [element 1] : | | array_flow.rb:1328:9:1328:9 | a [element 4] : | array_flow.rb:1328:9:1328:9 | [post] a [element 1] : | -| array_flow.rb:1328:9:1328:21 | call to slice! [element 2] : | array_flow.rb:1331:10:1331:10 | b [element 2] : | -| array_flow.rb:1328:9:1328:21 | call to slice! [element 2] : | array_flow.rb:1331:10:1331:10 | b [element 2] : | +| array_flow.rb:1328:9:1328:21 | call to slice! [element 2] : | array_flow.rb:1328:5:1328:5 | b [element 2] : | +| array_flow.rb:1328:9:1328:21 | call to slice! [element 2] : | array_flow.rb:1328:5:1328:5 | b [element 2] : | | array_flow.rb:1331:10:1331:10 | b [element 2] : | array_flow.rb:1331:10:1331:13 | ...[...] | | array_flow.rb:1331:10:1331:10 | b [element 2] : | array_flow.rb:1331:10:1331:13 | ...[...] | | array_flow.rb:1333:10:1333:10 | a [element 1] : | array_flow.rb:1333:10:1333:13 | ...[...] | | array_flow.rb:1333:10:1333:10 | a [element 1] : | array_flow.rb:1333:10:1333:13 | ...[...] | -| array_flow.rb:1336:16:1336:28 | call to source : | array_flow.rb:1337:9:1337:9 | a [element 2] : | -| array_flow.rb:1336:16:1336:28 | call to source : | array_flow.rb:1337:9:1337:9 | a [element 2] : | -| array_flow.rb:1336:34:1336:46 | call to source : | array_flow.rb:1337:9:1337:9 | a [element 4] : | -| array_flow.rb:1336:34:1336:46 | call to source : | array_flow.rb:1337:9:1337:9 | a [element 4] : | +| array_flow.rb:1336:5:1336:5 | a [element 2] : | array_flow.rb:1337:9:1337:9 | a [element 2] : | +| array_flow.rb:1336:5:1336:5 | a [element 2] : | array_flow.rb:1337:9:1337:9 | a [element 2] : | +| array_flow.rb:1336:5:1336:5 | a [element 4] : | array_flow.rb:1337:9:1337:9 | a [element 4] : | +| array_flow.rb:1336:5:1336:5 | a [element 4] : | array_flow.rb:1337:9:1337:9 | a [element 4] : | +| array_flow.rb:1336:16:1336:28 | call to source : | array_flow.rb:1336:5:1336:5 | a [element 2] : | +| array_flow.rb:1336:16:1336:28 | call to source : | array_flow.rb:1336:5:1336:5 | a [element 2] : | +| array_flow.rb:1336:34:1336:46 | call to source : | array_flow.rb:1336:5:1336:5 | a [element 4] : | +| array_flow.rb:1336:34:1336:46 | call to source : | array_flow.rb:1336:5:1336:5 | a [element 4] : | +| array_flow.rb:1337:5:1337:5 | b [element] : | array_flow.rb:1338:10:1338:10 | b [element] : | +| array_flow.rb:1337:5:1337:5 | b [element] : | array_flow.rb:1338:10:1338:10 | b [element] : | +| array_flow.rb:1337:5:1337:5 | b [element] : | array_flow.rb:1339:10:1339:10 | b [element] : | +| array_flow.rb:1337:5:1337:5 | b [element] : | array_flow.rb:1339:10:1339:10 | b [element] : | +| array_flow.rb:1337:5:1337:5 | b [element] : | array_flow.rb:1340:10:1340:10 | b [element] : | +| array_flow.rb:1337:5:1337:5 | b [element] : | array_flow.rb:1340:10:1340:10 | b [element] : | | array_flow.rb:1337:9:1337:9 | [post] a [element] : | array_flow.rb:1341:10:1341:10 | a [element] : | | array_flow.rb:1337:9:1337:9 | [post] a [element] : | array_flow.rb:1341:10:1341:10 | a [element] : | | array_flow.rb:1337:9:1337:9 | [post] a [element] : | array_flow.rb:1342:10:1342:10 | a [element] : | @@ -2777,12 +3454,8 @@ edges | array_flow.rb:1337:9:1337:9 | a [element 4] : | array_flow.rb:1337:9:1337:9 | [post] a [element] : | | array_flow.rb:1337:9:1337:9 | a [element 4] : | array_flow.rb:1337:9:1337:21 | call to slice! [element] : | | array_flow.rb:1337:9:1337:9 | a [element 4] : | array_flow.rb:1337:9:1337:21 | call to slice! [element] : | -| array_flow.rb:1337:9:1337:21 | call to slice! [element] : | array_flow.rb:1338:10:1338:10 | b [element] : | -| array_flow.rb:1337:9:1337:21 | call to slice! [element] : | array_flow.rb:1338:10:1338:10 | b [element] : | -| array_flow.rb:1337:9:1337:21 | call to slice! [element] : | array_flow.rb:1339:10:1339:10 | b [element] : | -| array_flow.rb:1337:9:1337:21 | call to slice! [element] : | array_flow.rb:1339:10:1339:10 | b [element] : | -| array_flow.rb:1337:9:1337:21 | call to slice! [element] : | array_flow.rb:1340:10:1340:10 | b [element] : | -| array_flow.rb:1337:9:1337:21 | call to slice! [element] : | array_flow.rb:1340:10:1340:10 | b [element] : | +| array_flow.rb:1337:9:1337:21 | call to slice! [element] : | array_flow.rb:1337:5:1337:5 | b [element] : | +| array_flow.rb:1337:9:1337:21 | call to slice! [element] : | array_flow.rb:1337:5:1337:5 | b [element] : | | array_flow.rb:1338:10:1338:10 | b [element] : | array_flow.rb:1338:10:1338:13 | ...[...] | | array_flow.rb:1338:10:1338:10 | b [element] : | array_flow.rb:1338:10:1338:13 | ...[...] | | array_flow.rb:1339:10:1339:10 | b [element] : | array_flow.rb:1339:10:1339:13 | ...[...] | @@ -2795,20 +3468,26 @@ edges | array_flow.rb:1342:10:1342:10 | a [element] : | array_flow.rb:1342:10:1342:13 | ...[...] | | array_flow.rb:1343:10:1343:10 | a [element] : | array_flow.rb:1343:10:1343:13 | ...[...] | | array_flow.rb:1343:10:1343:10 | a [element] : | array_flow.rb:1343:10:1343:13 | ...[...] | -| array_flow.rb:1347:16:1347:26 | call to source : | array_flow.rb:1348:9:1348:9 | a [element 2] : | -| array_flow.rb:1347:16:1347:26 | call to source : | array_flow.rb:1348:9:1348:9 | a [element 2] : | +| array_flow.rb:1347:5:1347:5 | a [element 2] : | array_flow.rb:1348:9:1348:9 | a [element 2] : | +| array_flow.rb:1347:5:1347:5 | a [element 2] : | array_flow.rb:1348:9:1348:9 | a [element 2] : | +| array_flow.rb:1347:16:1347:26 | call to source : | array_flow.rb:1347:5:1347:5 | a [element 2] : | +| array_flow.rb:1347:16:1347:26 | call to source : | array_flow.rb:1347:5:1347:5 | a [element 2] : | | array_flow.rb:1348:9:1348:9 | a [element 2] : | array_flow.rb:1348:27:1348:27 | x : | | array_flow.rb:1348:9:1348:9 | a [element 2] : | array_flow.rb:1348:27:1348:27 | x : | | array_flow.rb:1348:27:1348:27 | x : | array_flow.rb:1349:14:1349:14 | x | | array_flow.rb:1348:27:1348:27 | x : | array_flow.rb:1349:14:1349:14 | x | -| array_flow.rb:1355:16:1355:26 | call to source : | array_flow.rb:1356:9:1356:9 | a [element 2] : | -| array_flow.rb:1355:16:1355:26 | call to source : | array_flow.rb:1356:9:1356:9 | a [element 2] : | +| array_flow.rb:1355:5:1355:5 | a [element 2] : | array_flow.rb:1356:9:1356:9 | a [element 2] : | +| array_flow.rb:1355:5:1355:5 | a [element 2] : | array_flow.rb:1356:9:1356:9 | a [element 2] : | +| array_flow.rb:1355:16:1355:26 | call to source : | array_flow.rb:1355:5:1355:5 | a [element 2] : | +| array_flow.rb:1355:16:1355:26 | call to source : | array_flow.rb:1355:5:1355:5 | a [element 2] : | | array_flow.rb:1356:9:1356:9 | a [element 2] : | array_flow.rb:1356:28:1356:28 | x : | | array_flow.rb:1356:9:1356:9 | a [element 2] : | array_flow.rb:1356:28:1356:28 | x : | | array_flow.rb:1356:28:1356:28 | x : | array_flow.rb:1357:14:1357:14 | x | | array_flow.rb:1356:28:1356:28 | x : | array_flow.rb:1357:14:1357:14 | x | -| array_flow.rb:1363:16:1363:26 | call to source : | array_flow.rb:1364:9:1364:9 | a [element 2] : | -| array_flow.rb:1363:16:1363:26 | call to source : | array_flow.rb:1364:9:1364:9 | a [element 2] : | +| array_flow.rb:1363:5:1363:5 | a [element 2] : | array_flow.rb:1364:9:1364:9 | a [element 2] : | +| array_flow.rb:1363:5:1363:5 | a [element 2] : | array_flow.rb:1364:9:1364:9 | a [element 2] : | +| array_flow.rb:1363:16:1363:26 | call to source : | array_flow.rb:1363:5:1363:5 | a [element 2] : | +| array_flow.rb:1363:16:1363:26 | call to source : | array_flow.rb:1363:5:1363:5 | a [element 2] : | | array_flow.rb:1364:9:1364:9 | a [element 2] : | array_flow.rb:1364:26:1364:26 | x : | | array_flow.rb:1364:9:1364:9 | a [element 2] : | array_flow.rb:1364:26:1364:26 | x : | | array_flow.rb:1364:9:1364:9 | a [element 2] : | array_flow.rb:1364:29:1364:29 | y : | @@ -2817,30 +3496,36 @@ edges | array_flow.rb:1364:26:1364:26 | x : | array_flow.rb:1365:14:1365:14 | x | | array_flow.rb:1364:29:1364:29 | y : | array_flow.rb:1366:14:1366:14 | y | | array_flow.rb:1364:29:1364:29 | y : | array_flow.rb:1366:14:1366:14 | y | -| array_flow.rb:1371:16:1371:26 | call to source : | array_flow.rb:1372:9:1372:9 | a [element 2] : | -| array_flow.rb:1371:16:1371:26 | call to source : | array_flow.rb:1372:9:1372:9 | a [element 2] : | -| array_flow.rb:1371:16:1371:26 | call to source : | array_flow.rb:1375:9:1375:9 | a [element 2] : | -| array_flow.rb:1371:16:1371:26 | call to source : | array_flow.rb:1375:9:1375:9 | a [element 2] : | +| array_flow.rb:1371:5:1371:5 | a [element 2] : | array_flow.rb:1372:9:1372:9 | a [element 2] : | +| array_flow.rb:1371:5:1371:5 | a [element 2] : | array_flow.rb:1372:9:1372:9 | a [element 2] : | +| array_flow.rb:1371:5:1371:5 | a [element 2] : | array_flow.rb:1375:9:1375:9 | a [element 2] : | +| array_flow.rb:1371:5:1371:5 | a [element 2] : | array_flow.rb:1375:9:1375:9 | a [element 2] : | +| array_flow.rb:1371:16:1371:26 | call to source : | array_flow.rb:1371:5:1371:5 | a [element 2] : | +| array_flow.rb:1371:16:1371:26 | call to source : | array_flow.rb:1371:5:1371:5 | a [element 2] : | +| array_flow.rb:1372:5:1372:5 | b [element] : | array_flow.rb:1373:10:1373:10 | b [element] : | +| array_flow.rb:1372:5:1372:5 | b [element] : | array_flow.rb:1373:10:1373:10 | b [element] : | +| array_flow.rb:1372:5:1372:5 | b [element] : | array_flow.rb:1374:10:1374:10 | b [element] : | +| array_flow.rb:1372:5:1372:5 | b [element] : | array_flow.rb:1374:10:1374:10 | b [element] : | | array_flow.rb:1372:9:1372:9 | a [element 2] : | array_flow.rb:1372:9:1372:14 | call to sort [element] : | | array_flow.rb:1372:9:1372:9 | a [element 2] : | array_flow.rb:1372:9:1372:14 | call to sort [element] : | -| array_flow.rb:1372:9:1372:14 | call to sort [element] : | array_flow.rb:1373:10:1373:10 | b [element] : | -| array_flow.rb:1372:9:1372:14 | call to sort [element] : | array_flow.rb:1373:10:1373:10 | b [element] : | -| array_flow.rb:1372:9:1372:14 | call to sort [element] : | array_flow.rb:1374:10:1374:10 | b [element] : | -| array_flow.rb:1372:9:1372:14 | call to sort [element] : | array_flow.rb:1374:10:1374:10 | b [element] : | +| array_flow.rb:1372:9:1372:14 | call to sort [element] : | array_flow.rb:1372:5:1372:5 | b [element] : | +| array_flow.rb:1372:9:1372:14 | call to sort [element] : | array_flow.rb:1372:5:1372:5 | b [element] : | | array_flow.rb:1373:10:1373:10 | b [element] : | array_flow.rb:1373:10:1373:13 | ...[...] | | array_flow.rb:1373:10:1373:10 | b [element] : | array_flow.rb:1373:10:1373:13 | ...[...] | | array_flow.rb:1374:10:1374:10 | b [element] : | array_flow.rb:1374:10:1374:13 | ...[...] | | array_flow.rb:1374:10:1374:10 | b [element] : | array_flow.rb:1374:10:1374:13 | ...[...] | +| array_flow.rb:1375:5:1375:5 | c [element] : | array_flow.rb:1380:10:1380:10 | c [element] : | +| array_flow.rb:1375:5:1375:5 | c [element] : | array_flow.rb:1380:10:1380:10 | c [element] : | +| array_flow.rb:1375:5:1375:5 | c [element] : | array_flow.rb:1381:10:1381:10 | c [element] : | +| array_flow.rb:1375:5:1375:5 | c [element] : | array_flow.rb:1381:10:1381:10 | c [element] : | | array_flow.rb:1375:9:1375:9 | a [element 2] : | array_flow.rb:1375:9:1379:7 | call to sort [element] : | | array_flow.rb:1375:9:1375:9 | a [element 2] : | array_flow.rb:1375:9:1379:7 | call to sort [element] : | | array_flow.rb:1375:9:1375:9 | a [element 2] : | array_flow.rb:1375:20:1375:20 | x : | | array_flow.rb:1375:9:1375:9 | a [element 2] : | array_flow.rb:1375:20:1375:20 | x : | | array_flow.rb:1375:9:1375:9 | a [element 2] : | array_flow.rb:1375:23:1375:23 | y : | | array_flow.rb:1375:9:1375:9 | a [element 2] : | array_flow.rb:1375:23:1375:23 | y : | -| array_flow.rb:1375:9:1379:7 | call to sort [element] : | array_flow.rb:1380:10:1380:10 | c [element] : | -| array_flow.rb:1375:9:1379:7 | call to sort [element] : | array_flow.rb:1380:10:1380:10 | c [element] : | -| array_flow.rb:1375:9:1379:7 | call to sort [element] : | array_flow.rb:1381:10:1381:10 | c [element] : | -| array_flow.rb:1375:9:1379:7 | call to sort [element] : | array_flow.rb:1381:10:1381:10 | c [element] : | +| array_flow.rb:1375:9:1379:7 | call to sort [element] : | array_flow.rb:1375:5:1375:5 | c [element] : | +| array_flow.rb:1375:9:1379:7 | call to sort [element] : | array_flow.rb:1375:5:1375:5 | c [element] : | | array_flow.rb:1375:20:1375:20 | x : | array_flow.rb:1376:14:1376:14 | x | | array_flow.rb:1375:20:1375:20 | x : | array_flow.rb:1376:14:1376:14 | x | | array_flow.rb:1375:23:1375:23 | y : | array_flow.rb:1377:14:1377:14 | y | @@ -2849,8 +3534,14 @@ edges | array_flow.rb:1380:10:1380:10 | c [element] : | array_flow.rb:1380:10:1380:13 | ...[...] | | array_flow.rb:1381:10:1381:10 | c [element] : | array_flow.rb:1381:10:1381:13 | ...[...] | | array_flow.rb:1381:10:1381:10 | c [element] : | array_flow.rb:1381:10:1381:13 | ...[...] | -| array_flow.rb:1385:16:1385:26 | call to source : | array_flow.rb:1386:9:1386:9 | a [element 2] : | -| array_flow.rb:1385:16:1385:26 | call to source : | array_flow.rb:1386:9:1386:9 | a [element 2] : | +| array_flow.rb:1385:5:1385:5 | a [element 2] : | array_flow.rb:1386:9:1386:9 | a [element 2] : | +| array_flow.rb:1385:5:1385:5 | a [element 2] : | array_flow.rb:1386:9:1386:9 | a [element 2] : | +| array_flow.rb:1385:16:1385:26 | call to source : | array_flow.rb:1385:5:1385:5 | a [element 2] : | +| array_flow.rb:1385:16:1385:26 | call to source : | array_flow.rb:1385:5:1385:5 | a [element 2] : | +| array_flow.rb:1386:5:1386:5 | b [element] : | array_flow.rb:1387:10:1387:10 | b [element] : | +| array_flow.rb:1386:5:1386:5 | b [element] : | array_flow.rb:1387:10:1387:10 | b [element] : | +| array_flow.rb:1386:5:1386:5 | b [element] : | array_flow.rb:1388:10:1388:10 | b [element] : | +| array_flow.rb:1386:5:1386:5 | b [element] : | array_flow.rb:1388:10:1388:10 | b [element] : | | array_flow.rb:1386:9:1386:9 | [post] a [element] : | array_flow.rb:1389:10:1389:10 | a [element] : | | array_flow.rb:1386:9:1386:9 | [post] a [element] : | array_flow.rb:1389:10:1389:10 | a [element] : | | array_flow.rb:1386:9:1386:9 | [post] a [element] : | array_flow.rb:1390:10:1390:10 | a [element] : | @@ -2859,10 +3550,8 @@ edges | array_flow.rb:1386:9:1386:9 | a [element 2] : | array_flow.rb:1386:9:1386:9 | [post] a [element] : | | array_flow.rb:1386:9:1386:9 | a [element 2] : | array_flow.rb:1386:9:1386:15 | call to sort! [element] : | | array_flow.rb:1386:9:1386:9 | a [element 2] : | array_flow.rb:1386:9:1386:15 | call to sort! [element] : | -| array_flow.rb:1386:9:1386:15 | call to sort! [element] : | array_flow.rb:1387:10:1387:10 | b [element] : | -| array_flow.rb:1386:9:1386:15 | call to sort! [element] : | array_flow.rb:1387:10:1387:10 | b [element] : | -| array_flow.rb:1386:9:1386:15 | call to sort! [element] : | array_flow.rb:1388:10:1388:10 | b [element] : | -| array_flow.rb:1386:9:1386:15 | call to sort! [element] : | array_flow.rb:1388:10:1388:10 | b [element] : | +| array_flow.rb:1386:9:1386:15 | call to sort! [element] : | array_flow.rb:1386:5:1386:5 | b [element] : | +| array_flow.rb:1386:9:1386:15 | call to sort! [element] : | array_flow.rb:1386:5:1386:5 | b [element] : | | array_flow.rb:1387:10:1387:10 | b [element] : | array_flow.rb:1387:10:1387:13 | ...[...] | | array_flow.rb:1387:10:1387:10 | b [element] : | array_flow.rb:1387:10:1387:13 | ...[...] | | array_flow.rb:1388:10:1388:10 | b [element] : | array_flow.rb:1388:10:1388:13 | ...[...] | @@ -2871,8 +3560,14 @@ edges | array_flow.rb:1389:10:1389:10 | a [element] : | array_flow.rb:1389:10:1389:13 | ...[...] | | array_flow.rb:1390:10:1390:10 | a [element] : | array_flow.rb:1390:10:1390:13 | ...[...] | | array_flow.rb:1390:10:1390:10 | a [element] : | array_flow.rb:1390:10:1390:13 | ...[...] | -| array_flow.rb:1392:16:1392:26 | call to source : | array_flow.rb:1393:9:1393:9 | a [element 2] : | -| array_flow.rb:1392:16:1392:26 | call to source : | array_flow.rb:1393:9:1393:9 | a [element 2] : | +| array_flow.rb:1392:5:1392:5 | a [element 2] : | array_flow.rb:1393:9:1393:9 | a [element 2] : | +| array_flow.rb:1392:5:1392:5 | a [element 2] : | array_flow.rb:1393:9:1393:9 | a [element 2] : | +| array_flow.rb:1392:16:1392:26 | call to source : | array_flow.rb:1392:5:1392:5 | a [element 2] : | +| array_flow.rb:1392:16:1392:26 | call to source : | array_flow.rb:1392:5:1392:5 | a [element 2] : | +| array_flow.rb:1393:5:1393:5 | b [element] : | array_flow.rb:1398:10:1398:10 | b [element] : | +| array_flow.rb:1393:5:1393:5 | b [element] : | array_flow.rb:1398:10:1398:10 | b [element] : | +| array_flow.rb:1393:5:1393:5 | b [element] : | array_flow.rb:1399:10:1399:10 | b [element] : | +| array_flow.rb:1393:5:1393:5 | b [element] : | array_flow.rb:1399:10:1399:10 | b [element] : | | array_flow.rb:1393:9:1393:9 | [post] a [element] : | array_flow.rb:1400:10:1400:10 | a [element] : | | array_flow.rb:1393:9:1393:9 | [post] a [element] : | array_flow.rb:1400:10:1400:10 | a [element] : | | array_flow.rb:1393:9:1393:9 | [post] a [element] : | array_flow.rb:1401:10:1401:10 | a [element] : | @@ -2885,10 +3580,8 @@ edges | array_flow.rb:1393:9:1393:9 | a [element 2] : | array_flow.rb:1393:21:1393:21 | x : | | array_flow.rb:1393:9:1393:9 | a [element 2] : | array_flow.rb:1393:24:1393:24 | y : | | array_flow.rb:1393:9:1393:9 | a [element 2] : | array_flow.rb:1393:24:1393:24 | y : | -| array_flow.rb:1393:9:1397:7 | call to sort! [element] : | array_flow.rb:1398:10:1398:10 | b [element] : | -| array_flow.rb:1393:9:1397:7 | call to sort! [element] : | array_flow.rb:1398:10:1398:10 | b [element] : | -| array_flow.rb:1393:9:1397:7 | call to sort! [element] : | array_flow.rb:1399:10:1399:10 | b [element] : | -| array_flow.rb:1393:9:1397:7 | call to sort! [element] : | array_flow.rb:1399:10:1399:10 | b [element] : | +| array_flow.rb:1393:9:1397:7 | call to sort! [element] : | array_flow.rb:1393:5:1393:5 | b [element] : | +| array_flow.rb:1393:9:1397:7 | call to sort! [element] : | array_flow.rb:1393:5:1393:5 | b [element] : | | array_flow.rb:1393:21:1393:21 | x : | array_flow.rb:1394:14:1394:14 | x | | array_flow.rb:1393:21:1393:21 | x : | array_flow.rb:1394:14:1394:14 | x | | array_flow.rb:1393:24:1393:24 | y : | array_flow.rb:1395:14:1395:14 | y | @@ -2901,24 +3594,34 @@ edges | array_flow.rb:1400:10:1400:10 | a [element] : | array_flow.rb:1400:10:1400:13 | ...[...] | | array_flow.rb:1401:10:1401:10 | a [element] : | array_flow.rb:1401:10:1401:13 | ...[...] | | array_flow.rb:1401:10:1401:10 | a [element] : | array_flow.rb:1401:10:1401:13 | ...[...] | -| array_flow.rb:1405:16:1405:26 | call to source : | array_flow.rb:1406:9:1406:9 | a [element 2] : | -| array_flow.rb:1405:16:1405:26 | call to source : | array_flow.rb:1406:9:1406:9 | a [element 2] : | +| array_flow.rb:1405:5:1405:5 | a [element 2] : | array_flow.rb:1406:9:1406:9 | a [element 2] : | +| array_flow.rb:1405:5:1405:5 | a [element 2] : | array_flow.rb:1406:9:1406:9 | a [element 2] : | +| array_flow.rb:1405:16:1405:26 | call to source : | array_flow.rb:1405:5:1405:5 | a [element 2] : | +| array_flow.rb:1405:16:1405:26 | call to source : | array_flow.rb:1405:5:1405:5 | a [element 2] : | +| array_flow.rb:1406:5:1406:5 | b [element] : | array_flow.rb:1410:10:1410:10 | b [element] : | +| array_flow.rb:1406:5:1406:5 | b [element] : | array_flow.rb:1410:10:1410:10 | b [element] : | +| array_flow.rb:1406:5:1406:5 | b [element] : | array_flow.rb:1411:10:1411:10 | b [element] : | +| array_flow.rb:1406:5:1406:5 | b [element] : | array_flow.rb:1411:10:1411:10 | b [element] : | | array_flow.rb:1406:9:1406:9 | a [element 2] : | array_flow.rb:1406:9:1409:7 | call to sort_by [element] : | | array_flow.rb:1406:9:1406:9 | a [element 2] : | array_flow.rb:1406:9:1409:7 | call to sort_by [element] : | | array_flow.rb:1406:9:1406:9 | a [element 2] : | array_flow.rb:1406:23:1406:23 | x : | | array_flow.rb:1406:9:1406:9 | a [element 2] : | array_flow.rb:1406:23:1406:23 | x : | -| array_flow.rb:1406:9:1409:7 | call to sort_by [element] : | array_flow.rb:1410:10:1410:10 | b [element] : | -| array_flow.rb:1406:9:1409:7 | call to sort_by [element] : | array_flow.rb:1410:10:1410:10 | b [element] : | -| array_flow.rb:1406:9:1409:7 | call to sort_by [element] : | array_flow.rb:1411:10:1411:10 | b [element] : | -| array_flow.rb:1406:9:1409:7 | call to sort_by [element] : | array_flow.rb:1411:10:1411:10 | b [element] : | +| array_flow.rb:1406:9:1409:7 | call to sort_by [element] : | array_flow.rb:1406:5:1406:5 | b [element] : | +| array_flow.rb:1406:9:1409:7 | call to sort_by [element] : | array_flow.rb:1406:5:1406:5 | b [element] : | | array_flow.rb:1406:23:1406:23 | x : | array_flow.rb:1407:14:1407:14 | x | | array_flow.rb:1406:23:1406:23 | x : | array_flow.rb:1407:14:1407:14 | x | | array_flow.rb:1410:10:1410:10 | b [element] : | array_flow.rb:1410:10:1410:13 | ...[...] | | array_flow.rb:1410:10:1410:10 | b [element] : | array_flow.rb:1410:10:1410:13 | ...[...] | | array_flow.rb:1411:10:1411:10 | b [element] : | array_flow.rb:1411:10:1411:13 | ...[...] | | array_flow.rb:1411:10:1411:10 | b [element] : | array_flow.rb:1411:10:1411:13 | ...[...] | -| array_flow.rb:1415:16:1415:26 | call to source : | array_flow.rb:1416:9:1416:9 | a [element 2] : | -| array_flow.rb:1415:16:1415:26 | call to source : | array_flow.rb:1416:9:1416:9 | a [element 2] : | +| array_flow.rb:1415:5:1415:5 | a [element 2] : | array_flow.rb:1416:9:1416:9 | a [element 2] : | +| array_flow.rb:1415:5:1415:5 | a [element 2] : | array_flow.rb:1416:9:1416:9 | a [element 2] : | +| array_flow.rb:1415:16:1415:26 | call to source : | array_flow.rb:1415:5:1415:5 | a [element 2] : | +| array_flow.rb:1415:16:1415:26 | call to source : | array_flow.rb:1415:5:1415:5 | a [element 2] : | +| array_flow.rb:1416:5:1416:5 | b [element] : | array_flow.rb:1422:10:1422:10 | b [element] : | +| array_flow.rb:1416:5:1416:5 | b [element] : | array_flow.rb:1422:10:1422:10 | b [element] : | +| array_flow.rb:1416:5:1416:5 | b [element] : | array_flow.rb:1423:10:1423:10 | b [element] : | +| array_flow.rb:1416:5:1416:5 | b [element] : | array_flow.rb:1423:10:1423:10 | b [element] : | | array_flow.rb:1416:9:1416:9 | [post] a [element] : | array_flow.rb:1420:10:1420:10 | a [element] : | | array_flow.rb:1416:9:1416:9 | [post] a [element] : | array_flow.rb:1420:10:1420:10 | a [element] : | | array_flow.rb:1416:9:1416:9 | [post] a [element] : | array_flow.rb:1421:10:1421:10 | a [element] : | @@ -2929,10 +3632,8 @@ edges | array_flow.rb:1416:9:1416:9 | a [element 2] : | array_flow.rb:1416:9:1419:7 | call to sort_by! [element] : | | array_flow.rb:1416:9:1416:9 | a [element 2] : | array_flow.rb:1416:24:1416:24 | x : | | array_flow.rb:1416:9:1416:9 | a [element 2] : | array_flow.rb:1416:24:1416:24 | x : | -| array_flow.rb:1416:9:1419:7 | call to sort_by! [element] : | array_flow.rb:1422:10:1422:10 | b [element] : | -| array_flow.rb:1416:9:1419:7 | call to sort_by! [element] : | array_flow.rb:1422:10:1422:10 | b [element] : | -| array_flow.rb:1416:9:1419:7 | call to sort_by! [element] : | array_flow.rb:1423:10:1423:10 | b [element] : | -| array_flow.rb:1416:9:1419:7 | call to sort_by! [element] : | array_flow.rb:1423:10:1423:10 | b [element] : | +| array_flow.rb:1416:9:1419:7 | call to sort_by! [element] : | array_flow.rb:1416:5:1416:5 | b [element] : | +| array_flow.rb:1416:9:1419:7 | call to sort_by! [element] : | array_flow.rb:1416:5:1416:5 | b [element] : | | array_flow.rb:1416:24:1416:24 | x : | array_flow.rb:1417:14:1417:14 | x | | array_flow.rb:1416:24:1416:24 | x : | array_flow.rb:1417:14:1417:14 | x | | array_flow.rb:1420:10:1420:10 | a [element] : | array_flow.rb:1420:10:1420:13 | ...[...] | @@ -2943,58 +3644,74 @@ edges | array_flow.rb:1422:10:1422:10 | b [element] : | array_flow.rb:1422:10:1422:13 | ...[...] | | array_flow.rb:1423:10:1423:10 | b [element] : | array_flow.rb:1423:10:1423:13 | ...[...] | | array_flow.rb:1423:10:1423:10 | b [element] : | array_flow.rb:1423:10:1423:13 | ...[...] | -| array_flow.rb:1427:16:1427:26 | call to source : | array_flow.rb:1428:9:1428:9 | a [element 2] : | -| array_flow.rb:1427:16:1427:26 | call to source : | array_flow.rb:1428:9:1428:9 | a [element 2] : | +| array_flow.rb:1427:5:1427:5 | a [element 2] : | array_flow.rb:1428:9:1428:9 | a [element 2] : | +| array_flow.rb:1427:5:1427:5 | a [element 2] : | array_flow.rb:1428:9:1428:9 | a [element 2] : | +| array_flow.rb:1427:16:1427:26 | call to source : | array_flow.rb:1427:5:1427:5 | a [element 2] : | +| array_flow.rb:1427:16:1427:26 | call to source : | array_flow.rb:1427:5:1427:5 | a [element 2] : | | array_flow.rb:1428:9:1428:9 | a [element 2] : | array_flow.rb:1428:19:1428:19 | x : | | array_flow.rb:1428:9:1428:9 | a [element 2] : | array_flow.rb:1428:19:1428:19 | x : | | array_flow.rb:1428:19:1428:19 | x : | array_flow.rb:1429:14:1429:14 | x | | array_flow.rb:1428:19:1428:19 | x : | array_flow.rb:1429:14:1429:14 | x | -| array_flow.rb:1435:16:1435:28 | call to source : | array_flow.rb:1436:9:1436:9 | a [element 2] : | -| array_flow.rb:1435:16:1435:28 | call to source : | array_flow.rb:1436:9:1436:9 | a [element 2] : | -| array_flow.rb:1435:16:1435:28 | call to source : | array_flow.rb:1441:9:1441:9 | a [element 2] : | -| array_flow.rb:1435:16:1435:28 | call to source : | array_flow.rb:1441:9:1441:9 | a [element 2] : | -| array_flow.rb:1435:16:1435:28 | call to source : | array_flow.rb:1447:9:1447:9 | a [element 2] : | -| array_flow.rb:1435:16:1435:28 | call to source : | array_flow.rb:1447:9:1447:9 | a [element 2] : | -| array_flow.rb:1435:16:1435:28 | call to source : | array_flow.rb:1454:9:1454:9 | a [element 2] : | -| array_flow.rb:1435:16:1435:28 | call to source : | array_flow.rb:1454:9:1454:9 | a [element 2] : | -| array_flow.rb:1435:31:1435:43 | call to source : | array_flow.rb:1436:9:1436:9 | a [element 3] : | -| array_flow.rb:1435:31:1435:43 | call to source : | array_flow.rb:1436:9:1436:9 | a [element 3] : | -| array_flow.rb:1435:31:1435:43 | call to source : | array_flow.rb:1447:9:1447:9 | a [element 3] : | -| array_flow.rb:1435:31:1435:43 | call to source : | array_flow.rb:1447:9:1447:9 | a [element 3] : | +| array_flow.rb:1435:5:1435:5 | a [element 2] : | array_flow.rb:1436:9:1436:9 | a [element 2] : | +| array_flow.rb:1435:5:1435:5 | a [element 2] : | array_flow.rb:1436:9:1436:9 | a [element 2] : | +| array_flow.rb:1435:5:1435:5 | a [element 2] : | array_flow.rb:1441:9:1441:9 | a [element 2] : | +| array_flow.rb:1435:5:1435:5 | a [element 2] : | array_flow.rb:1441:9:1441:9 | a [element 2] : | +| array_flow.rb:1435:5:1435:5 | a [element 2] : | array_flow.rb:1447:9:1447:9 | a [element 2] : | +| array_flow.rb:1435:5:1435:5 | a [element 2] : | array_flow.rb:1447:9:1447:9 | a [element 2] : | +| array_flow.rb:1435:5:1435:5 | a [element 2] : | array_flow.rb:1454:9:1454:9 | a [element 2] : | +| array_flow.rb:1435:5:1435:5 | a [element 2] : | array_flow.rb:1454:9:1454:9 | a [element 2] : | +| array_flow.rb:1435:5:1435:5 | a [element 3] : | array_flow.rb:1436:9:1436:9 | a [element 3] : | +| array_flow.rb:1435:5:1435:5 | a [element 3] : | array_flow.rb:1436:9:1436:9 | a [element 3] : | +| array_flow.rb:1435:5:1435:5 | a [element 3] : | array_flow.rb:1447:9:1447:9 | a [element 3] : | +| array_flow.rb:1435:5:1435:5 | a [element 3] : | array_flow.rb:1447:9:1447:9 | a [element 3] : | +| array_flow.rb:1435:16:1435:28 | call to source : | array_flow.rb:1435:5:1435:5 | a [element 2] : | +| array_flow.rb:1435:16:1435:28 | call to source : | array_flow.rb:1435:5:1435:5 | a [element 2] : | +| array_flow.rb:1435:31:1435:43 | call to source : | array_flow.rb:1435:5:1435:5 | a [element 3] : | +| array_flow.rb:1435:31:1435:43 | call to source : | array_flow.rb:1435:5:1435:5 | a [element 3] : | +| array_flow.rb:1436:5:1436:5 | b [element 2] : | array_flow.rb:1439:10:1439:10 | b [element 2] : | +| array_flow.rb:1436:5:1436:5 | b [element 2] : | array_flow.rb:1439:10:1439:10 | b [element 2] : | +| array_flow.rb:1436:5:1436:5 | b [element 3] : | array_flow.rb:1440:10:1440:10 | b [element 3] : | +| array_flow.rb:1436:5:1436:5 | b [element 3] : | array_flow.rb:1440:10:1440:10 | b [element 3] : | | array_flow.rb:1436:9:1436:9 | a [element 2] : | array_flow.rb:1436:9:1436:17 | call to take [element 2] : | | array_flow.rb:1436:9:1436:9 | a [element 2] : | array_flow.rb:1436:9:1436:17 | call to take [element 2] : | | array_flow.rb:1436:9:1436:9 | a [element 3] : | array_flow.rb:1436:9:1436:17 | call to take [element 3] : | | array_flow.rb:1436:9:1436:9 | a [element 3] : | array_flow.rb:1436:9:1436:17 | call to take [element 3] : | -| array_flow.rb:1436:9:1436:17 | call to take [element 2] : | array_flow.rb:1439:10:1439:10 | b [element 2] : | -| array_flow.rb:1436:9:1436:17 | call to take [element 2] : | array_flow.rb:1439:10:1439:10 | b [element 2] : | -| array_flow.rb:1436:9:1436:17 | call to take [element 3] : | array_flow.rb:1440:10:1440:10 | b [element 3] : | -| array_flow.rb:1436:9:1436:17 | call to take [element 3] : | array_flow.rb:1440:10:1440:10 | b [element 3] : | +| array_flow.rb:1436:9:1436:17 | call to take [element 2] : | array_flow.rb:1436:5:1436:5 | b [element 2] : | +| array_flow.rb:1436:9:1436:17 | call to take [element 2] : | array_flow.rb:1436:5:1436:5 | b [element 2] : | +| array_flow.rb:1436:9:1436:17 | call to take [element 3] : | array_flow.rb:1436:5:1436:5 | b [element 3] : | +| array_flow.rb:1436:9:1436:17 | call to take [element 3] : | array_flow.rb:1436:5:1436:5 | b [element 3] : | | array_flow.rb:1439:10:1439:10 | b [element 2] : | array_flow.rb:1439:10:1439:13 | ...[...] | | array_flow.rb:1439:10:1439:10 | b [element 2] : | array_flow.rb:1439:10:1439:13 | ...[...] | | array_flow.rb:1440:10:1440:10 | b [element 3] : | array_flow.rb:1440:10:1440:13 | ...[...] | | array_flow.rb:1440:10:1440:10 | b [element 3] : | array_flow.rb:1440:10:1440:13 | ...[...] | +| array_flow.rb:1441:5:1441:5 | b [element 2] : | array_flow.rb:1444:10:1444:10 | b [element 2] : | +| array_flow.rb:1441:5:1441:5 | b [element 2] : | array_flow.rb:1444:10:1444:10 | b [element 2] : | +| array_flow.rb:1441:5:1441:5 | b [element 2] : | array_flow.rb:1446:10:1446:10 | b [element 2] : | +| array_flow.rb:1441:5:1441:5 | b [element 2] : | array_flow.rb:1446:10:1446:10 | b [element 2] : | | array_flow.rb:1441:9:1441:9 | a [element 2] : | array_flow.rb:1441:9:1441:17 | call to take [element 2] : | | array_flow.rb:1441:9:1441:9 | a [element 2] : | array_flow.rb:1441:9:1441:17 | call to take [element 2] : | -| array_flow.rb:1441:9:1441:17 | call to take [element 2] : | array_flow.rb:1444:10:1444:10 | b [element 2] : | -| array_flow.rb:1441:9:1441:17 | call to take [element 2] : | array_flow.rb:1444:10:1444:10 | b [element 2] : | -| array_flow.rb:1441:9:1441:17 | call to take [element 2] : | array_flow.rb:1446:10:1446:10 | b [element 2] : | -| array_flow.rb:1441:9:1441:17 | call to take [element 2] : | array_flow.rb:1446:10:1446:10 | b [element 2] : | +| array_flow.rb:1441:9:1441:17 | call to take [element 2] : | array_flow.rb:1441:5:1441:5 | b [element 2] : | +| array_flow.rb:1441:9:1441:17 | call to take [element 2] : | array_flow.rb:1441:5:1441:5 | b [element 2] : | | array_flow.rb:1444:10:1444:10 | b [element 2] : | array_flow.rb:1444:10:1444:13 | ...[...] | | array_flow.rb:1444:10:1444:10 | b [element 2] : | array_flow.rb:1444:10:1444:13 | ...[...] | | array_flow.rb:1446:10:1446:10 | b [element 2] : | array_flow.rb:1446:10:1446:13 | ...[...] | | array_flow.rb:1446:10:1446:10 | b [element 2] : | array_flow.rb:1446:10:1446:13 | ...[...] | +| array_flow.rb:1447:5:1447:5 | b [element 2] : | array_flow.rb:1450:10:1450:10 | b [element 2] : | +| array_flow.rb:1447:5:1447:5 | b [element 2] : | array_flow.rb:1450:10:1450:10 | b [element 2] : | +| array_flow.rb:1447:5:1447:5 | b [element 2] : | array_flow.rb:1452:10:1452:10 | b [element 2] : | +| array_flow.rb:1447:5:1447:5 | b [element 2] : | array_flow.rb:1452:10:1452:10 | b [element 2] : | +| array_flow.rb:1447:5:1447:5 | b [element 3] : | array_flow.rb:1451:10:1451:10 | b [element 3] : | +| array_flow.rb:1447:5:1447:5 | b [element 3] : | array_flow.rb:1451:10:1451:10 | b [element 3] : | +| array_flow.rb:1447:5:1447:5 | b [element 3] : | array_flow.rb:1452:10:1452:10 | b [element 3] : | +| array_flow.rb:1447:5:1447:5 | b [element 3] : | array_flow.rb:1452:10:1452:10 | b [element 3] : | | array_flow.rb:1447:9:1447:9 | a [element 2] : | array_flow.rb:1447:9:1447:19 | call to take [element 2] : | | array_flow.rb:1447:9:1447:9 | a [element 2] : | array_flow.rb:1447:9:1447:19 | call to take [element 2] : | | array_flow.rb:1447:9:1447:9 | a [element 3] : | array_flow.rb:1447:9:1447:19 | call to take [element 3] : | | array_flow.rb:1447:9:1447:9 | a [element 3] : | array_flow.rb:1447:9:1447:19 | call to take [element 3] : | -| array_flow.rb:1447:9:1447:19 | call to take [element 2] : | array_flow.rb:1450:10:1450:10 | b [element 2] : | -| array_flow.rb:1447:9:1447:19 | call to take [element 2] : | array_flow.rb:1450:10:1450:10 | b [element 2] : | -| array_flow.rb:1447:9:1447:19 | call to take [element 2] : | array_flow.rb:1452:10:1452:10 | b [element 2] : | -| array_flow.rb:1447:9:1447:19 | call to take [element 2] : | array_flow.rb:1452:10:1452:10 | b [element 2] : | -| array_flow.rb:1447:9:1447:19 | call to take [element 3] : | array_flow.rb:1451:10:1451:10 | b [element 3] : | -| array_flow.rb:1447:9:1447:19 | call to take [element 3] : | array_flow.rb:1451:10:1451:10 | b [element 3] : | -| array_flow.rb:1447:9:1447:19 | call to take [element 3] : | array_flow.rb:1452:10:1452:10 | b [element 3] : | -| array_flow.rb:1447:9:1447:19 | call to take [element 3] : | array_flow.rb:1452:10:1452:10 | b [element 3] : | +| array_flow.rb:1447:9:1447:19 | call to take [element 2] : | array_flow.rb:1447:5:1447:5 | b [element 2] : | +| array_flow.rb:1447:9:1447:19 | call to take [element 2] : | array_flow.rb:1447:5:1447:5 | b [element 2] : | +| array_flow.rb:1447:9:1447:19 | call to take [element 3] : | array_flow.rb:1447:5:1447:5 | b [element 3] : | +| array_flow.rb:1447:9:1447:19 | call to take [element 3] : | array_flow.rb:1447:5:1447:5 | b [element 3] : | | array_flow.rb:1450:10:1450:10 | b [element 2] : | array_flow.rb:1450:10:1450:13 | ...[...] | | array_flow.rb:1450:10:1450:10 | b [element 2] : | array_flow.rb:1450:10:1450:13 | ...[...] | | array_flow.rb:1451:10:1451:10 | b [element 3] : | array_flow.rb:1451:10:1451:13 | ...[...] | @@ -3007,64 +3724,92 @@ edges | array_flow.rb:1453:5:1453:5 | [post] a [element] : | array_flow.rb:1454:9:1454:9 | a [element] : | | array_flow.rb:1453:12:1453:24 | call to source : | array_flow.rb:1453:5:1453:5 | [post] a [element] : | | array_flow.rb:1453:12:1453:24 | call to source : | array_flow.rb:1453:5:1453:5 | [post] a [element] : | +| array_flow.rb:1454:5:1454:5 | b [element 2] : | array_flow.rb:1455:10:1455:10 | b [element 2] : | +| array_flow.rb:1454:5:1454:5 | b [element 2] : | array_flow.rb:1455:10:1455:10 | b [element 2] : | +| array_flow.rb:1454:5:1454:5 | b [element] : | array_flow.rb:1455:10:1455:10 | b [element] : | +| array_flow.rb:1454:5:1454:5 | b [element] : | array_flow.rb:1455:10:1455:10 | b [element] : | | array_flow.rb:1454:9:1454:9 | a [element 2] : | array_flow.rb:1454:9:1454:17 | call to take [element 2] : | | array_flow.rb:1454:9:1454:9 | a [element 2] : | array_flow.rb:1454:9:1454:17 | call to take [element 2] : | | array_flow.rb:1454:9:1454:9 | a [element] : | array_flow.rb:1454:9:1454:17 | call to take [element] : | | array_flow.rb:1454:9:1454:9 | a [element] : | array_flow.rb:1454:9:1454:17 | call to take [element] : | -| array_flow.rb:1454:9:1454:17 | call to take [element 2] : | array_flow.rb:1455:10:1455:10 | b [element 2] : | -| array_flow.rb:1454:9:1454:17 | call to take [element 2] : | array_flow.rb:1455:10:1455:10 | b [element 2] : | -| array_flow.rb:1454:9:1454:17 | call to take [element] : | array_flow.rb:1455:10:1455:10 | b [element] : | -| array_flow.rb:1454:9:1454:17 | call to take [element] : | array_flow.rb:1455:10:1455:10 | b [element] : | +| array_flow.rb:1454:9:1454:17 | call to take [element 2] : | array_flow.rb:1454:5:1454:5 | b [element 2] : | +| array_flow.rb:1454:9:1454:17 | call to take [element 2] : | array_flow.rb:1454:5:1454:5 | b [element 2] : | +| array_flow.rb:1454:9:1454:17 | call to take [element] : | array_flow.rb:1454:5:1454:5 | b [element] : | +| array_flow.rb:1454:9:1454:17 | call to take [element] : | array_flow.rb:1454:5:1454:5 | b [element] : | | array_flow.rb:1455:10:1455:10 | b [element 2] : | array_flow.rb:1455:10:1455:13 | ...[...] | | array_flow.rb:1455:10:1455:10 | b [element 2] : | array_flow.rb:1455:10:1455:13 | ...[...] | | array_flow.rb:1455:10:1455:10 | b [element] : | array_flow.rb:1455:10:1455:13 | ...[...] | | array_flow.rb:1455:10:1455:10 | b [element] : | array_flow.rb:1455:10:1455:13 | ...[...] | -| array_flow.rb:1459:16:1459:26 | call to source : | array_flow.rb:1460:9:1460:9 | a [element 2] : | -| array_flow.rb:1459:16:1459:26 | call to source : | array_flow.rb:1460:9:1460:9 | a [element 2] : | +| array_flow.rb:1459:5:1459:5 | a [element 2] : | array_flow.rb:1460:9:1460:9 | a [element 2] : | +| array_flow.rb:1459:5:1459:5 | a [element 2] : | array_flow.rb:1460:9:1460:9 | a [element 2] : | +| array_flow.rb:1459:16:1459:26 | call to source : | array_flow.rb:1459:5:1459:5 | a [element 2] : | +| array_flow.rb:1459:16:1459:26 | call to source : | array_flow.rb:1459:5:1459:5 | a [element 2] : | +| array_flow.rb:1460:5:1460:5 | b [element 2] : | array_flow.rb:1466:10:1466:10 | b [element 2] : | +| array_flow.rb:1460:5:1460:5 | b [element 2] : | array_flow.rb:1466:10:1466:10 | b [element 2] : | | array_flow.rb:1460:9:1460:9 | a [element 2] : | array_flow.rb:1460:9:1463:7 | call to take_while [element 2] : | | array_flow.rb:1460:9:1460:9 | a [element 2] : | array_flow.rb:1460:9:1463:7 | call to take_while [element 2] : | | array_flow.rb:1460:9:1460:9 | a [element 2] : | array_flow.rb:1460:26:1460:26 | x : | | array_flow.rb:1460:9:1460:9 | a [element 2] : | array_flow.rb:1460:26:1460:26 | x : | -| array_flow.rb:1460:9:1463:7 | call to take_while [element 2] : | array_flow.rb:1466:10:1466:10 | b [element 2] : | -| array_flow.rb:1460:9:1463:7 | call to take_while [element 2] : | array_flow.rb:1466:10:1466:10 | b [element 2] : | +| array_flow.rb:1460:9:1463:7 | call to take_while [element 2] : | array_flow.rb:1460:5:1460:5 | b [element 2] : | +| array_flow.rb:1460:9:1463:7 | call to take_while [element 2] : | array_flow.rb:1460:5:1460:5 | b [element 2] : | | array_flow.rb:1460:26:1460:26 | x : | array_flow.rb:1461:14:1461:14 | x | | array_flow.rb:1460:26:1460:26 | x : | array_flow.rb:1461:14:1461:14 | x | | array_flow.rb:1466:10:1466:10 | b [element 2] : | array_flow.rb:1466:10:1466:13 | ...[...] | | array_flow.rb:1466:10:1466:10 | b [element 2] : | array_flow.rb:1466:10:1466:13 | ...[...] | -| array_flow.rb:1472:19:1472:29 | call to source : | array_flow.rb:1473:9:1473:9 | a [element 3] : | -| array_flow.rb:1472:19:1472:29 | call to source : | array_flow.rb:1473:9:1473:9 | a [element 3] : | +| array_flow.rb:1472:5:1472:5 | a [element 3] : | array_flow.rb:1473:9:1473:9 | a [element 3] : | +| array_flow.rb:1472:5:1472:5 | a [element 3] : | array_flow.rb:1473:9:1473:9 | a [element 3] : | +| array_flow.rb:1472:19:1472:29 | call to source : | array_flow.rb:1472:5:1472:5 | a [element 3] : | +| array_flow.rb:1472:19:1472:29 | call to source : | array_flow.rb:1472:5:1472:5 | a [element 3] : | +| array_flow.rb:1473:5:1473:5 | b [element 3] : | array_flow.rb:1474:10:1474:10 | b [element 3] : | +| array_flow.rb:1473:5:1473:5 | b [element 3] : | array_flow.rb:1474:10:1474:10 | b [element 3] : | | array_flow.rb:1473:9:1473:9 | a [element 3] : | array_flow.rb:1473:9:1473:14 | call to to_a [element 3] : | | array_flow.rb:1473:9:1473:9 | a [element 3] : | array_flow.rb:1473:9:1473:14 | call to to_a [element 3] : | -| array_flow.rb:1473:9:1473:14 | call to to_a [element 3] : | array_flow.rb:1474:10:1474:10 | b [element 3] : | -| array_flow.rb:1473:9:1473:14 | call to to_a [element 3] : | array_flow.rb:1474:10:1474:10 | b [element 3] : | +| array_flow.rb:1473:9:1473:14 | call to to_a [element 3] : | array_flow.rb:1473:5:1473:5 | b [element 3] : | +| array_flow.rb:1473:9:1473:14 | call to to_a [element 3] : | array_flow.rb:1473:5:1473:5 | b [element 3] : | | array_flow.rb:1474:10:1474:10 | b [element 3] : | array_flow.rb:1474:10:1474:13 | ...[...] | | array_flow.rb:1474:10:1474:10 | b [element 3] : | array_flow.rb:1474:10:1474:13 | ...[...] | -| array_flow.rb:1478:16:1478:26 | call to source : | array_flow.rb:1479:9:1479:9 | a [element 2] : | -| array_flow.rb:1478:16:1478:26 | call to source : | array_flow.rb:1479:9:1479:9 | a [element 2] : | +| array_flow.rb:1478:5:1478:5 | a [element 2] : | array_flow.rb:1479:9:1479:9 | a [element 2] : | +| array_flow.rb:1478:5:1478:5 | a [element 2] : | array_flow.rb:1479:9:1479:9 | a [element 2] : | +| array_flow.rb:1478:16:1478:26 | call to source : | array_flow.rb:1478:5:1478:5 | a [element 2] : | +| array_flow.rb:1478:16:1478:26 | call to source : | array_flow.rb:1478:5:1478:5 | a [element 2] : | +| array_flow.rb:1479:5:1479:5 | b [element 2] : | array_flow.rb:1482:10:1482:10 | b [element 2] : | +| array_flow.rb:1479:5:1479:5 | b [element 2] : | array_flow.rb:1482:10:1482:10 | b [element 2] : | | array_flow.rb:1479:9:1479:9 | a [element 2] : | array_flow.rb:1479:9:1479:16 | call to to_ary [element 2] : | | array_flow.rb:1479:9:1479:9 | a [element 2] : | array_flow.rb:1479:9:1479:16 | call to to_ary [element 2] : | -| array_flow.rb:1479:9:1479:16 | call to to_ary [element 2] : | array_flow.rb:1482:10:1482:10 | b [element 2] : | -| array_flow.rb:1479:9:1479:16 | call to to_ary [element 2] : | array_flow.rb:1482:10:1482:10 | b [element 2] : | +| array_flow.rb:1479:9:1479:16 | call to to_ary [element 2] : | array_flow.rb:1479:5:1479:5 | b [element 2] : | +| array_flow.rb:1479:9:1479:16 | call to to_ary [element 2] : | array_flow.rb:1479:5:1479:5 | b [element 2] : | | array_flow.rb:1482:10:1482:10 | b [element 2] : | array_flow.rb:1482:10:1482:13 | ...[...] | | array_flow.rb:1482:10:1482:10 | b [element 2] : | array_flow.rb:1482:10:1482:13 | ...[...] | -| array_flow.rb:1495:14:1495:26 | call to source : | array_flow.rb:1496:9:1496:9 | a [element 0, element 1] : | -| array_flow.rb:1495:14:1495:26 | call to source : | array_flow.rb:1496:9:1496:9 | a [element 0, element 1] : | -| array_flow.rb:1495:34:1495:46 | call to source : | array_flow.rb:1496:9:1496:9 | a [element 1, element 1] : | -| array_flow.rb:1495:34:1495:46 | call to source : | array_flow.rb:1496:9:1496:9 | a [element 1, element 1] : | -| array_flow.rb:1495:54:1495:66 | call to source : | array_flow.rb:1496:9:1496:9 | a [element 2, element 1] : | -| array_flow.rb:1495:54:1495:66 | call to source : | array_flow.rb:1496:9:1496:9 | a [element 2, element 1] : | +| array_flow.rb:1495:5:1495:5 | a [element 0, element 1] : | array_flow.rb:1496:9:1496:9 | a [element 0, element 1] : | +| array_flow.rb:1495:5:1495:5 | a [element 0, element 1] : | array_flow.rb:1496:9:1496:9 | a [element 0, element 1] : | +| array_flow.rb:1495:5:1495:5 | a [element 1, element 1] : | array_flow.rb:1496:9:1496:9 | a [element 1, element 1] : | +| array_flow.rb:1495:5:1495:5 | a [element 1, element 1] : | array_flow.rb:1496:9:1496:9 | a [element 1, element 1] : | +| array_flow.rb:1495:5:1495:5 | a [element 2, element 1] : | array_flow.rb:1496:9:1496:9 | a [element 2, element 1] : | +| array_flow.rb:1495:5:1495:5 | a [element 2, element 1] : | array_flow.rb:1496:9:1496:9 | a [element 2, element 1] : | +| array_flow.rb:1495:14:1495:26 | call to source : | array_flow.rb:1495:5:1495:5 | a [element 0, element 1] : | +| array_flow.rb:1495:14:1495:26 | call to source : | array_flow.rb:1495:5:1495:5 | a [element 0, element 1] : | +| array_flow.rb:1495:34:1495:46 | call to source : | array_flow.rb:1495:5:1495:5 | a [element 1, element 1] : | +| array_flow.rb:1495:34:1495:46 | call to source : | array_flow.rb:1495:5:1495:5 | a [element 1, element 1] : | +| array_flow.rb:1495:54:1495:66 | call to source : | array_flow.rb:1495:5:1495:5 | a [element 2, element 1] : | +| array_flow.rb:1495:54:1495:66 | call to source : | array_flow.rb:1495:5:1495:5 | a [element 2, element 1] : | +| array_flow.rb:1496:5:1496:5 | b [element 1, element 0] : | array_flow.rb:1500:10:1500:10 | b [element 1, element 0] : | +| array_flow.rb:1496:5:1496:5 | b [element 1, element 0] : | array_flow.rb:1500:10:1500:10 | b [element 1, element 0] : | +| array_flow.rb:1496:5:1496:5 | b [element 1, element 1] : | array_flow.rb:1501:10:1501:10 | b [element 1, element 1] : | +| array_flow.rb:1496:5:1496:5 | b [element 1, element 1] : | array_flow.rb:1501:10:1501:10 | b [element 1, element 1] : | +| array_flow.rb:1496:5:1496:5 | b [element 1, element 2] : | array_flow.rb:1502:10:1502:10 | b [element 1, element 2] : | +| array_flow.rb:1496:5:1496:5 | b [element 1, element 2] : | array_flow.rb:1502:10:1502:10 | b [element 1, element 2] : | | array_flow.rb:1496:9:1496:9 | a [element 0, element 1] : | array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 0] : | | array_flow.rb:1496:9:1496:9 | a [element 0, element 1] : | array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 0] : | | array_flow.rb:1496:9:1496:9 | a [element 1, element 1] : | array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 1] : | | array_flow.rb:1496:9:1496:9 | a [element 1, element 1] : | array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 1] : | | array_flow.rb:1496:9:1496:9 | a [element 2, element 1] : | array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 2] : | | array_flow.rb:1496:9:1496:9 | a [element 2, element 1] : | array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 2] : | -| array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 0] : | array_flow.rb:1500:10:1500:10 | b [element 1, element 0] : | -| array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 0] : | array_flow.rb:1500:10:1500:10 | b [element 1, element 0] : | -| array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 1] : | array_flow.rb:1501:10:1501:10 | b [element 1, element 1] : | -| array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 1] : | array_flow.rb:1501:10:1501:10 | b [element 1, element 1] : | -| array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 2] : | array_flow.rb:1502:10:1502:10 | b [element 1, element 2] : | -| array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 2] : | array_flow.rb:1502:10:1502:10 | b [element 1, element 2] : | +| array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 0] : | array_flow.rb:1496:5:1496:5 | b [element 1, element 0] : | +| array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 0] : | array_flow.rb:1496:5:1496:5 | b [element 1, element 0] : | +| array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 1] : | array_flow.rb:1496:5:1496:5 | b [element 1, element 1] : | +| array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 1] : | array_flow.rb:1496:5:1496:5 | b [element 1, element 1] : | +| array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 2] : | array_flow.rb:1496:5:1496:5 | b [element 1, element 2] : | +| array_flow.rb:1496:9:1496:19 | call to transpose [element 1, element 2] : | array_flow.rb:1496:5:1496:5 | b [element 1, element 2] : | | array_flow.rb:1500:10:1500:10 | b [element 1, element 0] : | array_flow.rb:1500:10:1500:13 | ...[...] [element 0] : | | array_flow.rb:1500:10:1500:10 | b [element 1, element 0] : | array_flow.rb:1500:10:1500:13 | ...[...] [element 0] : | | array_flow.rb:1500:10:1500:13 | ...[...] [element 0] : | array_flow.rb:1500:10:1500:16 | ...[...] | @@ -3077,20 +3822,28 @@ edges | array_flow.rb:1502:10:1502:10 | b [element 1, element 2] : | array_flow.rb:1502:10:1502:13 | ...[...] [element 2] : | | array_flow.rb:1502:10:1502:13 | ...[...] [element 2] : | array_flow.rb:1502:10:1502:16 | ...[...] | | array_flow.rb:1502:10:1502:13 | ...[...] [element 2] : | array_flow.rb:1502:10:1502:16 | ...[...] | -| array_flow.rb:1506:16:1506:28 | call to source : | array_flow.rb:1509:9:1509:9 | a [element 2] : | -| array_flow.rb:1506:16:1506:28 | call to source : | array_flow.rb:1509:9:1509:9 | a [element 2] : | -| array_flow.rb:1507:13:1507:25 | call to source : | array_flow.rb:1509:17:1509:17 | b [element 1] : | -| array_flow.rb:1507:13:1507:25 | call to source : | array_flow.rb:1509:17:1509:17 | b [element 1] : | -| array_flow.rb:1508:13:1508:25 | call to source : | array_flow.rb:1509:20:1509:20 | c [element 1] : | -| array_flow.rb:1508:13:1508:25 | call to source : | array_flow.rb:1509:20:1509:20 | c [element 1] : | +| array_flow.rb:1506:5:1506:5 | a [element 2] : | array_flow.rb:1509:9:1509:9 | a [element 2] : | +| array_flow.rb:1506:5:1506:5 | a [element 2] : | array_flow.rb:1509:9:1509:9 | a [element 2] : | +| array_flow.rb:1506:16:1506:28 | call to source : | array_flow.rb:1506:5:1506:5 | a [element 2] : | +| array_flow.rb:1506:16:1506:28 | call to source : | array_flow.rb:1506:5:1506:5 | a [element 2] : | +| array_flow.rb:1507:5:1507:5 | b [element 1] : | array_flow.rb:1509:17:1509:17 | b [element 1] : | +| array_flow.rb:1507:5:1507:5 | b [element 1] : | array_flow.rb:1509:17:1509:17 | b [element 1] : | +| array_flow.rb:1507:13:1507:25 | call to source : | array_flow.rb:1507:5:1507:5 | b [element 1] : | +| array_flow.rb:1507:13:1507:25 | call to source : | array_flow.rb:1507:5:1507:5 | b [element 1] : | +| array_flow.rb:1508:5:1508:5 | c [element 1] : | array_flow.rb:1509:20:1509:20 | c [element 1] : | +| array_flow.rb:1508:5:1508:5 | c [element 1] : | array_flow.rb:1509:20:1509:20 | c [element 1] : | +| array_flow.rb:1508:13:1508:25 | call to source : | array_flow.rb:1508:5:1508:5 | c [element 1] : | +| array_flow.rb:1508:13:1508:25 | call to source : | array_flow.rb:1508:5:1508:5 | c [element 1] : | +| array_flow.rb:1509:5:1509:5 | d [element] : | array_flow.rb:1510:10:1510:10 | d [element] : | +| array_flow.rb:1509:5:1509:5 | d [element] : | array_flow.rb:1510:10:1510:10 | d [element] : | +| array_flow.rb:1509:5:1509:5 | d [element] : | array_flow.rb:1511:10:1511:10 | d [element] : | +| array_flow.rb:1509:5:1509:5 | d [element] : | array_flow.rb:1511:10:1511:10 | d [element] : | +| array_flow.rb:1509:5:1509:5 | d [element] : | array_flow.rb:1512:10:1512:10 | d [element] : | +| array_flow.rb:1509:5:1509:5 | d [element] : | array_flow.rb:1512:10:1512:10 | d [element] : | | array_flow.rb:1509:9:1509:9 | a [element 2] : | array_flow.rb:1509:9:1509:21 | call to union [element] : | | array_flow.rb:1509:9:1509:9 | a [element 2] : | array_flow.rb:1509:9:1509:21 | call to union [element] : | -| array_flow.rb:1509:9:1509:21 | call to union [element] : | array_flow.rb:1510:10:1510:10 | d [element] : | -| array_flow.rb:1509:9:1509:21 | call to union [element] : | array_flow.rb:1510:10:1510:10 | d [element] : | -| array_flow.rb:1509:9:1509:21 | call to union [element] : | array_flow.rb:1511:10:1511:10 | d [element] : | -| array_flow.rb:1509:9:1509:21 | call to union [element] : | array_flow.rb:1511:10:1511:10 | d [element] : | -| array_flow.rb:1509:9:1509:21 | call to union [element] : | array_flow.rb:1512:10:1512:10 | d [element] : | -| array_flow.rb:1509:9:1509:21 | call to union [element] : | array_flow.rb:1512:10:1512:10 | d [element] : | +| array_flow.rb:1509:9:1509:21 | call to union [element] : | array_flow.rb:1509:5:1509:5 | d [element] : | +| array_flow.rb:1509:9:1509:21 | call to union [element] : | array_flow.rb:1509:5:1509:5 | d [element] : | | array_flow.rb:1509:17:1509:17 | b [element 1] : | array_flow.rb:1509:9:1509:21 | call to union [element] : | | array_flow.rb:1509:17:1509:17 | b [element 1] : | array_flow.rb:1509:9:1509:21 | call to union [element] : | | array_flow.rb:1509:20:1509:20 | c [element 1] : | array_flow.rb:1509:9:1509:21 | call to union [element] : | @@ -3101,26 +3854,34 @@ edges | array_flow.rb:1511:10:1511:10 | d [element] : | array_flow.rb:1511:10:1511:13 | ...[...] | | array_flow.rb:1512:10:1512:10 | d [element] : | array_flow.rb:1512:10:1512:13 | ...[...] | | array_flow.rb:1512:10:1512:10 | d [element] : | array_flow.rb:1512:10:1512:13 | ...[...] | -| array_flow.rb:1516:19:1516:31 | call to source : | array_flow.rb:1518:9:1518:9 | a [element 3] : | -| array_flow.rb:1516:19:1516:31 | call to source : | array_flow.rb:1518:9:1518:9 | a [element 3] : | -| array_flow.rb:1516:19:1516:31 | call to source : | array_flow.rb:1522:9:1522:9 | a [element 3] : | -| array_flow.rb:1516:19:1516:31 | call to source : | array_flow.rb:1522:9:1522:9 | a [element 3] : | -| array_flow.rb:1516:34:1516:46 | call to source : | array_flow.rb:1518:9:1518:9 | a [element 4] : | -| array_flow.rb:1516:34:1516:46 | call to source : | array_flow.rb:1518:9:1518:9 | a [element 4] : | -| array_flow.rb:1516:34:1516:46 | call to source : | array_flow.rb:1522:9:1522:9 | a [element 4] : | -| array_flow.rb:1516:34:1516:46 | call to source : | array_flow.rb:1522:9:1522:9 | a [element 4] : | +| array_flow.rb:1516:5:1516:5 | a [element 3] : | array_flow.rb:1518:9:1518:9 | a [element 3] : | +| array_flow.rb:1516:5:1516:5 | a [element 3] : | array_flow.rb:1518:9:1518:9 | a [element 3] : | +| array_flow.rb:1516:5:1516:5 | a [element 3] : | array_flow.rb:1522:9:1522:9 | a [element 3] : | +| array_flow.rb:1516:5:1516:5 | a [element 3] : | array_flow.rb:1522:9:1522:9 | a [element 3] : | +| array_flow.rb:1516:5:1516:5 | a [element 4] : | array_flow.rb:1518:9:1518:9 | a [element 4] : | +| array_flow.rb:1516:5:1516:5 | a [element 4] : | array_flow.rb:1518:9:1518:9 | a [element 4] : | +| array_flow.rb:1516:5:1516:5 | a [element 4] : | array_flow.rb:1522:9:1522:9 | a [element 4] : | +| array_flow.rb:1516:5:1516:5 | a [element 4] : | array_flow.rb:1522:9:1522:9 | a [element 4] : | +| array_flow.rb:1516:19:1516:31 | call to source : | array_flow.rb:1516:5:1516:5 | a [element 3] : | +| array_flow.rb:1516:19:1516:31 | call to source : | array_flow.rb:1516:5:1516:5 | a [element 3] : | +| array_flow.rb:1516:34:1516:46 | call to source : | array_flow.rb:1516:5:1516:5 | a [element 4] : | +| array_flow.rb:1516:34:1516:46 | call to source : | array_flow.rb:1516:5:1516:5 | a [element 4] : | +| array_flow.rb:1518:5:1518:5 | b [element] : | array_flow.rb:1519:10:1519:10 | b [element] : | +| array_flow.rb:1518:5:1518:5 | b [element] : | array_flow.rb:1519:10:1519:10 | b [element] : | +| array_flow.rb:1518:5:1518:5 | b [element] : | array_flow.rb:1520:10:1520:10 | b [element] : | +| array_flow.rb:1518:5:1518:5 | b [element] : | array_flow.rb:1520:10:1520:10 | b [element] : | | array_flow.rb:1518:9:1518:9 | a [element 3] : | array_flow.rb:1518:9:1518:14 | call to uniq [element] : | | array_flow.rb:1518:9:1518:9 | a [element 3] : | array_flow.rb:1518:9:1518:14 | call to uniq [element] : | | array_flow.rb:1518:9:1518:9 | a [element 4] : | array_flow.rb:1518:9:1518:14 | call to uniq [element] : | | array_flow.rb:1518:9:1518:9 | a [element 4] : | array_flow.rb:1518:9:1518:14 | call to uniq [element] : | -| array_flow.rb:1518:9:1518:14 | call to uniq [element] : | array_flow.rb:1519:10:1519:10 | b [element] : | -| array_flow.rb:1518:9:1518:14 | call to uniq [element] : | array_flow.rb:1519:10:1519:10 | b [element] : | -| array_flow.rb:1518:9:1518:14 | call to uniq [element] : | array_flow.rb:1520:10:1520:10 | b [element] : | -| array_flow.rb:1518:9:1518:14 | call to uniq [element] : | array_flow.rb:1520:10:1520:10 | b [element] : | +| array_flow.rb:1518:9:1518:14 | call to uniq [element] : | array_flow.rb:1518:5:1518:5 | b [element] : | +| array_flow.rb:1518:9:1518:14 | call to uniq [element] : | array_flow.rb:1518:5:1518:5 | b [element] : | | array_flow.rb:1519:10:1519:10 | b [element] : | array_flow.rb:1519:10:1519:13 | ...[...] | | array_flow.rb:1519:10:1519:10 | b [element] : | array_flow.rb:1519:10:1519:13 | ...[...] | | array_flow.rb:1520:10:1520:10 | b [element] : | array_flow.rb:1520:10:1520:13 | ...[...] | | array_flow.rb:1520:10:1520:10 | b [element] : | array_flow.rb:1520:10:1520:13 | ...[...] | +| array_flow.rb:1522:5:1522:5 | c [element] : | array_flow.rb:1526:10:1526:10 | c [element] : | +| array_flow.rb:1522:5:1522:5 | c [element] : | array_flow.rb:1526:10:1526:10 | c [element] : | | array_flow.rb:1522:9:1522:9 | a [element 3] : | array_flow.rb:1522:9:1525:7 | call to uniq [element] : | | array_flow.rb:1522:9:1522:9 | a [element 3] : | array_flow.rb:1522:9:1525:7 | call to uniq [element] : | | array_flow.rb:1522:9:1522:9 | a [element 3] : | array_flow.rb:1522:20:1522:20 | x : | @@ -3129,16 +3890,24 @@ edges | array_flow.rb:1522:9:1522:9 | a [element 4] : | array_flow.rb:1522:9:1525:7 | call to uniq [element] : | | array_flow.rb:1522:9:1522:9 | a [element 4] : | array_flow.rb:1522:20:1522:20 | x : | | array_flow.rb:1522:9:1522:9 | a [element 4] : | array_flow.rb:1522:20:1522:20 | x : | -| array_flow.rb:1522:9:1525:7 | call to uniq [element] : | array_flow.rb:1526:10:1526:10 | c [element] : | -| array_flow.rb:1522:9:1525:7 | call to uniq [element] : | array_flow.rb:1526:10:1526:10 | c [element] : | +| array_flow.rb:1522:9:1525:7 | call to uniq [element] : | array_flow.rb:1522:5:1522:5 | c [element] : | +| array_flow.rb:1522:9:1525:7 | call to uniq [element] : | array_flow.rb:1522:5:1522:5 | c [element] : | | array_flow.rb:1522:20:1522:20 | x : | array_flow.rb:1523:14:1523:14 | x | | array_flow.rb:1522:20:1522:20 | x : | array_flow.rb:1523:14:1523:14 | x | | array_flow.rb:1526:10:1526:10 | c [element] : | array_flow.rb:1526:10:1526:13 | ...[...] | | array_flow.rb:1526:10:1526:10 | c [element] : | array_flow.rb:1526:10:1526:13 | ...[...] | -| array_flow.rb:1530:16:1530:28 | call to source : | array_flow.rb:1531:9:1531:9 | a [element 2] : | -| array_flow.rb:1530:16:1530:28 | call to source : | array_flow.rb:1531:9:1531:9 | a [element 2] : | -| array_flow.rb:1530:31:1530:43 | call to source : | array_flow.rb:1531:9:1531:9 | a [element 3] : | -| array_flow.rb:1530:31:1530:43 | call to source : | array_flow.rb:1531:9:1531:9 | a [element 3] : | +| array_flow.rb:1530:5:1530:5 | a [element 2] : | array_flow.rb:1531:9:1531:9 | a [element 2] : | +| array_flow.rb:1530:5:1530:5 | a [element 2] : | array_flow.rb:1531:9:1531:9 | a [element 2] : | +| array_flow.rb:1530:5:1530:5 | a [element 3] : | array_flow.rb:1531:9:1531:9 | a [element 3] : | +| array_flow.rb:1530:5:1530:5 | a [element 3] : | array_flow.rb:1531:9:1531:9 | a [element 3] : | +| array_flow.rb:1530:16:1530:28 | call to source : | array_flow.rb:1530:5:1530:5 | a [element 2] : | +| array_flow.rb:1530:16:1530:28 | call to source : | array_flow.rb:1530:5:1530:5 | a [element 2] : | +| array_flow.rb:1530:31:1530:43 | call to source : | array_flow.rb:1530:5:1530:5 | a [element 3] : | +| array_flow.rb:1530:31:1530:43 | call to source : | array_flow.rb:1530:5:1530:5 | a [element 3] : | +| array_flow.rb:1531:5:1531:5 | b [element] : | array_flow.rb:1532:10:1532:10 | b [element] : | +| array_flow.rb:1531:5:1531:5 | b [element] : | array_flow.rb:1532:10:1532:10 | b [element] : | +| array_flow.rb:1531:5:1531:5 | b [element] : | array_flow.rb:1533:10:1533:10 | b [element] : | +| array_flow.rb:1531:5:1531:5 | b [element] : | array_flow.rb:1533:10:1533:10 | b [element] : | | array_flow.rb:1531:9:1531:9 | [post] a [element] : | array_flow.rb:1534:10:1534:10 | a [element] : | | array_flow.rb:1531:9:1531:9 | [post] a [element] : | array_flow.rb:1534:10:1534:10 | a [element] : | | array_flow.rb:1531:9:1531:9 | [post] a [element] : | array_flow.rb:1535:10:1535:10 | a [element] : | @@ -3151,10 +3920,8 @@ edges | array_flow.rb:1531:9:1531:9 | a [element 3] : | array_flow.rb:1531:9:1531:9 | [post] a [element] : | | array_flow.rb:1531:9:1531:9 | a [element 3] : | array_flow.rb:1531:9:1531:15 | call to uniq! [element] : | | array_flow.rb:1531:9:1531:9 | a [element 3] : | array_flow.rb:1531:9:1531:15 | call to uniq! [element] : | -| array_flow.rb:1531:9:1531:15 | call to uniq! [element] : | array_flow.rb:1532:10:1532:10 | b [element] : | -| array_flow.rb:1531:9:1531:15 | call to uniq! [element] : | array_flow.rb:1532:10:1532:10 | b [element] : | -| array_flow.rb:1531:9:1531:15 | call to uniq! [element] : | array_flow.rb:1533:10:1533:10 | b [element] : | -| array_flow.rb:1531:9:1531:15 | call to uniq! [element] : | array_flow.rb:1533:10:1533:10 | b [element] : | +| array_flow.rb:1531:9:1531:15 | call to uniq! [element] : | array_flow.rb:1531:5:1531:5 | b [element] : | +| array_flow.rb:1531:9:1531:15 | call to uniq! [element] : | array_flow.rb:1531:5:1531:5 | b [element] : | | array_flow.rb:1532:10:1532:10 | b [element] : | array_flow.rb:1532:10:1532:13 | ...[...] | | array_flow.rb:1532:10:1532:10 | b [element] : | array_flow.rb:1532:10:1532:13 | ...[...] | | array_flow.rb:1533:10:1533:10 | b [element] : | array_flow.rb:1533:10:1533:13 | ...[...] | @@ -3163,10 +3930,18 @@ edges | array_flow.rb:1534:10:1534:10 | a [element] : | array_flow.rb:1534:10:1534:13 | ...[...] | | array_flow.rb:1535:10:1535:10 | a [element] : | array_flow.rb:1535:10:1535:13 | ...[...] | | array_flow.rb:1535:10:1535:10 | a [element] : | array_flow.rb:1535:10:1535:13 | ...[...] | -| array_flow.rb:1537:16:1537:28 | call to source : | array_flow.rb:1538:9:1538:9 | a [element 2] : | -| array_flow.rb:1537:16:1537:28 | call to source : | array_flow.rb:1538:9:1538:9 | a [element 2] : | -| array_flow.rb:1537:31:1537:43 | call to source : | array_flow.rb:1538:9:1538:9 | a [element 3] : | -| array_flow.rb:1537:31:1537:43 | call to source : | array_flow.rb:1538:9:1538:9 | a [element 3] : | +| array_flow.rb:1537:5:1537:5 | a [element 2] : | array_flow.rb:1538:9:1538:9 | a [element 2] : | +| array_flow.rb:1537:5:1537:5 | a [element 2] : | array_flow.rb:1538:9:1538:9 | a [element 2] : | +| array_flow.rb:1537:5:1537:5 | a [element 3] : | array_flow.rb:1538:9:1538:9 | a [element 3] : | +| array_flow.rb:1537:5:1537:5 | a [element 3] : | array_flow.rb:1538:9:1538:9 | a [element 3] : | +| array_flow.rb:1537:16:1537:28 | call to source : | array_flow.rb:1537:5:1537:5 | a [element 2] : | +| array_flow.rb:1537:16:1537:28 | call to source : | array_flow.rb:1537:5:1537:5 | a [element 2] : | +| array_flow.rb:1537:31:1537:43 | call to source : | array_flow.rb:1537:5:1537:5 | a [element 3] : | +| array_flow.rb:1537:31:1537:43 | call to source : | array_flow.rb:1537:5:1537:5 | a [element 3] : | +| array_flow.rb:1538:5:1538:5 | b [element] : | array_flow.rb:1542:10:1542:10 | b [element] : | +| array_flow.rb:1538:5:1538:5 | b [element] : | array_flow.rb:1542:10:1542:10 | b [element] : | +| array_flow.rb:1538:5:1538:5 | b [element] : | array_flow.rb:1543:10:1543:10 | b [element] : | +| array_flow.rb:1538:5:1538:5 | b [element] : | array_flow.rb:1543:10:1543:10 | b [element] : | | array_flow.rb:1538:9:1538:9 | [post] a [element] : | array_flow.rb:1544:10:1544:10 | a [element] : | | array_flow.rb:1538:9:1538:9 | [post] a [element] : | array_flow.rb:1544:10:1544:10 | a [element] : | | array_flow.rb:1538:9:1538:9 | [post] a [element] : | array_flow.rb:1545:10:1545:10 | a [element] : | @@ -3183,10 +3958,8 @@ edges | array_flow.rb:1538:9:1538:9 | a [element 3] : | array_flow.rb:1538:9:1541:7 | call to uniq! [element] : | | array_flow.rb:1538:9:1538:9 | a [element 3] : | array_flow.rb:1538:21:1538:21 | x : | | array_flow.rb:1538:9:1538:9 | a [element 3] : | array_flow.rb:1538:21:1538:21 | x : | -| array_flow.rb:1538:9:1541:7 | call to uniq! [element] : | array_flow.rb:1542:10:1542:10 | b [element] : | -| array_flow.rb:1538:9:1541:7 | call to uniq! [element] : | array_flow.rb:1542:10:1542:10 | b [element] : | -| array_flow.rb:1538:9:1541:7 | call to uniq! [element] : | array_flow.rb:1543:10:1543:10 | b [element] : | -| array_flow.rb:1538:9:1541:7 | call to uniq! [element] : | array_flow.rb:1543:10:1543:10 | b [element] : | +| array_flow.rb:1538:9:1541:7 | call to uniq! [element] : | array_flow.rb:1538:5:1538:5 | b [element] : | +| array_flow.rb:1538:9:1541:7 | call to uniq! [element] : | array_flow.rb:1538:5:1538:5 | b [element] : | | array_flow.rb:1538:21:1538:21 | x : | array_flow.rb:1539:14:1539:14 | x | | array_flow.rb:1538:21:1538:21 | x : | array_flow.rb:1539:14:1539:14 | x | | array_flow.rb:1542:10:1542:10 | b [element] : | array_flow.rb:1542:10:1542:13 | ...[...] | @@ -3197,8 +3970,10 @@ edges | array_flow.rb:1544:10:1544:10 | a [element] : | array_flow.rb:1544:10:1544:13 | ...[...] | | array_flow.rb:1545:10:1545:10 | a [element] : | array_flow.rb:1545:10:1545:13 | ...[...] | | array_flow.rb:1545:10:1545:10 | a [element] : | array_flow.rb:1545:10:1545:13 | ...[...] | -| array_flow.rb:1549:16:1549:28 | call to source : | array_flow.rb:1550:5:1550:5 | a [element 2] : | -| array_flow.rb:1549:16:1549:28 | call to source : | array_flow.rb:1550:5:1550:5 | a [element 2] : | +| array_flow.rb:1549:5:1549:5 | a [element 2] : | array_flow.rb:1550:5:1550:5 | a [element 2] : | +| array_flow.rb:1549:5:1549:5 | a [element 2] : | array_flow.rb:1550:5:1550:5 | a [element 2] : | +| array_flow.rb:1549:16:1549:28 | call to source : | array_flow.rb:1549:5:1549:5 | a [element 2] : | +| array_flow.rb:1549:16:1549:28 | call to source : | array_flow.rb:1549:5:1549:5 | a [element 2] : | | array_flow.rb:1550:5:1550:5 | [post] a [element 2] : | array_flow.rb:1553:10:1553:10 | a [element 2] : | | array_flow.rb:1550:5:1550:5 | [post] a [element 2] : | array_flow.rb:1553:10:1553:10 | a [element 2] : | | array_flow.rb:1550:5:1550:5 | [post] a [element 5] : | array_flow.rb:1556:10:1556:10 | a [element 5] : | @@ -3211,72 +3986,88 @@ edges | array_flow.rb:1553:10:1553:10 | a [element 2] : | array_flow.rb:1553:10:1553:13 | ...[...] | | array_flow.rb:1556:10:1556:10 | a [element 5] : | array_flow.rb:1556:10:1556:13 | ...[...] | | array_flow.rb:1556:10:1556:10 | a [element 5] : | array_flow.rb:1556:10:1556:13 | ...[...] | -| array_flow.rb:1560:13:1560:25 | call to source : | array_flow.rb:1562:9:1562:9 | a [element 1] : | -| array_flow.rb:1560:13:1560:25 | call to source : | array_flow.rb:1562:9:1562:9 | a [element 1] : | -| array_flow.rb:1560:13:1560:25 | call to source : | array_flow.rb:1568:9:1568:9 | a [element 1] : | -| array_flow.rb:1560:13:1560:25 | call to source : | array_flow.rb:1568:9:1568:9 | a [element 1] : | -| array_flow.rb:1560:13:1560:25 | call to source : | array_flow.rb:1572:9:1572:9 | a [element 1] : | -| array_flow.rb:1560:13:1560:25 | call to source : | array_flow.rb:1572:9:1572:9 | a [element 1] : | -| array_flow.rb:1560:13:1560:25 | call to source : | array_flow.rb:1576:9:1576:9 | a [element 1] : | -| array_flow.rb:1560:13:1560:25 | call to source : | array_flow.rb:1576:9:1576:9 | a [element 1] : | -| array_flow.rb:1560:31:1560:43 | call to source : | array_flow.rb:1568:9:1568:9 | a [element 3] : | -| array_flow.rb:1560:31:1560:43 | call to source : | array_flow.rb:1568:9:1568:9 | a [element 3] : | -| array_flow.rb:1560:31:1560:43 | call to source : | array_flow.rb:1572:9:1572:9 | a [element 3] : | -| array_flow.rb:1560:31:1560:43 | call to source : | array_flow.rb:1572:9:1572:9 | a [element 3] : | -| array_flow.rb:1560:31:1560:43 | call to source : | array_flow.rb:1576:9:1576:9 | a [element 3] : | -| array_flow.rb:1560:31:1560:43 | call to source : | array_flow.rb:1576:9:1576:9 | a [element 3] : | +| array_flow.rb:1560:5:1560:5 | a [element 1] : | array_flow.rb:1562:9:1562:9 | a [element 1] : | +| array_flow.rb:1560:5:1560:5 | a [element 1] : | array_flow.rb:1562:9:1562:9 | a [element 1] : | +| array_flow.rb:1560:5:1560:5 | a [element 1] : | array_flow.rb:1568:9:1568:9 | a [element 1] : | +| array_flow.rb:1560:5:1560:5 | a [element 1] : | array_flow.rb:1568:9:1568:9 | a [element 1] : | +| array_flow.rb:1560:5:1560:5 | a [element 1] : | array_flow.rb:1572:9:1572:9 | a [element 1] : | +| array_flow.rb:1560:5:1560:5 | a [element 1] : | array_flow.rb:1572:9:1572:9 | a [element 1] : | +| array_flow.rb:1560:5:1560:5 | a [element 1] : | array_flow.rb:1576:9:1576:9 | a [element 1] : | +| array_flow.rb:1560:5:1560:5 | a [element 1] : | array_flow.rb:1576:9:1576:9 | a [element 1] : | +| array_flow.rb:1560:5:1560:5 | a [element 3] : | array_flow.rb:1568:9:1568:9 | a [element 3] : | +| array_flow.rb:1560:5:1560:5 | a [element 3] : | array_flow.rb:1568:9:1568:9 | a [element 3] : | +| array_flow.rb:1560:5:1560:5 | a [element 3] : | array_flow.rb:1572:9:1572:9 | a [element 3] : | +| array_flow.rb:1560:5:1560:5 | a [element 3] : | array_flow.rb:1572:9:1572:9 | a [element 3] : | +| array_flow.rb:1560:5:1560:5 | a [element 3] : | array_flow.rb:1576:9:1576:9 | a [element 3] : | +| array_flow.rb:1560:5:1560:5 | a [element 3] : | array_flow.rb:1576:9:1576:9 | a [element 3] : | +| array_flow.rb:1560:13:1560:25 | call to source : | array_flow.rb:1560:5:1560:5 | a [element 1] : | +| array_flow.rb:1560:13:1560:25 | call to source : | array_flow.rb:1560:5:1560:5 | a [element 1] : | +| array_flow.rb:1560:31:1560:43 | call to source : | array_flow.rb:1560:5:1560:5 | a [element 3] : | +| array_flow.rb:1560:31:1560:43 | call to source : | array_flow.rb:1560:5:1560:5 | a [element 3] : | +| array_flow.rb:1562:5:1562:5 | b [element 1] : | array_flow.rb:1564:10:1564:10 | b [element 1] : | +| array_flow.rb:1562:5:1562:5 | b [element 1] : | array_flow.rb:1564:10:1564:10 | b [element 1] : | +| array_flow.rb:1562:5:1562:5 | b [element 3] : | array_flow.rb:1566:10:1566:10 | b [element 3] : | +| array_flow.rb:1562:5:1562:5 | b [element 3] : | array_flow.rb:1566:10:1566:10 | b [element 3] : | | array_flow.rb:1562:9:1562:9 | a [element 1] : | array_flow.rb:1562:9:1562:31 | call to values_at [element 1] : | | array_flow.rb:1562:9:1562:9 | a [element 1] : | array_flow.rb:1562:9:1562:31 | call to values_at [element 1] : | | array_flow.rb:1562:9:1562:9 | a [element 1] : | array_flow.rb:1562:9:1562:31 | call to values_at [element 3] : | | array_flow.rb:1562:9:1562:9 | a [element 1] : | array_flow.rb:1562:9:1562:31 | call to values_at [element 3] : | -| array_flow.rb:1562:9:1562:31 | call to values_at [element 1] : | array_flow.rb:1564:10:1564:10 | b [element 1] : | -| array_flow.rb:1562:9:1562:31 | call to values_at [element 1] : | array_flow.rb:1564:10:1564:10 | b [element 1] : | -| array_flow.rb:1562:9:1562:31 | call to values_at [element 3] : | array_flow.rb:1566:10:1566:10 | b [element 3] : | -| array_flow.rb:1562:9:1562:31 | call to values_at [element 3] : | array_flow.rb:1566:10:1566:10 | b [element 3] : | +| array_flow.rb:1562:9:1562:31 | call to values_at [element 1] : | array_flow.rb:1562:5:1562:5 | b [element 1] : | +| array_flow.rb:1562:9:1562:31 | call to values_at [element 1] : | array_flow.rb:1562:5:1562:5 | b [element 1] : | +| array_flow.rb:1562:9:1562:31 | call to values_at [element 3] : | array_flow.rb:1562:5:1562:5 | b [element 3] : | +| array_flow.rb:1562:9:1562:31 | call to values_at [element 3] : | array_flow.rb:1562:5:1562:5 | b [element 3] : | | array_flow.rb:1564:10:1564:10 | b [element 1] : | array_flow.rb:1564:10:1564:13 | ...[...] | | array_flow.rb:1564:10:1564:10 | b [element 1] : | array_flow.rb:1564:10:1564:13 | ...[...] | | array_flow.rb:1566:10:1566:10 | b [element 3] : | array_flow.rb:1566:10:1566:13 | ...[...] | | array_flow.rb:1566:10:1566:10 | b [element 3] : | array_flow.rb:1566:10:1566:13 | ...[...] | +| array_flow.rb:1568:5:1568:5 | b [element] : | array_flow.rb:1569:10:1569:10 | b [element] : | +| array_flow.rb:1568:5:1568:5 | b [element] : | array_flow.rb:1569:10:1569:10 | b [element] : | +| array_flow.rb:1568:5:1568:5 | b [element] : | array_flow.rb:1570:10:1570:10 | b [element] : | +| array_flow.rb:1568:5:1568:5 | b [element] : | array_flow.rb:1570:10:1570:10 | b [element] : | | array_flow.rb:1568:9:1568:9 | a [element 1] : | array_flow.rb:1568:9:1568:25 | call to values_at [element] : | | array_flow.rb:1568:9:1568:9 | a [element 1] : | array_flow.rb:1568:9:1568:25 | call to values_at [element] : | | array_flow.rb:1568:9:1568:9 | a [element 3] : | array_flow.rb:1568:9:1568:25 | call to values_at [element] : | | array_flow.rb:1568:9:1568:9 | a [element 3] : | array_flow.rb:1568:9:1568:25 | call to values_at [element] : | -| array_flow.rb:1568:9:1568:25 | call to values_at [element] : | array_flow.rb:1569:10:1569:10 | b [element] : | -| array_flow.rb:1568:9:1568:25 | call to values_at [element] : | array_flow.rb:1569:10:1569:10 | b [element] : | -| array_flow.rb:1568:9:1568:25 | call to values_at [element] : | array_flow.rb:1570:10:1570:10 | b [element] : | -| array_flow.rb:1568:9:1568:25 | call to values_at [element] : | array_flow.rb:1570:10:1570:10 | b [element] : | +| array_flow.rb:1568:9:1568:25 | call to values_at [element] : | array_flow.rb:1568:5:1568:5 | b [element] : | +| array_flow.rb:1568:9:1568:25 | call to values_at [element] : | array_flow.rb:1568:5:1568:5 | b [element] : | | array_flow.rb:1569:10:1569:10 | b [element] : | array_flow.rb:1569:10:1569:13 | ...[...] | | array_flow.rb:1569:10:1569:10 | b [element] : | array_flow.rb:1569:10:1569:13 | ...[...] | | array_flow.rb:1570:10:1570:10 | b [element] : | array_flow.rb:1570:10:1570:13 | ...[...] | | array_flow.rb:1570:10:1570:10 | b [element] : | array_flow.rb:1570:10:1570:13 | ...[...] | +| array_flow.rb:1572:5:1572:5 | b [element] : | array_flow.rb:1573:10:1573:10 | b [element] : | +| array_flow.rb:1572:5:1572:5 | b [element] : | array_flow.rb:1573:10:1573:10 | b [element] : | +| array_flow.rb:1572:5:1572:5 | b [element] : | array_flow.rb:1574:10:1574:10 | b [element] : | +| array_flow.rb:1572:5:1572:5 | b [element] : | array_flow.rb:1574:10:1574:10 | b [element] : | | array_flow.rb:1572:9:1572:9 | a [element 1] : | array_flow.rb:1572:9:1572:26 | call to values_at [element] : | | array_flow.rb:1572:9:1572:9 | a [element 1] : | array_flow.rb:1572:9:1572:26 | call to values_at [element] : | | array_flow.rb:1572:9:1572:9 | a [element 3] : | array_flow.rb:1572:9:1572:26 | call to values_at [element] : | | array_flow.rb:1572:9:1572:9 | a [element 3] : | array_flow.rb:1572:9:1572:26 | call to values_at [element] : | -| array_flow.rb:1572:9:1572:26 | call to values_at [element] : | array_flow.rb:1573:10:1573:10 | b [element] : | -| array_flow.rb:1572:9:1572:26 | call to values_at [element] : | array_flow.rb:1573:10:1573:10 | b [element] : | -| array_flow.rb:1572:9:1572:26 | call to values_at [element] : | array_flow.rb:1574:10:1574:10 | b [element] : | -| array_flow.rb:1572:9:1572:26 | call to values_at [element] : | array_flow.rb:1574:10:1574:10 | b [element] : | +| array_flow.rb:1572:9:1572:26 | call to values_at [element] : | array_flow.rb:1572:5:1572:5 | b [element] : | +| array_flow.rb:1572:9:1572:26 | call to values_at [element] : | array_flow.rb:1572:5:1572:5 | b [element] : | | array_flow.rb:1573:10:1573:10 | b [element] : | array_flow.rb:1573:10:1573:13 | ...[...] | | array_flow.rb:1573:10:1573:10 | b [element] : | array_flow.rb:1573:10:1573:13 | ...[...] | | array_flow.rb:1574:10:1574:10 | b [element] : | array_flow.rb:1574:10:1574:13 | ...[...] | | array_flow.rb:1574:10:1574:10 | b [element] : | array_flow.rb:1574:10:1574:13 | ...[...] | +| array_flow.rb:1576:5:1576:5 | b [element 1] : | array_flow.rb:1578:10:1578:10 | b [element 1] : | +| array_flow.rb:1576:5:1576:5 | b [element 1] : | array_flow.rb:1578:10:1578:10 | b [element 1] : | +| array_flow.rb:1576:5:1576:5 | b [element] : | array_flow.rb:1577:10:1577:10 | b [element] : | +| array_flow.rb:1576:5:1576:5 | b [element] : | array_flow.rb:1577:10:1577:10 | b [element] : | +| array_flow.rb:1576:5:1576:5 | b [element] : | array_flow.rb:1578:10:1578:10 | b [element] : | +| array_flow.rb:1576:5:1576:5 | b [element] : | array_flow.rb:1578:10:1578:10 | b [element] : | +| array_flow.rb:1576:5:1576:5 | b [element] : | array_flow.rb:1579:10:1579:10 | b [element] : | +| array_flow.rb:1576:5:1576:5 | b [element] : | array_flow.rb:1579:10:1579:10 | b [element] : | +| array_flow.rb:1576:5:1576:5 | b [element] : | array_flow.rb:1580:10:1580:10 | b [element] : | +| array_flow.rb:1576:5:1576:5 | b [element] : | array_flow.rb:1580:10:1580:10 | b [element] : | | array_flow.rb:1576:9:1576:9 | a [element 1] : | array_flow.rb:1576:9:1576:28 | call to values_at [element] : | | array_flow.rb:1576:9:1576:9 | a [element 1] : | array_flow.rb:1576:9:1576:28 | call to values_at [element] : | | array_flow.rb:1576:9:1576:9 | a [element 3] : | array_flow.rb:1576:9:1576:28 | call to values_at [element 1] : | | array_flow.rb:1576:9:1576:9 | a [element 3] : | array_flow.rb:1576:9:1576:28 | call to values_at [element 1] : | | array_flow.rb:1576:9:1576:9 | a [element 3] : | array_flow.rb:1576:9:1576:28 | call to values_at [element] : | | array_flow.rb:1576:9:1576:9 | a [element 3] : | array_flow.rb:1576:9:1576:28 | call to values_at [element] : | -| array_flow.rb:1576:9:1576:28 | call to values_at [element 1] : | array_flow.rb:1578:10:1578:10 | b [element 1] : | -| array_flow.rb:1576:9:1576:28 | call to values_at [element 1] : | array_flow.rb:1578:10:1578:10 | b [element 1] : | -| array_flow.rb:1576:9:1576:28 | call to values_at [element] : | array_flow.rb:1577:10:1577:10 | b [element] : | -| array_flow.rb:1576:9:1576:28 | call to values_at [element] : | array_flow.rb:1577:10:1577:10 | b [element] : | -| array_flow.rb:1576:9:1576:28 | call to values_at [element] : | array_flow.rb:1578:10:1578:10 | b [element] : | -| array_flow.rb:1576:9:1576:28 | call to values_at [element] : | array_flow.rb:1578:10:1578:10 | b [element] : | -| array_flow.rb:1576:9:1576:28 | call to values_at [element] : | array_flow.rb:1579:10:1579:10 | b [element] : | -| array_flow.rb:1576:9:1576:28 | call to values_at [element] : | array_flow.rb:1579:10:1579:10 | b [element] : | -| array_flow.rb:1576:9:1576:28 | call to values_at [element] : | array_flow.rb:1580:10:1580:10 | b [element] : | -| array_flow.rb:1576:9:1576:28 | call to values_at [element] : | array_flow.rb:1580:10:1580:10 | b [element] : | +| array_flow.rb:1576:9:1576:28 | call to values_at [element 1] : | array_flow.rb:1576:5:1576:5 | b [element 1] : | +| array_flow.rb:1576:9:1576:28 | call to values_at [element 1] : | array_flow.rb:1576:5:1576:5 | b [element 1] : | +| array_flow.rb:1576:9:1576:28 | call to values_at [element] : | array_flow.rb:1576:5:1576:5 | b [element] : | +| array_flow.rb:1576:9:1576:28 | call to values_at [element] : | array_flow.rb:1576:5:1576:5 | b [element] : | | array_flow.rb:1577:10:1577:10 | b [element] : | array_flow.rb:1577:10:1577:13 | ...[...] | | array_flow.rb:1577:10:1577:10 | b [element] : | array_flow.rb:1577:10:1577:13 | ...[...] | | array_flow.rb:1578:10:1578:10 | b [element 1] : | array_flow.rb:1578:10:1578:13 | ...[...] | @@ -3287,26 +4078,38 @@ edges | array_flow.rb:1579:10:1579:10 | b [element] : | array_flow.rb:1579:10:1579:13 | ...[...] | | array_flow.rb:1580:10:1580:10 | b [element] : | array_flow.rb:1580:10:1580:13 | ...[...] | | array_flow.rb:1580:10:1580:10 | b [element] : | array_flow.rb:1580:10:1580:13 | ...[...] | -| array_flow.rb:1584:16:1584:28 | call to source : | array_flow.rb:1587:9:1587:9 | a [element 2] : | -| array_flow.rb:1584:16:1584:28 | call to source : | array_flow.rb:1587:9:1587:9 | a [element 2] : | -| array_flow.rb:1584:16:1584:28 | call to source : | array_flow.rb:1592:5:1592:5 | a [element 2] : | -| array_flow.rb:1584:16:1584:28 | call to source : | array_flow.rb:1592:5:1592:5 | a [element 2] : | -| array_flow.rb:1585:13:1585:25 | call to source : | array_flow.rb:1587:15:1587:15 | b [element 1] : | -| array_flow.rb:1585:13:1585:25 | call to source : | array_flow.rb:1587:15:1587:15 | b [element 1] : | -| array_flow.rb:1585:13:1585:25 | call to source : | array_flow.rb:1592:11:1592:11 | b [element 1] : | -| array_flow.rb:1585:13:1585:25 | call to source : | array_flow.rb:1592:11:1592:11 | b [element 1] : | -| array_flow.rb:1586:10:1586:22 | call to source : | array_flow.rb:1587:18:1587:18 | c [element 0] : | -| array_flow.rb:1586:10:1586:22 | call to source : | array_flow.rb:1587:18:1587:18 | c [element 0] : | -| array_flow.rb:1586:10:1586:22 | call to source : | array_flow.rb:1592:14:1592:14 | c [element 0] : | -| array_flow.rb:1586:10:1586:22 | call to source : | array_flow.rb:1592:14:1592:14 | c [element 0] : | +| array_flow.rb:1584:5:1584:5 | a [element 2] : | array_flow.rb:1587:9:1587:9 | a [element 2] : | +| array_flow.rb:1584:5:1584:5 | a [element 2] : | array_flow.rb:1587:9:1587:9 | a [element 2] : | +| array_flow.rb:1584:5:1584:5 | a [element 2] : | array_flow.rb:1592:5:1592:5 | a [element 2] : | +| array_flow.rb:1584:5:1584:5 | a [element 2] : | array_flow.rb:1592:5:1592:5 | a [element 2] : | +| array_flow.rb:1584:16:1584:28 | call to source : | array_flow.rb:1584:5:1584:5 | a [element 2] : | +| array_flow.rb:1584:16:1584:28 | call to source : | array_flow.rb:1584:5:1584:5 | a [element 2] : | +| array_flow.rb:1585:5:1585:5 | b [element 1] : | array_flow.rb:1587:15:1587:15 | b [element 1] : | +| array_flow.rb:1585:5:1585:5 | b [element 1] : | array_flow.rb:1587:15:1587:15 | b [element 1] : | +| array_flow.rb:1585:5:1585:5 | b [element 1] : | array_flow.rb:1592:11:1592:11 | b [element 1] : | +| array_flow.rb:1585:5:1585:5 | b [element 1] : | array_flow.rb:1592:11:1592:11 | b [element 1] : | +| array_flow.rb:1585:13:1585:25 | call to source : | array_flow.rb:1585:5:1585:5 | b [element 1] : | +| array_flow.rb:1585:13:1585:25 | call to source : | array_flow.rb:1585:5:1585:5 | b [element 1] : | +| array_flow.rb:1586:5:1586:5 | c [element 0] : | array_flow.rb:1587:18:1587:18 | c [element 0] : | +| array_flow.rb:1586:5:1586:5 | c [element 0] : | array_flow.rb:1587:18:1587:18 | c [element 0] : | +| array_flow.rb:1586:5:1586:5 | c [element 0] : | array_flow.rb:1592:14:1592:14 | c [element 0] : | +| array_flow.rb:1586:5:1586:5 | c [element 0] : | array_flow.rb:1592:14:1592:14 | c [element 0] : | +| array_flow.rb:1586:10:1586:22 | call to source : | array_flow.rb:1586:5:1586:5 | c [element 0] : | +| array_flow.rb:1586:10:1586:22 | call to source : | array_flow.rb:1586:5:1586:5 | c [element 0] : | +| array_flow.rb:1587:5:1587:5 | d [element 0, element 2] : | array_flow.rb:1589:10:1589:10 | d [element 0, element 2] : | +| array_flow.rb:1587:5:1587:5 | d [element 0, element 2] : | array_flow.rb:1589:10:1589:10 | d [element 0, element 2] : | +| array_flow.rb:1587:5:1587:5 | d [element 1, element 1] : | array_flow.rb:1590:10:1590:10 | d [element 1, element 1] : | +| array_flow.rb:1587:5:1587:5 | d [element 1, element 1] : | array_flow.rb:1590:10:1590:10 | d [element 1, element 1] : | +| array_flow.rb:1587:5:1587:5 | d [element 2, element 0] : | array_flow.rb:1591:10:1591:10 | d [element 2, element 0] : | +| array_flow.rb:1587:5:1587:5 | d [element 2, element 0] : | array_flow.rb:1591:10:1591:10 | d [element 2, element 0] : | | array_flow.rb:1587:9:1587:9 | a [element 2] : | array_flow.rb:1587:9:1587:19 | call to zip [element 2, element 0] : | | array_flow.rb:1587:9:1587:9 | a [element 2] : | array_flow.rb:1587:9:1587:19 | call to zip [element 2, element 0] : | -| array_flow.rb:1587:9:1587:19 | call to zip [element 0, element 2] : | array_flow.rb:1589:10:1589:10 | d [element 0, element 2] : | -| array_flow.rb:1587:9:1587:19 | call to zip [element 0, element 2] : | array_flow.rb:1589:10:1589:10 | d [element 0, element 2] : | -| array_flow.rb:1587:9:1587:19 | call to zip [element 1, element 1] : | array_flow.rb:1590:10:1590:10 | d [element 1, element 1] : | -| array_flow.rb:1587:9:1587:19 | call to zip [element 1, element 1] : | array_flow.rb:1590:10:1590:10 | d [element 1, element 1] : | -| array_flow.rb:1587:9:1587:19 | call to zip [element 2, element 0] : | array_flow.rb:1591:10:1591:10 | d [element 2, element 0] : | -| array_flow.rb:1587:9:1587:19 | call to zip [element 2, element 0] : | array_flow.rb:1591:10:1591:10 | d [element 2, element 0] : | +| array_flow.rb:1587:9:1587:19 | call to zip [element 0, element 2] : | array_flow.rb:1587:5:1587:5 | d [element 0, element 2] : | +| array_flow.rb:1587:9:1587:19 | call to zip [element 0, element 2] : | array_flow.rb:1587:5:1587:5 | d [element 0, element 2] : | +| array_flow.rb:1587:9:1587:19 | call to zip [element 1, element 1] : | array_flow.rb:1587:5:1587:5 | d [element 1, element 1] : | +| array_flow.rb:1587:9:1587:19 | call to zip [element 1, element 1] : | array_flow.rb:1587:5:1587:5 | d [element 1, element 1] : | +| array_flow.rb:1587:9:1587:19 | call to zip [element 2, element 0] : | array_flow.rb:1587:5:1587:5 | d [element 2, element 0] : | +| array_flow.rb:1587:9:1587:19 | call to zip [element 2, element 0] : | array_flow.rb:1587:5:1587:5 | d [element 2, element 0] : | | array_flow.rb:1587:15:1587:15 | b [element 1] : | array_flow.rb:1587:9:1587:19 | call to zip [element 1, element 1] : | | array_flow.rb:1587:15:1587:15 | b [element 1] : | array_flow.rb:1587:9:1587:19 | call to zip [element 1, element 1] : | | array_flow.rb:1587:18:1587:18 | c [element 0] : | array_flow.rb:1587:9:1587:19 | call to zip [element 0, element 2] : | @@ -3341,18 +4144,24 @@ edges | array_flow.rb:1594:14:1594:14 | x [element 1] : | array_flow.rb:1594:14:1594:17 | ...[...] | | array_flow.rb:1595:14:1595:14 | x [element 2] : | array_flow.rb:1595:14:1595:17 | ...[...] | | array_flow.rb:1595:14:1595:14 | x [element 2] : | array_flow.rb:1595:14:1595:17 | ...[...] | -| array_flow.rb:1600:16:1600:28 | call to source : | array_flow.rb:1602:9:1602:9 | a [element 2] : | -| array_flow.rb:1600:16:1600:28 | call to source : | array_flow.rb:1602:9:1602:9 | a [element 2] : | -| array_flow.rb:1601:13:1601:25 | call to source : | array_flow.rb:1602:13:1602:13 | b [element 1] : | -| array_flow.rb:1601:13:1601:25 | call to source : | array_flow.rb:1602:13:1602:13 | b [element 1] : | +| array_flow.rb:1600:5:1600:5 | a [element 2] : | array_flow.rb:1602:9:1602:9 | a [element 2] : | +| array_flow.rb:1600:5:1600:5 | a [element 2] : | array_flow.rb:1602:9:1602:9 | a [element 2] : | +| array_flow.rb:1600:16:1600:28 | call to source : | array_flow.rb:1600:5:1600:5 | a [element 2] : | +| array_flow.rb:1600:16:1600:28 | call to source : | array_flow.rb:1600:5:1600:5 | a [element 2] : | +| array_flow.rb:1601:5:1601:5 | b [element 1] : | array_flow.rb:1602:13:1602:13 | b [element 1] : | +| array_flow.rb:1601:5:1601:5 | b [element 1] : | array_flow.rb:1602:13:1602:13 | b [element 1] : | +| array_flow.rb:1601:13:1601:25 | call to source : | array_flow.rb:1601:5:1601:5 | b [element 1] : | +| array_flow.rb:1601:13:1601:25 | call to source : | array_flow.rb:1601:5:1601:5 | b [element 1] : | +| array_flow.rb:1602:5:1602:5 | c [element] : | array_flow.rb:1603:10:1603:10 | c [element] : | +| array_flow.rb:1602:5:1602:5 | c [element] : | array_flow.rb:1603:10:1603:10 | c [element] : | +| array_flow.rb:1602:5:1602:5 | c [element] : | array_flow.rb:1604:10:1604:10 | c [element] : | +| array_flow.rb:1602:5:1602:5 | c [element] : | array_flow.rb:1604:10:1604:10 | c [element] : | +| array_flow.rb:1602:5:1602:5 | c [element] : | array_flow.rb:1605:10:1605:10 | c [element] : | +| array_flow.rb:1602:5:1602:5 | c [element] : | array_flow.rb:1605:10:1605:10 | c [element] : | | array_flow.rb:1602:9:1602:9 | a [element 2] : | array_flow.rb:1602:9:1602:13 | ... \| ... [element] : | | array_flow.rb:1602:9:1602:9 | a [element 2] : | array_flow.rb:1602:9:1602:13 | ... \| ... [element] : | -| array_flow.rb:1602:9:1602:13 | ... \| ... [element] : | array_flow.rb:1603:10:1603:10 | c [element] : | -| array_flow.rb:1602:9:1602:13 | ... \| ... [element] : | array_flow.rb:1603:10:1603:10 | c [element] : | -| array_flow.rb:1602:9:1602:13 | ... \| ... [element] : | array_flow.rb:1604:10:1604:10 | c [element] : | -| array_flow.rb:1602:9:1602:13 | ... \| ... [element] : | array_flow.rb:1604:10:1604:10 | c [element] : | -| array_flow.rb:1602:9:1602:13 | ... \| ... [element] : | array_flow.rb:1605:10:1605:10 | c [element] : | -| array_flow.rb:1602:9:1602:13 | ... \| ... [element] : | array_flow.rb:1605:10:1605:10 | c [element] : | +| array_flow.rb:1602:9:1602:13 | ... \| ... [element] : | array_flow.rb:1602:5:1602:5 | c [element] : | +| array_flow.rb:1602:9:1602:13 | ... \| ... [element] : | array_flow.rb:1602:5:1602:5 | c [element] : | | array_flow.rb:1602:13:1602:13 | b [element 1] : | array_flow.rb:1602:9:1602:13 | ... \| ... [element] : | | array_flow.rb:1602:13:1602:13 | b [element 1] : | array_flow.rb:1602:9:1602:13 | ... \| ... [element] : | | array_flow.rb:1603:10:1603:10 | c [element] : | array_flow.rb:1603:10:1603:13 | ...[...] | @@ -3432,6 +4241,8 @@ edges | array_flow.rb:1631:10:1631:10 | a [element] : | array_flow.rb:1631:10:1631:15 | ...[...] | | array_flow.rb:1631:10:1631:10 | a [element] : | array_flow.rb:1631:10:1631:15 | ...[...] | nodes +| array_flow.rb:2:5:2:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:2:5:2:5 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:2:9:2:20 | * ... [element 0] : | semmle.label | * ... [element 0] : | | array_flow.rb:2:9:2:20 | * ... [element 0] : | semmle.label | * ... [element 0] : | | array_flow.rb:2:10:2:20 | call to source : | semmle.label | call to source : | @@ -3444,6 +4255,8 @@ nodes | array_flow.rb:5:10:5:10 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:5:10:5:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:5:10:5:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:9:5:9:5 | a [element 1] : | semmle.label | a [element 1] : | +| array_flow.rb:9:5:9:5 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:9:13:9:21 | call to source : | semmle.label | call to source : | | array_flow.rb:9:13:9:21 | call to source : | semmle.label | call to source : | | array_flow.rb:11:10:11:10 | a [element 1] : | semmle.label | a [element 1] : | @@ -3454,6 +4267,8 @@ nodes | array_flow.rb:13:10:13:10 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:13:10:13:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:13:10:13:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:17:5:17:5 | a [element] : | semmle.label | a [element] : | +| array_flow.rb:17:5:17:5 | a [element] : | semmle.label | a [element] : | | array_flow.rb:17:9:17:33 | call to new [element] : | semmle.label | call to new [element] : | | array_flow.rb:17:9:17:33 | call to new [element] : | semmle.label | call to new [element] : | | array_flow.rb:17:22:17:32 | call to source : | semmle.label | call to source : | @@ -3466,6 +4281,8 @@ nodes | array_flow.rb:19:10:19:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:19:10:19:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:19:10:19:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:21:5:21:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:21:5:21:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:21:9:21:20 | call to new [element] : | semmle.label | call to new [element] : | | array_flow.rb:21:9:21:20 | call to new [element] : | semmle.label | call to new [element] : | | array_flow.rb:21:19:21:19 | a [element] : | semmle.label | a [element] : | @@ -3478,6 +4295,8 @@ nodes | array_flow.rb:23:10:23:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:23:10:23:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:23:10:23:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:25:5:25:5 | c [element] : | semmle.label | c [element] : | +| array_flow.rb:25:5:25:5 | c [element] : | semmle.label | c [element] : | | array_flow.rb:25:9:27:7 | call to new [element] : | semmle.label | call to new [element] : | | array_flow.rb:25:9:27:7 | call to new [element] : | semmle.label | call to new [element] : | | array_flow.rb:26:9:26:19 | call to source : | semmle.label | call to source : | @@ -3490,8 +4309,12 @@ nodes | array_flow.rb:29:10:29:10 | c [element] : | semmle.label | c [element] : | | array_flow.rb:29:10:29:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:29:10:29:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:33:5:33:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:33:5:33:5 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:33:10:33:18 | call to source : | semmle.label | call to source : | | array_flow.rb:33:10:33:18 | call to source : | semmle.label | call to source : | +| array_flow.rb:34:5:34:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:34:5:34:5 | b [element 0] : | semmle.label | b [element 0] : | | array_flow.rb:34:9:34:28 | call to try_convert [element 0] : | semmle.label | call to try_convert [element 0] : | | array_flow.rb:34:9:34:28 | call to try_convert [element 0] : | semmle.label | call to try_convert [element 0] : | | array_flow.rb:34:27:34:27 | a [element 0] : | semmle.label | a [element 0] : | @@ -3500,10 +4323,16 @@ nodes | array_flow.rb:35:10:35:10 | b [element 0] : | semmle.label | b [element 0] : | | array_flow.rb:35:10:35:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:35:10:35:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:40:5:40:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:40:5:40:5 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:40:10:40:20 | call to source : | semmle.label | call to source : | | array_flow.rb:40:10:40:20 | call to source : | semmle.label | call to source : | +| array_flow.rb:41:5:41:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:41:5:41:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:41:16:41:26 | call to source : | semmle.label | call to source : | | array_flow.rb:41:16:41:26 | call to source : | semmle.label | call to source : | +| array_flow.rb:42:5:42:5 | c [element] : | semmle.label | c [element] : | +| array_flow.rb:42:5:42:5 | c [element] : | semmle.label | c [element] : | | array_flow.rb:42:9:42:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:42:9:42:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:42:9:42:13 | ... & ... [element] : | semmle.label | ... & ... [element] : | @@ -3518,8 +4347,12 @@ nodes | array_flow.rb:44:10:44:10 | c [element] : | semmle.label | c [element] : | | array_flow.rb:44:10:44:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:44:10:44:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:48:5:48:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:48:5:48:5 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:48:10:48:18 | call to source : | semmle.label | call to source : | | array_flow.rb:48:10:48:18 | call to source : | semmle.label | call to source : | +| array_flow.rb:49:5:49:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:49:5:49:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:49:9:49:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:49:9:49:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:49:9:49:13 | ... * ... [element] : | semmle.label | ... * ... [element] : | @@ -3532,10 +4365,18 @@ nodes | array_flow.rb:51:10:51:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:51:10:51:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:51:10:51:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:55:5:55:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:55:5:55:5 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:55:10:55:20 | call to source : | semmle.label | call to source : | | array_flow.rb:55:10:55:20 | call to source : | semmle.label | call to source : | +| array_flow.rb:56:5:56:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:56:5:56:5 | b [element 1] : | semmle.label | b [element 1] : | | array_flow.rb:56:13:56:23 | call to source : | semmle.label | call to source : | | array_flow.rb:56:13:56:23 | call to source : | semmle.label | call to source : | +| array_flow.rb:57:5:57:5 | c [element 0] : | semmle.label | c [element 0] : | +| array_flow.rb:57:5:57:5 | c [element 0] : | semmle.label | c [element 0] : | +| array_flow.rb:57:5:57:5 | c [element] : | semmle.label | c [element] : | +| array_flow.rb:57:5:57:5 | c [element] : | semmle.label | c [element] : | | array_flow.rb:57:9:57:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:57:9:57:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:57:9:57:13 | ... + ... [element 0] : | semmle.label | ... + ... [element 0] : | @@ -3554,8 +4395,12 @@ nodes | array_flow.rb:59:10:59:10 | c [element] : | semmle.label | c [element] : | | array_flow.rb:59:10:59:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:59:10:59:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:63:5:63:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:63:5:63:5 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:63:10:63:20 | call to source : | semmle.label | call to source : | | array_flow.rb:63:10:63:20 | call to source : | semmle.label | call to source : | +| array_flow.rb:65:5:65:5 | c [element] : | semmle.label | c [element] : | +| array_flow.rb:65:5:65:5 | c [element] : | semmle.label | c [element] : | | array_flow.rb:65:9:65:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:65:9:65:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:65:9:65:13 | ... - ... [element] : | semmle.label | ... - ... [element] : | @@ -3568,8 +4413,15 @@ nodes | array_flow.rb:67:10:67:10 | c [element] : | semmle.label | c [element] : | | array_flow.rb:67:10:67:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:67:10:67:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:71:5:71:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:71:5:71:5 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:71:10:71:20 | call to source : | semmle.label | call to source : | | array_flow.rb:71:10:71:20 | call to source : | semmle.label | call to source : | +| array_flow.rb:72:5:72:5 | b : | semmle.label | b : | +| array_flow.rb:72:5:72:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:72:5:72:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:72:5:72:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:72:5:72:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:72:9:72:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:72:9:72:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:72:9:72:9 | a [element 0] : | semmle.label | a [element 0] : | @@ -3602,14 +4454,24 @@ nodes | array_flow.rb:76:10:76:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:76:10:76:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:76:10:76:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:80:5:80:5 | a [element 1] : | semmle.label | a [element 1] : | +| array_flow.rb:80:5:80:5 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:80:13:80:21 | call to source : | semmle.label | call to source : | | array_flow.rb:80:13:80:21 | call to source : | semmle.label | call to source : | +| array_flow.rb:81:8:81:8 | c : | semmle.label | c : | +| array_flow.rb:81:8:81:8 | c : | semmle.label | c : | +| array_flow.rb:81:15:81:15 | __synth__3 [element 1] : | semmle.label | __synth__3 [element 1] : | +| array_flow.rb:81:15:81:15 | __synth__3 [element 1] : | semmle.label | __synth__3 [element 1] : | | array_flow.rb:81:15:81:15 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:81:15:81:15 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:83:10:83:10 | c | semmle.label | c | | array_flow.rb:83:10:83:10 | c | semmle.label | c | +| array_flow.rb:88:5:88:5 | a [element 1] : | semmle.label | a [element 1] : | +| array_flow.rb:88:5:88:5 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:88:13:88:22 | call to source : | semmle.label | call to source : | | array_flow.rb:88:13:88:22 | call to source : | semmle.label | call to source : | +| array_flow.rb:89:5:89:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:89:5:89:5 | b [element 1] : | semmle.label | b [element 1] : | | array_flow.rb:89:9:89:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:89:9:89:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:89:9:89:15 | ...[...] [element 1] : | semmle.label | ...[...] [element 1] : | @@ -3622,8 +4484,12 @@ nodes | array_flow.rb:92:10:92:10 | b [element 1] : | semmle.label | b [element 1] : | | array_flow.rb:92:10:92:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:92:10:92:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:96:5:96:5 | a [element 1] : | semmle.label | a [element 1] : | +| array_flow.rb:96:5:96:5 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:96:13:96:22 | call to source : | semmle.label | call to source : | | array_flow.rb:96:13:96:22 | call to source : | semmle.label | call to source : | +| array_flow.rb:97:5:97:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:97:5:97:5 | b [element 1] : | semmle.label | b [element 1] : | | array_flow.rb:97:9:97:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:97:9:97:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:97:9:97:15 | ...[...] [element 1] : | semmle.label | ...[...] [element 1] : | @@ -3636,8 +4502,12 @@ nodes | array_flow.rb:101:10:101:10 | b [element 1] : | semmle.label | b [element 1] : | | array_flow.rb:101:10:101:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:101:10:101:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:103:5:103:5 | a [element 1] : | semmle.label | a [element 1] : | +| array_flow.rb:103:5:103:5 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:103:13:103:24 | call to source : | semmle.label | call to source : | | array_flow.rb:103:13:103:24 | call to source : | semmle.label | call to source : | +| array_flow.rb:104:5:104:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:104:5:104:5 | b [element 1] : | semmle.label | b [element 1] : | | array_flow.rb:104:9:104:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:104:9:104:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:104:9:104:16 | ...[...] [element 1] : | semmle.label | ...[...] [element 1] : | @@ -3646,10 +4516,16 @@ nodes | array_flow.rb:106:10:106:10 | b [element 1] : | semmle.label | b [element 1] : | | array_flow.rb:106:10:106:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:106:10:106:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:109:5:109:5 | a [element 1] : | semmle.label | a [element 1] : | +| array_flow.rb:109:5:109:5 | a [element 1] : | semmle.label | a [element 1] : | +| array_flow.rb:109:5:109:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:109:5:109:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:109:13:109:24 | call to source : | semmle.label | call to source : | | array_flow.rb:109:13:109:24 | call to source : | semmle.label | call to source : | | array_flow.rb:109:30:109:41 | call to source : | semmle.label | call to source : | | array_flow.rb:109:30:109:41 | call to source : | semmle.label | call to source : | +| array_flow.rb:110:5:110:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:110:5:110:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:110:9:110:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:110:9:110:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:110:9:110:9 | a [element 3] : | semmle.label | a [element 3] : | @@ -3664,6 +4540,8 @@ nodes | array_flow.rb:112:10:112:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:112:10:112:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:112:10:112:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:114:5:114:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:114:5:114:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:114:9:114:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:114:9:114:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:114:9:114:9 | a [element 3] : | semmle.label | a [element 3] : | @@ -3742,6 +4620,8 @@ nodes | array_flow.rb:148:10:148:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:148:10:148:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:148:10:148:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:152:5:152:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:152:5:152:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:152:16:152:25 | call to source : | semmle.label | call to source : | | array_flow.rb:152:16:152:25 | call to source : | semmle.label | call to source : | | array_flow.rb:153:5:153:5 | a [element 2] : | semmle.label | a [element 2] : | @@ -3750,6 +4630,8 @@ nodes | array_flow.rb:153:16:153:16 | x : | semmle.label | x : | | array_flow.rb:154:14:154:14 | x | semmle.label | x | | array_flow.rb:154:14:154:14 | x | semmle.label | x | +| array_flow.rb:159:5:159:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:159:5:159:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:159:16:159:25 | call to source : | semmle.label | call to source : | | array_flow.rb:159:16:159:25 | call to source : | semmle.label | call to source : | | array_flow.rb:160:5:160:5 | a [element 2] : | semmle.label | a [element 2] : | @@ -3758,8 +4640,14 @@ nodes | array_flow.rb:160:16:160:16 | x : | semmle.label | x : | | array_flow.rb:161:14:161:14 | x | semmle.label | x | | array_flow.rb:161:14:161:14 | x | semmle.label | x | +| array_flow.rb:166:5:166:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:166:5:166:5 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:166:10:166:21 | call to source : | semmle.label | call to source : | | array_flow.rb:166:10:166:21 | call to source : | semmle.label | call to source : | +| array_flow.rb:167:5:167:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:167:5:167:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:167:5:167:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:167:5:167:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:167:9:167:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:167:9:167:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:167:9:167:9 | a [element 0] : | semmle.label | a [element 0] : | @@ -3792,8 +4680,12 @@ nodes | array_flow.rb:171:10:171:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:171:10:171:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:171:10:171:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:177:5:177:5 | c [element 1] : | semmle.label | c [element 1] : | +| array_flow.rb:177:5:177:5 | c [element 1] : | semmle.label | c [element 1] : | | array_flow.rb:177:15:177:24 | call to source : | semmle.label | call to source : | | array_flow.rb:177:15:177:24 | call to source : | semmle.label | call to source : | +| array_flow.rb:178:5:178:5 | d [element 2, element 1] : | semmle.label | d [element 2, element 1] : | +| array_flow.rb:178:5:178:5 | d [element 2, element 1] : | semmle.label | d [element 2, element 1] : | | array_flow.rb:178:16:178:16 | c [element 1] : | semmle.label | c [element 1] : | | array_flow.rb:178:16:178:16 | c [element 1] : | semmle.label | c [element 1] : | | array_flow.rb:179:10:179:26 | ( ... ) | semmle.label | ( ... ) | @@ -3812,6 +4704,8 @@ nodes | array_flow.rb:180:11:180:22 | call to assoc [element 1] : | semmle.label | call to assoc [element 1] : | | array_flow.rb:180:11:180:25 | ...[...] : | semmle.label | ...[...] : | | array_flow.rb:180:11:180:25 | ...[...] : | semmle.label | ...[...] : | +| array_flow.rb:184:5:184:5 | a [element 1] : | semmle.label | a [element 1] : | +| array_flow.rb:184:5:184:5 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:184:13:184:22 | call to source : | semmle.label | call to source : | | array_flow.rb:184:13:184:22 | call to source : | semmle.label | call to source : | | array_flow.rb:186:10:186:10 | a [element 1] : | semmle.label | a [element 1] : | @@ -3822,8 +4716,12 @@ nodes | array_flow.rb:188:10:188:10 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:188:10:188:16 | call to at | semmle.label | call to at | | array_flow.rb:188:10:188:16 | call to at | semmle.label | call to at | +| array_flow.rb:192:5:192:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:192:5:192:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:192:16:192:25 | call to source : | semmle.label | call to source : | | array_flow.rb:192:16:192:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:193:5:193:5 | b : | semmle.label | b : | +| array_flow.rb:193:5:193:5 | b : | semmle.label | b : | | array_flow.rb:193:9:193:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:193:9:193:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:193:9:195:7 | call to bsearch : | semmle.label | call to bsearch : | @@ -3834,6 +4732,8 @@ nodes | array_flow.rb:194:14:194:14 | x | semmle.label | x | | array_flow.rb:196:10:196:10 | b | semmle.label | b | | array_flow.rb:196:10:196:10 | b | semmle.label | b | +| array_flow.rb:200:5:200:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:200:5:200:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:200:16:200:25 | call to source : | semmle.label | call to source : | | array_flow.rb:200:16:200:25 | call to source : | semmle.label | call to source : | | array_flow.rb:201:9:201:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -3842,6 +4742,8 @@ nodes | array_flow.rb:201:29:201:29 | x : | semmle.label | x : | | array_flow.rb:202:14:202:14 | x | semmle.label | x | | array_flow.rb:202:14:202:14 | x | semmle.label | x | +| array_flow.rb:208:5:208:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:208:5:208:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:208:16:208:25 | call to source : | semmle.label | call to source : | | array_flow.rb:208:16:208:25 | call to source : | semmle.label | call to source : | | array_flow.rb:209:5:209:5 | a [element 2] : | semmle.label | a [element 2] : | @@ -3850,6 +4752,10 @@ nodes | array_flow.rb:209:17:209:17 | x : | semmle.label | x : | | array_flow.rb:210:14:210:14 | x | semmle.label | x | | array_flow.rb:210:14:210:14 | x | semmle.label | x | +| array_flow.rb:215:5:215:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:215:5:215:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:215:5:215:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:215:5:215:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:215:16:215:27 | call to source : | semmle.label | call to source : | | array_flow.rb:215:16:215:27 | call to source : | semmle.label | call to source : | | array_flow.rb:215:30:215:41 | call to source : | semmle.label | call to source : | @@ -3866,8 +4772,12 @@ nodes | array_flow.rb:217:14:217:14 | x | semmle.label | x | | array_flow.rb:218:14:218:14 | y | semmle.label | y | | array_flow.rb:218:14:218:14 | y | semmle.label | y | +| array_flow.rb:231:5:231:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:231:5:231:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:231:16:231:27 | call to source : | semmle.label | call to source : | | array_flow.rb:231:16:231:27 | call to source : | semmle.label | call to source : | +| array_flow.rb:232:5:232:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:232:5:232:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:232:9:232:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:232:9:232:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:232:9:235:7 | call to collect [element] : | semmle.label | call to collect [element] : | @@ -3882,8 +4792,12 @@ nodes | array_flow.rb:236:10:236:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:236:10:236:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:236:10:236:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:240:5:240:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:240:5:240:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:240:16:240:27 | call to source : | semmle.label | call to source : | | array_flow.rb:240:16:240:27 | call to source : | semmle.label | call to source : | +| array_flow.rb:241:5:241:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:241:5:241:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:241:9:241:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:241:9:241:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:241:9:241:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -3904,8 +4818,12 @@ nodes | array_flow.rb:246:10:246:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:246:10:246:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:246:10:246:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:250:5:250:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:250:5:250:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:250:16:250:27 | call to source : | semmle.label | call to source : | | array_flow.rb:250:16:250:27 | call to source : | semmle.label | call to source : | +| array_flow.rb:251:5:251:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:251:5:251:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:251:9:251:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:251:9:251:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:251:9:254:7 | call to collect_concat [element] : | semmle.label | call to collect_concat [element] : | @@ -3920,6 +4838,8 @@ nodes | array_flow.rb:255:10:255:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:255:10:255:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:255:10:255:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:256:5:256:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:256:5:256:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:256:9:256:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:256:9:256:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:256:9:259:7 | call to collect_concat [element] : | semmle.label | call to collect_concat [element] : | @@ -3934,8 +4854,12 @@ nodes | array_flow.rb:260:10:260:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:260:10:260:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:260:10:260:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:264:5:264:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:264:5:264:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:264:16:264:25 | call to source : | semmle.label | call to source : | | array_flow.rb:264:16:264:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:265:5:265:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:265:5:265:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:265:9:265:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:265:9:265:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:265:9:267:7 | call to combination [element 2] : | semmle.label | call to combination [element 2] : | @@ -3950,8 +4874,12 @@ nodes | array_flow.rb:269:10:269:10 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:269:10:269:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:269:10:269:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:273:5:273:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:273:5:273:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:273:16:273:25 | call to source : | semmle.label | call to source : | | array_flow.rb:273:16:273:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:274:5:274:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:274:5:274:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:274:9:274:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:274:9:274:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:274:9:274:17 | call to compact [element] : | semmle.label | call to compact [element] : | @@ -3960,8 +4888,12 @@ nodes | array_flow.rb:275:10:275:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:275:10:275:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:275:10:275:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:279:5:279:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:279:5:279:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:279:16:279:25 | call to source : | semmle.label | call to source : | | array_flow.rb:279:16:279:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:280:5:280:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:280:5:280:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:280:9:280:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:280:9:280:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:280:9:280:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -3976,8 +4908,12 @@ nodes | array_flow.rb:282:10:282:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:282:10:282:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:282:10:282:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:286:5:286:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:286:5:286:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:286:16:286:27 | call to source : | semmle.label | call to source : | | array_flow.rb:286:16:286:27 | call to source : | semmle.label | call to source : | +| array_flow.rb:287:5:287:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:287:5:287:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:287:16:287:27 | call to source : | semmle.label | call to source : | | array_flow.rb:287:16:287:27 | call to source : | semmle.label | call to source : | | array_flow.rb:288:5:288:5 | [post] a [element] : | semmle.label | [post] a [element] : | @@ -3994,6 +4930,8 @@ nodes | array_flow.rb:290:10:290:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:290:10:290:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:290:10:290:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:294:5:294:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:294:5:294:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:294:16:294:25 | call to source : | semmle.label | call to source : | | array_flow.rb:294:16:294:25 | call to source : | semmle.label | call to source : | | array_flow.rb:295:5:295:5 | a [element 2] : | semmle.label | a [element 2] : | @@ -4002,6 +4940,8 @@ nodes | array_flow.rb:295:17:295:17 | x : | semmle.label | x : | | array_flow.rb:296:14:296:14 | x | semmle.label | x | | array_flow.rb:296:14:296:14 | x | semmle.label | x | +| array_flow.rb:301:5:301:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:301:5:301:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:301:16:301:25 | call to source : | semmle.label | call to source : | | array_flow.rb:301:16:301:25 | call to source : | semmle.label | call to source : | | array_flow.rb:302:5:302:5 | a [element 2] : | semmle.label | a [element 2] : | @@ -4010,8 +4950,12 @@ nodes | array_flow.rb:302:20:302:20 | x : | semmle.label | x : | | array_flow.rb:303:14:303:14 | x | semmle.label | x | | array_flow.rb:303:14:303:14 | x | semmle.label | x | +| array_flow.rb:308:5:308:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:308:5:308:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:308:16:308:25 | call to source : | semmle.label | call to source : | | array_flow.rb:308:16:308:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:309:5:309:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:309:5:309:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:309:9:309:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:309:9:309:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:309:9:309:21 | call to deconstruct [element 2] : | semmle.label | call to deconstruct [element 2] : | @@ -4020,8 +4964,12 @@ nodes | array_flow.rb:312:10:312:10 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:312:10:312:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:312:10:312:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:316:5:316:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:316:5:316:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:316:16:316:27 | call to source : | semmle.label | call to source : | | array_flow.rb:316:16:316:27 | call to source : | semmle.label | call to source : | +| array_flow.rb:317:5:317:5 | b : | semmle.label | b : | +| array_flow.rb:317:5:317:5 | b : | semmle.label | b : | | array_flow.rb:317:9:317:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:317:9:317:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:317:9:317:36 | call to delete : | semmle.label | call to delete : | @@ -4030,10 +4978,16 @@ nodes | array_flow.rb:317:23:317:34 | call to source : | semmle.label | call to source : | | array_flow.rb:318:10:318:10 | b | semmle.label | b | | array_flow.rb:318:10:318:10 | b | semmle.label | b | +| array_flow.rb:325:5:325:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:325:5:325:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:325:5:325:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:325:5:325:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:325:16:325:27 | call to source : | semmle.label | call to source : | | array_flow.rb:325:16:325:27 | call to source : | semmle.label | call to source : | | array_flow.rb:325:30:325:41 | call to source : | semmle.label | call to source : | | array_flow.rb:325:30:325:41 | call to source : | semmle.label | call to source : | +| array_flow.rb:326:5:326:5 | b : | semmle.label | b : | +| array_flow.rb:326:5:326:5 | b : | semmle.label | b : | | array_flow.rb:326:9:326:9 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | | array_flow.rb:326:9:326:9 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | | array_flow.rb:326:9:326:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -4048,10 +5002,16 @@ nodes | array_flow.rb:328:10:328:10 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:328:10:328:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:328:10:328:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:330:5:330:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:330:5:330:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:330:5:330:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:330:5:330:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:330:16:330:27 | call to source : | semmle.label | call to source : | | array_flow.rb:330:16:330:27 | call to source : | semmle.label | call to source : | | array_flow.rb:330:30:330:41 | call to source : | semmle.label | call to source : | | array_flow.rb:330:30:330:41 | call to source : | semmle.label | call to source : | +| array_flow.rb:331:5:331:5 | b : | semmle.label | b : | +| array_flow.rb:331:5:331:5 | b : | semmle.label | b : | | array_flow.rb:331:9:331:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:331:9:331:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:331:9:331:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -4070,8 +5030,12 @@ nodes | array_flow.rb:334:10:334:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:334:10:334:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:334:10:334:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:338:5:338:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:338:5:338:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:338:16:338:25 | call to source : | semmle.label | call to source : | | array_flow.rb:338:16:338:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:339:5:339:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:339:5:339:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:339:9:339:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:339:9:339:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:339:9:339:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -4098,8 +5062,12 @@ nodes | array_flow.rb:345:10:345:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:345:10:345:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:345:10:345:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:349:5:349:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:349:5:349:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:349:16:349:25 | call to source : | semmle.label | call to source : | | array_flow.rb:349:16:349:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:350:5:350:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:350:5:350:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:350:9:350:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:350:9:350:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:350:9:350:25 | call to difference [element] : | semmle.label | call to difference [element] : | @@ -4108,6 +5076,10 @@ nodes | array_flow.rb:351:10:351:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:351:10:351:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:351:10:351:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:355:5:355:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:355:5:355:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:355:5:355:5 | a [element 3, element 1] : | semmle.label | a [element 3, element 1] : | +| array_flow.rb:355:5:355:5 | a [element 3, element 1] : | semmle.label | a [element 3, element 1] : | | array_flow.rb:355:16:355:27 | call to source : | semmle.label | call to source : | | array_flow.rb:355:16:355:27 | call to source : | semmle.label | call to source : | | array_flow.rb:355:34:355:45 | call to source : | semmle.label | call to source : | @@ -4124,8 +5096,12 @@ nodes | array_flow.rb:360:10:360:10 | a [element 3, element 1] : | semmle.label | a [element 3, element 1] : | | array_flow.rb:360:10:360:19 | call to dig | semmle.label | call to dig | | array_flow.rb:360:10:360:19 | call to dig | semmle.label | call to dig | +| array_flow.rb:364:5:364:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:364:5:364:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:364:16:364:27 | call to source : | semmle.label | call to source : | | array_flow.rb:364:16:364:27 | call to source : | semmle.label | call to source : | +| array_flow.rb:365:5:365:5 | b : | semmle.label | b : | +| array_flow.rb:365:5:365:5 | b : | semmle.label | b : | | array_flow.rb:365:9:365:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:365:9:365:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:365:9:367:7 | call to detect : | semmle.label | call to detect : | @@ -4138,10 +5114,16 @@ nodes | array_flow.rb:366:14:366:14 | x | semmle.label | x | | array_flow.rb:368:10:368:10 | b | semmle.label | b | | array_flow.rb:368:10:368:10 | b | semmle.label | b | +| array_flow.rb:372:5:372:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:372:5:372:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:372:5:372:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:372:5:372:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:372:16:372:27 | call to source : | semmle.label | call to source : | | array_flow.rb:372:16:372:27 | call to source : | semmle.label | call to source : | | array_flow.rb:372:30:372:41 | call to source : | semmle.label | call to source : | | array_flow.rb:372:30:372:41 | call to source : | semmle.label | call to source : | +| array_flow.rb:373:5:373:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:373:5:373:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:373:9:373:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:373:9:373:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:373:9:373:9 | a [element 3] : | semmle.label | a [element 3] : | @@ -4152,6 +5134,10 @@ nodes | array_flow.rb:374:10:374:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:374:10:374:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:374:10:374:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:375:5:375:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:375:5:375:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:375:5:375:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:375:5:375:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:375:9:375:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:375:9:375:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:375:9:375:9 | a [element 3] : | semmle.label | a [element 3] : | @@ -4174,6 +5160,10 @@ nodes | array_flow.rb:379:5:379:5 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:379:12:379:23 | call to source : | semmle.label | call to source : | | array_flow.rb:379:12:379:23 | call to source : | semmle.label | call to source : | +| array_flow.rb:380:5:380:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:380:5:380:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:380:5:380:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:380:5:380:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:380:9:380:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:380:9:380:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:380:9:380:9 | a [element] : | semmle.label | a [element] : | @@ -4188,6 +5178,8 @@ nodes | array_flow.rb:381:10:381:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:381:10:381:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:381:10:381:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:382:5:382:5 | c [element] : | semmle.label | c [element] : | +| array_flow.rb:382:5:382:5 | c [element] : | semmle.label | c [element] : | | array_flow.rb:382:9:382:9 | b [element] : | semmle.label | b [element] : | | array_flow.rb:382:9:382:9 | b [element] : | semmle.label | b [element] : | | array_flow.rb:382:9:382:19 | call to drop [element] : | semmle.label | call to drop [element] : | @@ -4196,10 +5188,16 @@ nodes | array_flow.rb:383:10:383:10 | c [element] : | semmle.label | c [element] : | | array_flow.rb:383:10:383:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:383:10:383:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:387:5:387:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:387:5:387:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:387:5:387:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:387:5:387:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:387:16:387:27 | call to source : | semmle.label | call to source : | | array_flow.rb:387:16:387:27 | call to source : | semmle.label | call to source : | | array_flow.rb:387:30:387:41 | call to source : | semmle.label | call to source : | | array_flow.rb:387:30:387:41 | call to source : | semmle.label | call to source : | +| array_flow.rb:388:5:388:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:388:5:388:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:388:9:388:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:388:9:388:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:388:9:388:9 | a [element 3] : | semmle.label | a [element 3] : | @@ -4214,8 +5212,12 @@ nodes | array_flow.rb:391:10:391:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:391:10:391:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:391:10:391:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:395:5:395:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:395:5:395:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:395:16:395:25 | call to source : | semmle.label | call to source : | | array_flow.rb:395:16:395:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:396:5:396:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:396:5:396:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:396:9:396:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:396:9:396:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:396:9:398:7 | call to each [element 2] : | semmle.label | call to each [element 2] : | @@ -4228,12 +5230,16 @@ nodes | array_flow.rb:399:10:399:10 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:399:10:399:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:399:10:399:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:403:5:403:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:403:5:403:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:403:16:403:25 | call to source : | semmle.label | call to source : | | array_flow.rb:403:16:403:25 | call to source : | semmle.label | call to source : | -| array_flow.rb:404:9:406:7 | ... = ... : | semmle.label | ... = ... : | -| array_flow.rb:404:9:406:7 | ... = ... : | semmle.label | ... = ... : | +| array_flow.rb:404:5:404:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:404:5:404:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:404:9:406:7 | __synth__0__1 : | semmle.label | __synth__0__1 : | | array_flow.rb:404:9:406:7 | __synth__0__1 : | semmle.label | __synth__0__1 : | +| array_flow.rb:404:13:404:13 | x : | semmle.label | x : | +| array_flow.rb:404:13:404:13 | x : | semmle.label | x : | | array_flow.rb:404:18:404:18 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:404:18:404:18 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:405:14:405:14 | x | semmle.label | x | @@ -4244,6 +5250,8 @@ nodes | array_flow.rb:408:10:408:10 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:408:10:408:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:408:10:408:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:412:5:412:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:412:5:412:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:412:16:412:25 | call to source : | semmle.label | call to source : | | array_flow.rb:412:16:412:25 | call to source : | semmle.label | call to source : | | array_flow.rb:413:5:413:5 | a [element 2] : | semmle.label | a [element 2] : | @@ -4256,8 +5264,12 @@ nodes | array_flow.rb:414:15:414:15 | x [element] : | semmle.label | x [element] : | | array_flow.rb:414:15:414:18 | ...[...] : | semmle.label | ...[...] : | | array_flow.rb:414:15:414:18 | ...[...] : | semmle.label | ...[...] : | +| array_flow.rb:419:5:419:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:419:5:419:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:419:16:419:25 | call to source : | semmle.label | call to source : | | array_flow.rb:419:16:419:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:420:5:420:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:420:5:420:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:420:9:420:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:420:9:420:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:420:9:422:7 | call to each_entry [element 2] : | semmle.label | call to each_entry [element 2] : | @@ -4270,8 +5282,12 @@ nodes | array_flow.rb:423:10:423:10 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:423:10:423:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:423:10:423:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:427:5:427:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:427:5:427:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:427:16:427:25 | call to source : | semmle.label | call to source : | | array_flow.rb:427:16:427:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:428:5:428:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:428:5:428:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:428:9:428:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:428:9:428:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:428:9:430:7 | call to each_index [element 2] : | semmle.label | call to each_index [element 2] : | @@ -4280,6 +5296,8 @@ nodes | array_flow.rb:431:10:431:10 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:431:10:431:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:431:10:431:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:435:5:435:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:435:5:435:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:435:19:435:28 | call to source : | semmle.label | call to source : | | array_flow.rb:435:19:435:28 | call to source : | semmle.label | call to source : | | array_flow.rb:436:5:436:5 | a [element 3] : | semmle.label | a [element 3] : | @@ -4290,8 +5308,12 @@ nodes | array_flow.rb:437:14:437:14 | x [element] : | semmle.label | x [element] : | | array_flow.rb:437:14:437:17 | ...[...] | semmle.label | ...[...] | | array_flow.rb:437:14:437:17 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:442:5:442:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:442:5:442:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:442:19:442:28 | call to source : | semmle.label | call to source : | | array_flow.rb:442:19:442:28 | call to source : | semmle.label | call to source : | +| array_flow.rb:443:5:443:5 | b [element 3] : | semmle.label | b [element 3] : | +| array_flow.rb:443:5:443:5 | b [element 3] : | semmle.label | b [element 3] : | | array_flow.rb:443:9:443:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:443:9:443:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:443:9:446:7 | call to each_with_index [element 3] : | semmle.label | call to each_with_index [element 3] : | @@ -4304,8 +5326,12 @@ nodes | array_flow.rb:447:10:447:10 | b [element 3] : | semmle.label | b [element 3] : | | array_flow.rb:447:10:447:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:447:10:447:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:451:5:451:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:451:5:451:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:451:19:451:30 | call to source : | semmle.label | call to source : | | array_flow.rb:451:19:451:30 | call to source : | semmle.label | call to source : | +| array_flow.rb:452:5:452:5 | b : | semmle.label | b : | +| array_flow.rb:452:5:452:5 | b : | semmle.label | b : | | array_flow.rb:452:9:452:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:452:9:452:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:452:9:455:7 | call to each_with_object : | semmle.label | call to each_with_object : | @@ -4322,8 +5348,12 @@ nodes | array_flow.rb:454:14:454:14 | a | semmle.label | a | | array_flow.rb:456:10:456:10 | b | semmle.label | b | | array_flow.rb:456:10:456:10 | b | semmle.label | b | +| array_flow.rb:460:5:460:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:460:5:460:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:460:19:460:28 | call to source : | semmle.label | call to source : | | array_flow.rb:460:19:460:28 | call to source : | semmle.label | call to source : | +| array_flow.rb:461:5:461:5 | b [element 3] : | semmle.label | b [element 3] : | +| array_flow.rb:461:5:461:5 | b [element 3] : | semmle.label | b [element 3] : | | array_flow.rb:461:9:461:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:461:9:461:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:461:9:461:17 | call to entries [element 3] : | semmle.label | call to entries [element 3] : | @@ -4332,10 +5362,16 @@ nodes | array_flow.rb:462:10:462:10 | b [element 3] : | semmle.label | b [element 3] : | | array_flow.rb:462:10:462:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:462:10:462:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:466:5:466:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:466:5:466:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:466:5:466:5 | a [element 4] : | semmle.label | a [element 4] : | +| array_flow.rb:466:5:466:5 | a [element 4] : | semmle.label | a [element 4] : | | array_flow.rb:466:19:466:30 | call to source : | semmle.label | call to source : | | array_flow.rb:466:19:466:30 | call to source : | semmle.label | call to source : | | array_flow.rb:466:33:466:44 | call to source : | semmle.label | call to source : | | array_flow.rb:466:33:466:44 | call to source : | semmle.label | call to source : | +| array_flow.rb:467:5:467:5 | b : | semmle.label | b : | +| array_flow.rb:467:5:467:5 | b : | semmle.label | b : | | array_flow.rb:467:9:467:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:467:9:467:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:467:9:467:9 | a [element 4] : | semmle.label | a [element 4] : | @@ -4350,12 +5386,16 @@ nodes | array_flow.rb:468:14:468:14 | x | semmle.label | x | | array_flow.rb:470:10:470:10 | b | semmle.label | b | | array_flow.rb:470:10:470:10 | b | semmle.label | b | +| array_flow.rb:471:5:471:5 | b : | semmle.label | b : | +| array_flow.rb:471:5:471:5 | b : | semmle.label | b : | | array_flow.rb:471:9:471:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:471:9:471:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:471:9:471:18 | call to fetch : | semmle.label | call to fetch : | | array_flow.rb:471:9:471:18 | call to fetch : | semmle.label | call to fetch : | | array_flow.rb:472:10:472:10 | b | semmle.label | b | | array_flow.rb:472:10:472:10 | b | semmle.label | b | +| array_flow.rb:473:5:473:5 | b : | semmle.label | b : | +| array_flow.rb:473:5:473:5 | b : | semmle.label | b : | | array_flow.rb:473:9:473:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:473:9:473:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:473:9:473:32 | call to fetch : | semmle.label | call to fetch : | @@ -4364,12 +5404,16 @@ nodes | array_flow.rb:473:20:473:31 | call to source : | semmle.label | call to source : | | array_flow.rb:474:10:474:10 | b | semmle.label | b | | array_flow.rb:474:10:474:10 | b | semmle.label | b | +| array_flow.rb:475:5:475:5 | b : | semmle.label | b : | +| array_flow.rb:475:5:475:5 | b : | semmle.label | b : | | array_flow.rb:475:9:475:34 | call to fetch : | semmle.label | call to fetch : | | array_flow.rb:475:9:475:34 | call to fetch : | semmle.label | call to fetch : | | array_flow.rb:475:22:475:33 | call to source : | semmle.label | call to source : | | array_flow.rb:475:22:475:33 | call to source : | semmle.label | call to source : | | array_flow.rb:476:10:476:10 | b | semmle.label | b | | array_flow.rb:476:10:476:10 | b | semmle.label | b | +| array_flow.rb:477:5:477:5 | b : | semmle.label | b : | +| array_flow.rb:477:5:477:5 | b : | semmle.label | b : | | array_flow.rb:477:9:477:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:477:9:477:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:477:9:477:9 | a [element 4] : | semmle.label | a [element 4] : | @@ -4380,6 +5424,8 @@ nodes | array_flow.rb:477:20:477:31 | call to source : | semmle.label | call to source : | | array_flow.rb:478:10:478:10 | b | semmle.label | b | | array_flow.rb:478:10:478:10 | b | semmle.label | b | +| array_flow.rb:482:5:482:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:482:5:482:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:482:19:482:30 | call to source : | semmle.label | call to source : | | array_flow.rb:482:19:482:30 | call to source : | semmle.label | call to source : | | array_flow.rb:483:5:483:5 | [post] a [element] : | semmle.label | [post] a [element] : | @@ -4416,8 +5462,12 @@ nodes | array_flow.rb:494:10:494:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:494:10:494:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:494:10:494:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:498:5:498:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:498:5:498:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:498:19:498:28 | call to source : | semmle.label | call to source : | | array_flow.rb:498:19:498:28 | call to source : | semmle.label | call to source : | +| array_flow.rb:499:5:499:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:499:5:499:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:499:9:499:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:499:9:499:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:499:9:501:7 | call to filter [element] : | semmle.label | call to filter [element] : | @@ -4430,8 +5480,12 @@ nodes | array_flow.rb:502:10:502:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:502:10:502:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:502:10:502:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:506:5:506:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:506:5:506:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:506:19:506:28 | call to source : | semmle.label | call to source : | | array_flow.rb:506:19:506:28 | call to source : | semmle.label | call to source : | +| array_flow.rb:507:5:507:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:507:5:507:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:507:9:507:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:507:9:507:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:507:9:509:7 | call to filter_map [element] : | semmle.label | call to filter_map [element] : | @@ -4444,8 +5498,12 @@ nodes | array_flow.rb:510:10:510:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:510:10:510:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:510:10:510:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:514:5:514:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:514:5:514:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:514:19:514:28 | call to source : | semmle.label | call to source : | | array_flow.rb:514:19:514:28 | call to source : | semmle.label | call to source : | +| array_flow.rb:515:5:515:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:515:5:515:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:515:9:515:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:515:9:515:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:515:9:515:9 | a [element 3] : | semmle.label | a [element 3] : | @@ -4464,8 +5522,12 @@ nodes | array_flow.rb:520:10:520:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:520:10:520:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:520:10:520:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:524:5:524:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:524:5:524:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:524:19:524:30 | call to source : | semmle.label | call to source : | | array_flow.rb:524:19:524:30 | call to source : | semmle.label | call to source : | +| array_flow.rb:525:5:525:5 | b : | semmle.label | b : | +| array_flow.rb:525:5:525:5 | b : | semmle.label | b : | | array_flow.rb:525:9:525:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:525:9:525:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:525:9:527:7 | call to find : | semmle.label | call to find : | @@ -4478,8 +5540,12 @@ nodes | array_flow.rb:526:14:526:14 | x | semmle.label | x | | array_flow.rb:528:10:528:10 | b | semmle.label | b | | array_flow.rb:528:10:528:10 | b | semmle.label | b | +| array_flow.rb:532:5:532:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:532:5:532:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:532:19:532:28 | call to source : | semmle.label | call to source : | | array_flow.rb:532:19:532:28 | call to source : | semmle.label | call to source : | +| array_flow.rb:533:5:533:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:533:5:533:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:533:9:533:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:533:9:533:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:533:9:535:7 | call to find_all [element] : | semmle.label | call to find_all [element] : | @@ -4492,6 +5558,8 @@ nodes | array_flow.rb:536:10:536:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:536:10:536:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:536:10:536:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:540:5:540:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:540:5:540:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:540:19:540:28 | call to source : | semmle.label | call to source : | | array_flow.rb:540:19:540:28 | call to source : | semmle.label | call to source : | | array_flow.rb:541:5:541:5 | a [element 3] : | semmle.label | a [element 3] : | @@ -4500,6 +5568,10 @@ nodes | array_flow.rb:541:22:541:22 | x : | semmle.label | x : | | array_flow.rb:542:14:542:14 | x | semmle.label | x | | array_flow.rb:542:14:542:14 | x | semmle.label | x | +| array_flow.rb:547:5:547:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:547:5:547:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:547:5:547:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:547:5:547:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:547:10:547:21 | call to source : | semmle.label | call to source : | | array_flow.rb:547:10:547:21 | call to source : | semmle.label | call to source : | | array_flow.rb:547:30:547:41 | call to source : | semmle.label | call to source : | @@ -4514,6 +5586,10 @@ nodes | array_flow.rb:549:10:549:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:549:10:549:16 | call to first | semmle.label | call to first | | array_flow.rb:549:10:549:16 | call to first | semmle.label | call to first | +| array_flow.rb:550:5:550:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:550:5:550:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:550:5:550:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:550:5:550:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:550:9:550:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:550:9:550:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:550:9:550:9 | a [element] : | semmle.label | a [element] : | @@ -4532,6 +5608,12 @@ nodes | array_flow.rb:552:10:552:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:552:10:552:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:552:10:552:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:553:5:553:5 | c [element 0] : | semmle.label | c [element 0] : | +| array_flow.rb:553:5:553:5 | c [element 0] : | semmle.label | c [element 0] : | +| array_flow.rb:553:5:553:5 | c [element 3] : | semmle.label | c [element 3] : | +| array_flow.rb:553:5:553:5 | c [element 3] : | semmle.label | c [element 3] : | +| array_flow.rb:553:5:553:5 | c [element] : | semmle.label | c [element] : | +| array_flow.rb:553:5:553:5 | c [element] : | semmle.label | c [element] : | | array_flow.rb:553:9:553:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:553:9:553:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:553:9:553:9 | a [element 3] : | semmle.label | a [element 3] : | @@ -4556,8 +5638,12 @@ nodes | array_flow.rb:555:10:555:10 | c [element] : | semmle.label | c [element] : | | array_flow.rb:555:10:555:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:555:10:555:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:559:5:559:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:559:5:559:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:559:16:559:27 | call to source : | semmle.label | call to source : | | array_flow.rb:559:16:559:27 | call to source : | semmle.label | call to source : | +| array_flow.rb:560:5:560:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:560:5:560:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:560:9:560:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:560:9:560:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:560:9:563:7 | call to flat_map [element] : | semmle.label | call to flat_map [element] : | @@ -4572,6 +5658,8 @@ nodes | array_flow.rb:564:10:564:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:564:10:564:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:564:10:564:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:565:5:565:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:565:5:565:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:565:9:565:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:565:9:565:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:565:9:568:7 | call to flat_map [element] : | semmle.label | call to flat_map [element] : | @@ -4586,8 +5674,12 @@ nodes | array_flow.rb:569:10:569:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:569:10:569:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:569:10:569:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:573:5:573:5 | a [element 2, element 1] : | semmle.label | a [element 2, element 1] : | +| array_flow.rb:573:5:573:5 | a [element 2, element 1] : | semmle.label | a [element 2, element 1] : | | array_flow.rb:573:20:573:29 | call to source : | semmle.label | call to source : | | array_flow.rb:573:20:573:29 | call to source : | semmle.label | call to source : | +| array_flow.rb:574:5:574:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:574:5:574:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:574:9:574:9 | a [element 2, element 1] : | semmle.label | a [element 2, element 1] : | | array_flow.rb:574:9:574:9 | a [element 2, element 1] : | semmle.label | a [element 2, element 1] : | | array_flow.rb:574:9:574:17 | call to flatten [element] : | semmle.label | call to flatten [element] : | @@ -4596,6 +5688,8 @@ nodes | array_flow.rb:575:10:575:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:575:10:575:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:575:10:575:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:579:5:579:5 | a [element 2, element 1] : | semmle.label | a [element 2, element 1] : | +| array_flow.rb:579:5:579:5 | a [element 2, element 1] : | semmle.label | a [element 2, element 1] : | | array_flow.rb:579:20:579:29 | call to source : | semmle.label | call to source : | | array_flow.rb:579:20:579:29 | call to source : | semmle.label | call to source : | | array_flow.rb:580:10:580:10 | a [element 2, element 1] : | semmle.label | a [element 2, element 1] : | @@ -4604,6 +5698,10 @@ nodes | array_flow.rb:580:10:580:13 | ...[...] [element 1] : | semmle.label | ...[...] [element 1] : | | array_flow.rb:580:10:580:16 | ...[...] | semmle.label | ...[...] | | array_flow.rb:580:10:580:16 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:581:5:581:5 | b [element, element 1] : | semmle.label | b [element, element 1] : | +| array_flow.rb:581:5:581:5 | b [element, element 1] : | semmle.label | b [element, element 1] : | +| array_flow.rb:581:5:581:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:581:5:581:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:581:9:581:9 | [post] a [element, element 1] : | semmle.label | [post] a [element, element 1] : | | array_flow.rb:581:9:581:9 | [post] a [element, element 1] : | semmle.label | [post] a [element, element 1] : | | array_flow.rb:581:9:581:9 | [post] a [element] : | semmle.label | [post] a [element] : | @@ -4638,8 +5736,12 @@ nodes | array_flow.rb:585:10:585:13 | ...[...] [element 1] : | semmle.label | ...[...] [element 1] : | | array_flow.rb:585:10:585:16 | ...[...] | semmle.label | ...[...] | | array_flow.rb:585:10:585:16 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:589:5:589:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:589:5:589:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:589:19:589:30 | call to source : | semmle.label | call to source : | | array_flow.rb:589:19:589:30 | call to source : | semmle.label | call to source : | +| array_flow.rb:590:5:590:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:590:5:590:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:590:9:590:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:590:9:590:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:590:9:590:20 | call to grep [element] : | semmle.label | call to grep [element] : | @@ -4648,6 +5750,8 @@ nodes | array_flow.rb:591:10:591:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:591:10:591:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:591:10:591:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:592:5:592:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:592:5:592:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:592:9:592:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:592:9:592:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:592:9:595:7 | call to grep [element] : | semmle.label | call to grep [element] : | @@ -4662,8 +5766,12 @@ nodes | array_flow.rb:596:10:596:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:596:10:596:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:596:10:596:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:600:5:600:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:600:5:600:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:600:19:600:30 | call to source : | semmle.label | call to source : | | array_flow.rb:600:19:600:30 | call to source : | semmle.label | call to source : | +| array_flow.rb:601:5:601:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:601:5:601:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:601:9:601:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:601:9:601:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:601:9:601:21 | call to grep_v [element] : | semmle.label | call to grep_v [element] : | @@ -4672,6 +5780,8 @@ nodes | array_flow.rb:602:10:602:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:602:10:602:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:602:10:602:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:603:5:603:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:603:5:603:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:603:9:603:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:603:9:603:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:603:9:606:7 | call to grep_v [element] : | semmle.label | call to grep_v [element] : | @@ -4686,6 +5796,8 @@ nodes | array_flow.rb:607:10:607:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:607:10:607:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:607:10:607:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:611:5:611:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:611:5:611:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:611:19:611:30 | call to source : | semmle.label | call to source : | | array_flow.rb:611:19:611:30 | call to source : | semmle.label | call to source : | | array_flow.rb:612:9:612:9 | a [element 3] : | semmle.label | a [element 3] : | @@ -4694,6 +5806,8 @@ nodes | array_flow.rb:612:24:612:24 | x : | semmle.label | x : | | array_flow.rb:613:14:613:14 | x | semmle.label | x | | array_flow.rb:613:14:613:14 | x | semmle.label | x | +| array_flow.rb:620:5:620:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:620:5:620:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:620:19:620:28 | call to source : | semmle.label | call to source : | | array_flow.rb:620:19:620:28 | call to source : | semmle.label | call to source : | | array_flow.rb:621:5:621:5 | a [element 3] : | semmle.label | a [element 3] : | @@ -4702,10 +5816,16 @@ nodes | array_flow.rb:621:17:621:17 | x : | semmle.label | x : | | array_flow.rb:622:14:622:14 | x | semmle.label | x | | array_flow.rb:622:14:622:14 | x | semmle.label | x | +| array_flow.rb:627:5:627:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:627:5:627:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:627:5:627:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:627:5:627:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:627:10:627:21 | call to source : | semmle.label | call to source : | | array_flow.rb:627:10:627:21 | call to source : | semmle.label | call to source : | | array_flow.rb:627:27:627:38 | call to source : | semmle.label | call to source : | | array_flow.rb:627:27:627:38 | call to source : | semmle.label | call to source : | +| array_flow.rb:628:5:628:5 | b : | semmle.label | b : | +| array_flow.rb:628:5:628:5 | b : | semmle.label | b : | | array_flow.rb:628:9:628:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:628:9:628:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:628:9:628:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -4724,6 +5844,8 @@ nodes | array_flow.rb:631:9:631:19 | call to source : | semmle.label | call to source : | | array_flow.rb:633:10:633:10 | b | semmle.label | b | | array_flow.rb:633:10:633:10 | b | semmle.label | b | +| array_flow.rb:634:5:634:5 | c : | semmle.label | c : | +| array_flow.rb:634:5:634:5 | c : | semmle.label | c : | | array_flow.rb:634:9:634:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:634:9:634:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:634:9:634:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -4738,8 +5860,16 @@ nodes | array_flow.rb:637:9:637:19 | call to source : | semmle.label | call to source : | | array_flow.rb:639:10:639:10 | c | semmle.label | c | | array_flow.rb:639:10:639:10 | c | semmle.label | c | +| array_flow.rb:644:5:644:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:644:5:644:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:644:16:644:27 | call to source : | semmle.label | call to source : | | array_flow.rb:644:16:644:27 | call to source : | semmle.label | call to source : | +| array_flow.rb:645:5:645:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:645:5:645:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:645:5:645:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:645:5:645:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:645:5:645:5 | b [element 4] : | semmle.label | b [element 4] : | +| array_flow.rb:645:5:645:5 | b [element 4] : | semmle.label | b [element 4] : | | array_flow.rb:645:9:645:9 | [post] a [element 1] : | semmle.label | [post] a [element 1] : | | array_flow.rb:645:9:645:9 | [post] a [element 1] : | semmle.label | [post] a [element 1] : | | array_flow.rb:645:9:645:9 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | @@ -4782,8 +5912,12 @@ nodes | array_flow.rb:655:10:655:10 | b [element 4] : | semmle.label | b [element 4] : | | array_flow.rb:655:10:655:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:655:10:655:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:658:5:658:5 | c [element 2] : | semmle.label | c [element 2] : | +| array_flow.rb:658:5:658:5 | c [element 2] : | semmle.label | c [element 2] : | | array_flow.rb:658:16:658:27 | call to source : | semmle.label | call to source : | | array_flow.rb:658:16:658:27 | call to source : | semmle.label | call to source : | +| array_flow.rb:659:5:659:5 | d [element] : | semmle.label | d [element] : | +| array_flow.rb:659:5:659:5 | d [element] : | semmle.label | d [element] : | | array_flow.rb:659:9:659:9 | [post] c [element] : | semmle.label | [post] c [element] : | | array_flow.rb:659:9:659:9 | [post] c [element] : | semmle.label | [post] c [element] : | | array_flow.rb:659:9:659:9 | c [element 2] : | semmle.label | c [element 2] : | @@ -4802,8 +5936,12 @@ nodes | array_flow.rb:661:10:661:10 | d [element] : | semmle.label | d [element] : | | array_flow.rb:661:10:661:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:661:10:661:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:672:5:672:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:672:5:672:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:672:16:672:27 | call to source : | semmle.label | call to source : | | array_flow.rb:672:16:672:27 | call to source : | semmle.label | call to source : | +| array_flow.rb:673:5:673:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:673:5:673:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:673:9:673:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:673:9:673:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:673:9:673:60 | call to intersection [element] : | semmle.label | call to intersection [element] : | @@ -4816,8 +5954,12 @@ nodes | array_flow.rb:674:10:674:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:674:10:674:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:674:10:674:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:678:5:678:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:678:5:678:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:678:16:678:25 | call to source : | semmle.label | call to source : | | array_flow.rb:678:16:678:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:679:5:679:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:679:5:679:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:679:9:679:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:679:9:679:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:679:9:679:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -4836,6 +5978,8 @@ nodes | array_flow.rb:684:10:684:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:684:10:684:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:684:10:684:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:688:5:688:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:688:5:688:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:688:16:688:27 | call to source : | semmle.label | call to source : | | array_flow.rb:688:16:688:27 | call to source : | semmle.label | call to source : | | array_flow.rb:689:5:689:5 | [post] a [element] : | semmle.label | [post] a [element] : | @@ -4848,6 +5992,8 @@ nodes | array_flow.rb:690:10:690:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:690:10:690:15 | call to last | semmle.label | call to last | | array_flow.rb:690:10:690:15 | call to last | semmle.label | call to last | +| array_flow.rb:691:5:691:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:691:5:691:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:691:9:691:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:691:9:691:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:691:9:691:9 | a [element] : | semmle.label | a [element] : | @@ -4862,8 +6008,12 @@ nodes | array_flow.rb:693:10:693:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:693:10:693:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:693:10:693:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:697:5:697:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:697:5:697:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:697:16:697:27 | call to source : | semmle.label | call to source : | | array_flow.rb:697:16:697:27 | call to source : | semmle.label | call to source : | +| array_flow.rb:698:5:698:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:698:5:698:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:698:9:698:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:698:9:698:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:698:9:701:7 | call to map [element] : | semmle.label | call to map [element] : | @@ -4878,8 +6028,12 @@ nodes | array_flow.rb:702:10:702:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:702:10:702:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:702:10:702:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:706:5:706:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:706:5:706:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:706:16:706:27 | call to source : | semmle.label | call to source : | | array_flow.rb:706:16:706:27 | call to source : | semmle.label | call to source : | +| array_flow.rb:707:5:707:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:707:5:707:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:707:9:707:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:707:9:707:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:707:9:710:7 | call to map! [element] : | semmle.label | call to map! [element] : | @@ -4894,14 +6048,20 @@ nodes | array_flow.rb:711:10:711:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:711:10:711:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:711:10:711:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:715:5:715:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:715:5:715:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:715:16:715:25 | call to source : | semmle.label | call to source : | | array_flow.rb:715:16:715:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:718:5:718:5 | b : | semmle.label | b : | +| array_flow.rb:718:5:718:5 | b : | semmle.label | b : | | array_flow.rb:718:9:718:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:718:9:718:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:718:9:718:13 | call to max : | semmle.label | call to max : | | array_flow.rb:718:9:718:13 | call to max : | semmle.label | call to max : | | array_flow.rb:719:10:719:10 | b | semmle.label | b | | array_flow.rb:719:10:719:10 | b | semmle.label | b | +| array_flow.rb:722:5:722:5 | c [element] : | semmle.label | c [element] : | +| array_flow.rb:722:5:722:5 | c [element] : | semmle.label | c [element] : | | array_flow.rb:722:9:722:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:722:9:722:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:722:9:722:16 | call to max [element] : | semmle.label | call to max [element] : | @@ -4910,6 +6070,8 @@ nodes | array_flow.rb:723:10:723:10 | c [element] : | semmle.label | c [element] : | | array_flow.rb:723:10:723:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:723:10:723:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:726:5:726:5 | d : | semmle.label | d : | +| array_flow.rb:726:5:726:5 | d : | semmle.label | d : | | array_flow.rb:726:9:726:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:726:9:726:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:726:9:730:7 | call to max : | semmle.label | call to max : | @@ -4924,6 +6086,8 @@ nodes | array_flow.rb:728:14:728:14 | y | semmle.label | y | | array_flow.rb:731:10:731:10 | d | semmle.label | d | | array_flow.rb:731:10:731:10 | d | semmle.label | d | +| array_flow.rb:734:5:734:5 | e [element] : | semmle.label | e [element] : | +| array_flow.rb:734:5:734:5 | e [element] : | semmle.label | e [element] : | | array_flow.rb:734:9:734:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:734:9:734:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:734:9:738:7 | call to max [element] : | semmle.label | call to max [element] : | @@ -4940,8 +6104,12 @@ nodes | array_flow.rb:739:10:739:10 | e [element] : | semmle.label | e [element] : | | array_flow.rb:739:10:739:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:739:10:739:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:743:5:743:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:743:5:743:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:743:16:743:25 | call to source : | semmle.label | call to source : | | array_flow.rb:743:16:743:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:746:5:746:5 | b : | semmle.label | b : | +| array_flow.rb:746:5:746:5 | b : | semmle.label | b : | | array_flow.rb:746:9:746:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:746:9:746:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:746:9:749:7 | call to max_by : | semmle.label | call to max_by : | @@ -4952,6 +6120,8 @@ nodes | array_flow.rb:747:14:747:14 | x | semmle.label | x | | array_flow.rb:750:10:750:10 | b | semmle.label | b | | array_flow.rb:750:10:750:10 | b | semmle.label | b | +| array_flow.rb:753:5:753:5 | c [element] : | semmle.label | c [element] : | +| array_flow.rb:753:5:753:5 | c [element] : | semmle.label | c [element] : | | array_flow.rb:753:9:753:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:753:9:753:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:753:9:756:7 | call to max_by [element] : | semmle.label | call to max_by [element] : | @@ -4964,14 +6134,20 @@ nodes | array_flow.rb:757:10:757:10 | c [element] : | semmle.label | c [element] : | | array_flow.rb:757:10:757:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:757:10:757:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:761:5:761:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:761:5:761:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:761:16:761:25 | call to source : | semmle.label | call to source : | | array_flow.rb:761:16:761:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:764:5:764:5 | b : | semmle.label | b : | +| array_flow.rb:764:5:764:5 | b : | semmle.label | b : | | array_flow.rb:764:9:764:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:764:9:764:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:764:9:764:13 | call to min : | semmle.label | call to min : | | array_flow.rb:764:9:764:13 | call to min : | semmle.label | call to min : | | array_flow.rb:765:10:765:10 | b | semmle.label | b | | array_flow.rb:765:10:765:10 | b | semmle.label | b | +| array_flow.rb:768:5:768:5 | c [element] : | semmle.label | c [element] : | +| array_flow.rb:768:5:768:5 | c [element] : | semmle.label | c [element] : | | array_flow.rb:768:9:768:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:768:9:768:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:768:9:768:16 | call to min [element] : | semmle.label | call to min [element] : | @@ -4980,6 +6156,8 @@ nodes | array_flow.rb:769:10:769:10 | c [element] : | semmle.label | c [element] : | | array_flow.rb:769:10:769:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:769:10:769:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:772:5:772:5 | d : | semmle.label | d : | +| array_flow.rb:772:5:772:5 | d : | semmle.label | d : | | array_flow.rb:772:9:772:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:772:9:772:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:772:9:776:7 | call to min : | semmle.label | call to min : | @@ -4994,6 +6172,8 @@ nodes | array_flow.rb:774:14:774:14 | y | semmle.label | y | | array_flow.rb:777:10:777:10 | d | semmle.label | d | | array_flow.rb:777:10:777:10 | d | semmle.label | d | +| array_flow.rb:780:5:780:5 | e [element] : | semmle.label | e [element] : | +| array_flow.rb:780:5:780:5 | e [element] : | semmle.label | e [element] : | | array_flow.rb:780:9:780:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:780:9:780:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:780:9:784:7 | call to min [element] : | semmle.label | call to min [element] : | @@ -5010,8 +6190,12 @@ nodes | array_flow.rb:785:10:785:10 | e [element] : | semmle.label | e [element] : | | array_flow.rb:785:10:785:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:785:10:785:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:789:5:789:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:789:5:789:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:789:16:789:25 | call to source : | semmle.label | call to source : | | array_flow.rb:789:16:789:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:792:5:792:5 | b : | semmle.label | b : | +| array_flow.rb:792:5:792:5 | b : | semmle.label | b : | | array_flow.rb:792:9:792:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:792:9:792:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:792:9:795:7 | call to min_by : | semmle.label | call to min_by : | @@ -5022,6 +6206,8 @@ nodes | array_flow.rb:793:14:793:14 | x | semmle.label | x | | array_flow.rb:796:10:796:10 | b | semmle.label | b | | array_flow.rb:796:10:796:10 | b | semmle.label | b | +| array_flow.rb:799:5:799:5 | c [element] : | semmle.label | c [element] : | +| array_flow.rb:799:5:799:5 | c [element] : | semmle.label | c [element] : | | array_flow.rb:799:9:799:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:799:9:799:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:799:9:802:7 | call to min_by [element] : | semmle.label | call to min_by [element] : | @@ -5034,8 +6220,12 @@ nodes | array_flow.rb:803:10:803:10 | c [element] : | semmle.label | c [element] : | | array_flow.rb:803:10:803:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:803:10:803:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:807:5:807:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:807:5:807:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:807:16:807:25 | call to source : | semmle.label | call to source : | | array_flow.rb:807:16:807:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:809:5:809:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:809:5:809:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:809:9:809:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:809:9:809:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:809:9:809:16 | call to minmax [element] : | semmle.label | call to minmax [element] : | @@ -5048,6 +6238,8 @@ nodes | array_flow.rb:811:10:811:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:811:10:811:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:811:10:811:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:813:5:813:5 | c [element] : | semmle.label | c [element] : | +| array_flow.rb:813:5:813:5 | c [element] : | semmle.label | c [element] : | | array_flow.rb:813:9:813:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:813:9:813:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:813:9:817:7 | call to minmax [element] : | semmle.label | call to minmax [element] : | @@ -5068,8 +6260,12 @@ nodes | array_flow.rb:819:10:819:10 | c [element] : | semmle.label | c [element] : | | array_flow.rb:819:10:819:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:819:10:819:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:823:5:823:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:823:5:823:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:823:16:823:25 | call to source : | semmle.label | call to source : | | array_flow.rb:823:16:823:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:824:5:824:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:824:5:824:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:824:9:824:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:824:9:824:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:824:9:827:7 | call to minmax_by [element] : | semmle.label | call to minmax_by [element] : | @@ -5086,6 +6282,8 @@ nodes | array_flow.rb:829:10:829:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:829:10:829:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:829:10:829:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:833:5:833:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:833:5:833:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:833:16:833:25 | call to source : | semmle.label | call to source : | | array_flow.rb:833:16:833:25 | call to source : | semmle.label | call to source : | | array_flow.rb:834:5:834:5 | a [element 2] : | semmle.label | a [element 2] : | @@ -5094,6 +6292,8 @@ nodes | array_flow.rb:834:17:834:17 | x : | semmle.label | x : | | array_flow.rb:835:14:835:14 | x | semmle.label | x | | array_flow.rb:835:14:835:14 | x | semmle.label | x | +| array_flow.rb:842:5:842:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:842:5:842:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:842:16:842:25 | call to source : | semmle.label | call to source : | | array_flow.rb:842:16:842:25 | call to source : | semmle.label | call to source : | | array_flow.rb:843:5:843:5 | a [element 2] : | semmle.label | a [element 2] : | @@ -5102,12 +6302,18 @@ nodes | array_flow.rb:843:16:843:16 | x : | semmle.label | x : | | array_flow.rb:844:14:844:14 | x | semmle.label | x | | array_flow.rb:844:14:844:14 | x | semmle.label | x | +| array_flow.rb:849:5:849:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:849:16:849:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:850:5:850:5 | b : | semmle.label | b : | | array_flow.rb:850:9:850:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:850:9:850:20 | call to pack : | semmle.label | call to pack : | | array_flow.rb:851:10:851:10 | b | semmle.label | b | +| array_flow.rb:855:5:855:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:855:5:855:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:855:16:855:25 | call to source : | semmle.label | call to source : | | array_flow.rb:855:16:855:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:856:5:856:5 | b [element, element] : | semmle.label | b [element, element] : | +| array_flow.rb:856:5:856:5 | b [element, element] : | semmle.label | b [element, element] : | | array_flow.rb:856:9:856:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:856:9:856:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:856:9:859:7 | call to partition [element, element] : | semmle.label | call to partition [element, element] : | @@ -5128,8 +6334,12 @@ nodes | array_flow.rb:861:10:861:13 | ...[...] [element] : | semmle.label | ...[...] [element] : | | array_flow.rb:861:10:861:16 | ...[...] | semmle.label | ...[...] | | array_flow.rb:861:10:861:16 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:865:5:865:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:865:5:865:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:865:16:865:25 | call to source : | semmle.label | call to source : | | array_flow.rb:865:16:865:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:867:5:867:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:867:5:867:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:867:9:867:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:867:9:867:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:867:9:871:7 | call to permutation [element 2] : | semmle.label | call to permutation [element 2] : | @@ -5152,6 +6362,8 @@ nodes | array_flow.rb:873:10:873:10 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:873:10:873:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:873:10:873:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:875:5:875:5 | c [element 2] : | semmle.label | c [element 2] : | +| array_flow.rb:875:5:875:5 | c [element 2] : | semmle.label | c [element 2] : | | array_flow.rb:875:9:875:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:875:9:875:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:875:9:878:7 | call to permutation [element 2] : | semmle.label | call to permutation [element 2] : | @@ -5186,10 +6398,16 @@ nodes | array_flow.rb:887:10:887:10 | c [element 2] : | semmle.label | c [element 2] : | | array_flow.rb:887:10:887:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:887:10:887:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:894:5:894:5 | a [element 1] : | semmle.label | a [element 1] : | +| array_flow.rb:894:5:894:5 | a [element 1] : | semmle.label | a [element 1] : | +| array_flow.rb:894:5:894:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:894:5:894:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:894:13:894:24 | call to source : | semmle.label | call to source : | | array_flow.rb:894:13:894:24 | call to source : | semmle.label | call to source : | | array_flow.rb:894:30:894:41 | call to source : | semmle.label | call to source : | | array_flow.rb:894:30:894:41 | call to source : | semmle.label | call to source : | +| array_flow.rb:895:5:895:5 | b : | semmle.label | b : | +| array_flow.rb:895:5:895:5 | b : | semmle.label | b : | | array_flow.rb:895:9:895:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:895:9:895:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:895:9:895:9 | a [element 3] : | semmle.label | a [element 3] : | @@ -5206,10 +6424,16 @@ nodes | array_flow.rb:900:10:900:10 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:900:10:900:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:900:10:900:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:902:5:902:5 | a [element 1] : | semmle.label | a [element 1] : | +| array_flow.rb:902:5:902:5 | a [element 1] : | semmle.label | a [element 1] : | +| array_flow.rb:902:5:902:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:902:5:902:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:902:13:902:24 | call to source : | semmle.label | call to source : | | array_flow.rb:902:13:902:24 | call to source : | semmle.label | call to source : | | array_flow.rb:902:30:902:41 | call to source : | semmle.label | call to source : | | array_flow.rb:902:30:902:41 | call to source : | semmle.label | call to source : | +| array_flow.rb:903:5:903:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:903:5:903:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:903:9:903:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:903:9:903:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:903:9:903:9 | a [element 3] : | semmle.label | a [element 3] : | @@ -5232,6 +6456,8 @@ nodes | array_flow.rb:909:10:909:10 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:909:10:909:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:909:10:909:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:913:5:913:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:913:5:913:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:913:16:913:27 | call to source : | semmle.label | call to source : | | array_flow.rb:913:16:913:27 | call to source : | semmle.label | call to source : | | array_flow.rb:914:5:914:5 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | @@ -5250,12 +6476,20 @@ nodes | array_flow.rb:920:10:920:10 | a [element 5] : | semmle.label | a [element 5] : | | array_flow.rb:920:10:920:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:920:10:920:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:924:5:924:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:924:5:924:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:924:16:924:27 | call to source : | semmle.label | call to source : | | array_flow.rb:924:16:924:27 | call to source : | semmle.label | call to source : | +| array_flow.rb:925:5:925:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:925:5:925:5 | b [element 1] : | semmle.label | b [element 1] : | | array_flow.rb:925:13:925:24 | call to source : | semmle.label | call to source : | | array_flow.rb:925:13:925:24 | call to source : | semmle.label | call to source : | +| array_flow.rb:926:5:926:5 | c [element 0] : | semmle.label | c [element 0] : | +| array_flow.rb:926:5:926:5 | c [element 0] : | semmle.label | c [element 0] : | | array_flow.rb:926:10:926:21 | call to source : | semmle.label | call to source : | | array_flow.rb:926:10:926:21 | call to source : | semmle.label | call to source : | +| array_flow.rb:927:5:927:5 | d [element, element] : | semmle.label | d [element, element] : | +| array_flow.rb:927:5:927:5 | d [element, element] : | semmle.label | d [element, element] : | | array_flow.rb:927:9:927:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:927:9:927:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:927:9:927:22 | call to product [element, element] : | semmle.label | call to product [element, element] : | @@ -5276,8 +6510,14 @@ nodes | array_flow.rb:929:10:929:13 | ...[...] [element] : | semmle.label | ...[...] [element] : | | array_flow.rb:929:10:929:16 | ...[...] | semmle.label | ...[...] | | array_flow.rb:929:10:929:16 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:933:5:933:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:933:5:933:5 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:933:10:933:21 | call to source : | semmle.label | call to source : | | array_flow.rb:933:10:933:21 | call to source : | semmle.label | call to source : | +| array_flow.rb:934:5:934:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:934:5:934:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:934:5:934:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:934:5:934:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:934:9:934:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:934:9:934:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:934:9:934:9 | a [element 0] : | semmle.label | a [element 0] : | @@ -5310,8 +6550,12 @@ nodes | array_flow.rb:938:10:938:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:938:10:938:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:938:10:938:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:944:5:944:5 | c [element 0] : | semmle.label | c [element 0] : | +| array_flow.rb:944:5:944:5 | c [element 0] : | semmle.label | c [element 0] : | | array_flow.rb:944:10:944:19 | call to source : | semmle.label | call to source : | | array_flow.rb:944:10:944:19 | call to source : | semmle.label | call to source : | +| array_flow.rb:945:5:945:5 | d [element 2, element 0] : | semmle.label | d [element 2, element 0] : | +| array_flow.rb:945:5:945:5 | d [element 2, element 0] : | semmle.label | d [element 2, element 0] : | | array_flow.rb:945:16:945:16 | c [element 0] : | semmle.label | c [element 0] : | | array_flow.rb:945:16:945:16 | c [element 0] : | semmle.label | c [element 0] : | | array_flow.rb:946:10:946:10 | d [element 2, element 0] : | semmle.label | d [element 2, element 0] : | @@ -5326,6 +6570,10 @@ nodes | array_flow.rb:947:10:947:22 | call to rassoc [element 0] : | semmle.label | call to rassoc [element 0] : | | array_flow.rb:947:10:947:25 | ...[...] | semmle.label | ...[...] | | array_flow.rb:947:10:947:25 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:951:5:951:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:951:5:951:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:951:5:951:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:951:5:951:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:951:10:951:21 | call to source : | semmle.label | call to source : | | array_flow.rb:951:10:951:21 | call to source : | semmle.label | call to source : | | array_flow.rb:951:27:951:38 | call to source : | semmle.label | call to source : | @@ -5350,8 +6598,12 @@ nodes | array_flow.rb:957:28:957:28 | y : | semmle.label | y : | | array_flow.rb:959:14:959:14 | y | semmle.label | y | | array_flow.rb:959:14:959:14 | y | semmle.label | y | +| array_flow.rb:965:5:965:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:965:5:965:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:965:16:965:25 | call to source : | semmle.label | call to source : | | array_flow.rb:965:16:965:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:966:5:966:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:966:5:966:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:966:9:966:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:966:9:966:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:966:9:969:7 | call to reject [element] : | semmle.label | call to reject [element] : | @@ -5364,8 +6616,12 @@ nodes | array_flow.rb:970:10:970:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:970:10:970:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:970:10:970:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:974:5:974:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:974:5:974:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:974:16:974:25 | call to source : | semmle.label | call to source : | | array_flow.rb:974:16:974:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:975:5:975:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:975:5:975:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:975:9:975:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:975:9:975:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:975:9:975:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -5384,8 +6640,12 @@ nodes | array_flow.rb:980:10:980:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:980:10:980:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:980:10:980:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:984:5:984:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:984:5:984:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:984:16:984:25 | call to source : | semmle.label | call to source : | | array_flow.rb:984:16:984:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:985:5:985:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:985:5:985:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:985:9:985:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:985:9:985:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:985:9:988:7 | call to repeated_combination [element 2] : | semmle.label | call to repeated_combination [element 2] : | @@ -5404,8 +6664,12 @@ nodes | array_flow.rb:990:10:990:10 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:990:10:990:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:990:10:990:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:994:5:994:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:994:5:994:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:994:16:994:25 | call to source : | semmle.label | call to source : | | array_flow.rb:994:16:994:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:995:5:995:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:995:5:995:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:995:9:995:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:995:9:995:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:995:9:998:7 | call to repeated_permutation [element 2] : | semmle.label | call to repeated_permutation [element 2] : | @@ -5424,6 +6688,8 @@ nodes | array_flow.rb:1000:10:1000:10 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:1000:10:1000:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1000:10:1000:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1006:5:1006:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1006:5:1006:5 | b [element 0] : | semmle.label | b [element 0] : | | array_flow.rb:1006:9:1006:9 | [post] a [element 0] : | semmle.label | [post] a [element 0] : | | array_flow.rb:1006:9:1006:9 | [post] a [element 0] : | semmle.label | [post] a [element 0] : | | array_flow.rb:1006:9:1006:33 | call to replace [element 0] : | semmle.label | call to replace [element 0] : | @@ -5438,10 +6704,16 @@ nodes | array_flow.rb:1008:10:1008:10 | b [element 0] : | semmle.label | b [element 0] : | | array_flow.rb:1008:10:1008:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1008:10:1008:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1012:5:1012:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1012:5:1012:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1012:5:1012:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:1012:5:1012:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1012:16:1012:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1012:16:1012:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1012:31:1012:43 | call to source : | semmle.label | call to source : | | array_flow.rb:1012:31:1012:43 | call to source : | semmle.label | call to source : | +| array_flow.rb:1013:5:1013:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1013:5:1013:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1013:9:1013:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1013:9:1013:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1013:9:1013:9 | a [element 3] : | semmle.label | a [element 3] : | @@ -5468,10 +6740,16 @@ nodes | array_flow.rb:1019:10:1019:10 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1019:10:1019:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1019:10:1019:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1023:5:1023:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1023:5:1023:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1023:5:1023:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:1023:5:1023:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1023:16:1023:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1023:16:1023:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1023:31:1023:43 | call to source : | semmle.label | call to source : | | array_flow.rb:1023:31:1023:43 | call to source : | semmle.label | call to source : | +| array_flow.rb:1024:5:1024:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1024:5:1024:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1024:9:1024:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1024:9:1024:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1024:9:1024:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -5508,8 +6786,12 @@ nodes | array_flow.rb:1030:10:1030:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:1030:10:1030:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1030:10:1030:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1034:5:1034:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1034:5:1034:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1034:16:1034:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1034:16:1034:26 | call to source : | semmle.label | call to source : | +| array_flow.rb:1035:5:1035:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1035:5:1035:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:1035:9:1035:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1035:9:1035:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1035:9:1037:7 | call to reverse_each [element 2] : | semmle.label | call to reverse_each [element 2] : | @@ -5522,6 +6804,8 @@ nodes | array_flow.rb:1038:10:1038:10 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:1038:10:1038:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1038:10:1038:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1042:5:1042:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1042:5:1042:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1042:16:1042:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1042:16:1042:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1043:5:1043:5 | a [element 2] : | semmle.label | a [element 2] : | @@ -5530,12 +6814,24 @@ nodes | array_flow.rb:1043:18:1043:18 | x : | semmle.label | x : | | array_flow.rb:1044:14:1044:14 | x | semmle.label | x | | array_flow.rb:1044:14:1044:14 | x | semmle.label | x | +| array_flow.rb:1052:5:1052:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:1052:5:1052:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:1052:5:1052:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1052:5:1052:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1052:5:1052:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:1052:5:1052:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1052:10:1052:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1052:10:1052:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1052:28:1052:40 | call to source : | semmle.label | call to source : | | array_flow.rb:1052:28:1052:40 | call to source : | semmle.label | call to source : | | array_flow.rb:1052:43:1052:55 | call to source : | semmle.label | call to source : | | array_flow.rb:1052:43:1052:55 | call to source : | semmle.label | call to source : | +| array_flow.rb:1054:5:1054:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:1054:5:1054:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:1054:5:1054:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1054:5:1054:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1054:5:1054:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1054:5:1054:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1054:9:1054:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:1054:9:1054:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:1054:9:1054:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -5568,6 +6864,12 @@ nodes | array_flow.rb:1058:10:1058:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1058:10:1058:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1058:10:1058:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1060:5:1060:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1060:5:1060:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1060:5:1060:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:1060:5:1060:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:1060:5:1060:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1060:5:1060:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1060:9:1060:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:1060:9:1060:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:1060:9:1060:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -5600,6 +6902,12 @@ nodes | array_flow.rb:1064:10:1064:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1064:10:1064:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1064:10:1064:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1066:5:1066:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1066:5:1066:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1066:5:1066:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1066:5:1066:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1066:5:1066:5 | b [element 3] : | semmle.label | b [element 3] : | +| array_flow.rb:1066:5:1066:5 | b [element 3] : | semmle.label | b [element 3] : | | array_flow.rb:1066:9:1066:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:1066:9:1066:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:1066:9:1066:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -5624,6 +6932,8 @@ nodes | array_flow.rb:1070:10:1070:10 | b [element 3] : | semmle.label | b [element 3] : | | array_flow.rb:1070:10:1070:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1070:10:1070:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1072:5:1072:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1072:5:1072:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1072:9:1072:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:1072:9:1072:9 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:1072:9:1072:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -5648,12 +6958,24 @@ nodes | array_flow.rb:1076:10:1076:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1076:10:1076:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1076:10:1076:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1084:5:1084:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:1084:5:1084:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:1084:5:1084:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1084:5:1084:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1084:5:1084:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:1084:5:1084:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1084:10:1084:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1084:10:1084:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1084:28:1084:40 | call to source : | semmle.label | call to source : | | array_flow.rb:1084:28:1084:40 | call to source : | semmle.label | call to source : | | array_flow.rb:1084:43:1084:55 | call to source : | semmle.label | call to source : | | array_flow.rb:1084:43:1084:55 | call to source : | semmle.label | call to source : | +| array_flow.rb:1085:5:1085:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:1085:5:1085:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:1085:5:1085:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1085:5:1085:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1085:5:1085:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1085:5:1085:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1085:9:1085:9 | [post] a [element 1] : | semmle.label | [post] a [element 1] : | | array_flow.rb:1085:9:1085:9 | [post] a [element 1] : | semmle.label | [post] a [element 1] : | | array_flow.rb:1085:9:1085:9 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | @@ -5712,12 +7034,24 @@ nodes | array_flow.rb:1093:10:1093:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1093:10:1093:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1093:10:1093:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1095:5:1095:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:1095:5:1095:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:1095:5:1095:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1095:5:1095:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1095:5:1095:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:1095:5:1095:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1095:10:1095:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1095:10:1095:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1095:28:1095:40 | call to source : | semmle.label | call to source : | | array_flow.rb:1095:28:1095:40 | call to source : | semmle.label | call to source : | | array_flow.rb:1095:43:1095:55 | call to source : | semmle.label | call to source : | | array_flow.rb:1095:43:1095:55 | call to source : | semmle.label | call to source : | +| array_flow.rb:1096:5:1096:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1096:5:1096:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1096:5:1096:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:1096:5:1096:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:1096:5:1096:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1096:5:1096:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1096:9:1096:9 | [post] a [element 0] : | semmle.label | [post] a [element 0] : | | array_flow.rb:1096:9:1096:9 | [post] a [element 0] : | semmle.label | [post] a [element 0] : | | array_flow.rb:1096:9:1096:9 | [post] a [element 1] : | semmle.label | [post] a [element 1] : | @@ -5776,12 +7110,24 @@ nodes | array_flow.rb:1104:10:1104:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1104:10:1104:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1104:10:1104:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1106:5:1106:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:1106:5:1106:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:1106:5:1106:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1106:5:1106:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1106:5:1106:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:1106:5:1106:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1106:10:1106:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1106:10:1106:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1106:28:1106:40 | call to source : | semmle.label | call to source : | | array_flow.rb:1106:28:1106:40 | call to source : | semmle.label | call to source : | | array_flow.rb:1106:43:1106:55 | call to source : | semmle.label | call to source : | | array_flow.rb:1106:43:1106:55 | call to source : | semmle.label | call to source : | +| array_flow.rb:1107:5:1107:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1107:5:1107:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1107:5:1107:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1107:5:1107:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1107:5:1107:5 | b [element 3] : | semmle.label | b [element 3] : | +| array_flow.rb:1107:5:1107:5 | b [element 3] : | semmle.label | b [element 3] : | | array_flow.rb:1107:9:1107:9 | [post] a [element 0] : | semmle.label | [post] a [element 0] : | | array_flow.rb:1107:9:1107:9 | [post] a [element 0] : | semmle.label | [post] a [element 0] : | | array_flow.rb:1107:9:1107:9 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | @@ -5824,12 +7170,20 @@ nodes | array_flow.rb:1115:10:1115:10 | b [element 3] : | semmle.label | b [element 3] : | | array_flow.rb:1115:10:1115:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1115:10:1115:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1117:5:1117:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:1117:5:1117:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:1117:5:1117:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1117:5:1117:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1117:5:1117:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:1117:5:1117:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1117:10:1117:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1117:10:1117:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1117:28:1117:40 | call to source : | semmle.label | call to source : | | array_flow.rb:1117:28:1117:40 | call to source : | semmle.label | call to source : | | array_flow.rb:1117:43:1117:55 | call to source : | semmle.label | call to source : | | array_flow.rb:1117:43:1117:55 | call to source : | semmle.label | call to source : | +| array_flow.rb:1118:5:1118:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1118:5:1118:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1118:9:1118:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1118:9:1118:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1118:9:1118:9 | a [element 0] : | semmle.label | a [element 0] : | @@ -5872,8 +7226,12 @@ nodes | array_flow.rb:1126:10:1126:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1126:10:1126:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1126:10:1126:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1130:5:1130:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:1130:5:1130:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1130:19:1130:29 | call to source : | semmle.label | call to source : | | array_flow.rb:1130:19:1130:29 | call to source : | semmle.label | call to source : | +| array_flow.rb:1131:5:1131:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1131:5:1131:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1131:9:1131:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1131:9:1131:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1131:9:1133:7 | call to select [element] : | semmle.label | call to select [element] : | @@ -5886,8 +7244,12 @@ nodes | array_flow.rb:1134:10:1134:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1134:10:1134:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1134:10:1134:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1138:5:1138:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1138:5:1138:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1138:16:1138:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1138:16:1138:26 | call to source : | semmle.label | call to source : | +| array_flow.rb:1139:5:1139:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1139:5:1139:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1139:9:1139:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1139:9:1139:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1139:9:1139:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -5906,10 +7268,16 @@ nodes | array_flow.rb:1144:10:1144:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1144:10:1144:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1144:10:1144:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1148:5:1148:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:1148:5:1148:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:1148:5:1148:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1148:5:1148:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1148:10:1148:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1148:10:1148:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1148:28:1148:40 | call to source : | semmle.label | call to source : | | array_flow.rb:1148:28:1148:40 | call to source : | semmle.label | call to source : | +| array_flow.rb:1149:5:1149:5 | b : | semmle.label | b : | +| array_flow.rb:1149:5:1149:5 | b : | semmle.label | b : | | array_flow.rb:1149:9:1149:9 | [post] a [element 1] : | semmle.label | [post] a [element 1] : | | array_flow.rb:1149:9:1149:9 | [post] a [element 1] : | semmle.label | [post] a [element 1] : | | array_flow.rb:1149:9:1149:9 | a [element 0] : | semmle.label | a [element 0] : | @@ -5924,10 +7292,16 @@ nodes | array_flow.rb:1152:10:1152:10 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:1152:10:1152:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1152:10:1152:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1155:5:1155:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:1155:5:1155:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:1155:5:1155:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1155:5:1155:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1155:10:1155:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1155:10:1155:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1155:28:1155:40 | call to source : | semmle.label | call to source : | | array_flow.rb:1155:28:1155:40 | call to source : | semmle.label | call to source : | +| array_flow.rb:1156:5:1156:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1156:5:1156:5 | b [element 0] : | semmle.label | b [element 0] : | | array_flow.rb:1156:9:1156:9 | [post] a [element 0] : | semmle.label | [post] a [element 0] : | | array_flow.rb:1156:9:1156:9 | [post] a [element 0] : | semmle.label | [post] a [element 0] : | | array_flow.rb:1156:9:1156:9 | a [element 0] : | semmle.label | a [element 0] : | @@ -5944,10 +7318,16 @@ nodes | array_flow.rb:1159:10:1159:10 | a [element 0] : | semmle.label | a [element 0] : | | array_flow.rb:1159:10:1159:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1159:10:1159:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1163:5:1163:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:1163:5:1163:5 | a [element 0] : | semmle.label | a [element 0] : | +| array_flow.rb:1163:5:1163:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1163:5:1163:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1163:10:1163:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1163:10:1163:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1163:28:1163:40 | call to source : | semmle.label | call to source : | | array_flow.rb:1163:28:1163:40 | call to source : | semmle.label | call to source : | +| array_flow.rb:1164:5:1164:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1164:5:1164:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1164:9:1164:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1164:9:1164:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1164:9:1164:9 | a [element 0] : | semmle.label | a [element 0] : | @@ -5980,8 +7360,12 @@ nodes | array_flow.rb:1169:10:1169:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:1169:10:1169:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1169:10:1169:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1173:5:1173:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1173:5:1173:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1173:16:1173:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1173:16:1173:26 | call to source : | semmle.label | call to source : | +| array_flow.rb:1174:5:1174:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1174:5:1174:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1174:9:1174:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1174:9:1174:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1174:9:1174:17 | call to shuffle [element] : | semmle.label | call to shuffle [element] : | @@ -6002,8 +7386,12 @@ nodes | array_flow.rb:1180:10:1180:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1180:10:1180:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1180:10:1180:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1184:5:1184:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1184:5:1184:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1184:16:1184:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1184:16:1184:26 | call to source : | semmle.label | call to source : | +| array_flow.rb:1185:5:1185:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1185:5:1185:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1185:9:1185:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1185:9:1185:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1185:9:1185:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6036,16 +7424,24 @@ nodes | array_flow.rb:1191:10:1191:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1191:10:1191:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1191:10:1191:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | semmle.label | a [element 4] : | +| array_flow.rb:1195:5:1195:5 | a [element 4] : | semmle.label | a [element 4] : | | array_flow.rb:1195:16:1195:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1195:16:1195:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1195:34:1195:46 | call to source : | semmle.label | call to source : | | array_flow.rb:1195:34:1195:46 | call to source : | semmle.label | call to source : | +| array_flow.rb:1197:5:1197:5 | b : | semmle.label | b : | +| array_flow.rb:1197:5:1197:5 | b : | semmle.label | b : | | array_flow.rb:1197:9:1197:9 | a [element 4] : | semmle.label | a [element 4] : | | array_flow.rb:1197:9:1197:9 | a [element 4] : | semmle.label | a [element 4] : | | array_flow.rb:1197:9:1197:17 | call to slice : | semmle.label | call to slice : | | array_flow.rb:1197:9:1197:17 | call to slice : | semmle.label | call to slice : | | array_flow.rb:1198:10:1198:10 | b | semmle.label | b | | array_flow.rb:1198:10:1198:10 | b | semmle.label | b | +| array_flow.rb:1200:5:1200:5 | b : | semmle.label | b : | +| array_flow.rb:1200:5:1200:5 | b : | semmle.label | b : | | array_flow.rb:1200:9:1200:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1200:9:1200:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1200:9:1200:9 | a [element 4] : | semmle.label | a [element 4] : | @@ -6054,6 +7450,10 @@ nodes | array_flow.rb:1200:9:1200:19 | call to slice : | semmle.label | call to slice : | | array_flow.rb:1201:10:1201:10 | b | semmle.label | b | | array_flow.rb:1201:10:1201:10 | b | semmle.label | b | +| array_flow.rb:1203:5:1203:5 | b : | semmle.label | b : | +| array_flow.rb:1203:5:1203:5 | b : | semmle.label | b : | +| array_flow.rb:1203:5:1203:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1203:5:1203:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1203:9:1203:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1203:9:1203:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1203:9:1203:9 | a [element 4] : | semmle.label | a [element 4] : | @@ -6069,6 +7469,10 @@ nodes | array_flow.rb:1207:10:1207:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1207:10:1207:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1207:10:1207:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1209:5:1209:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1209:5:1209:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1209:5:1209:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1209:5:1209:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:1209:9:1209:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1209:9:1209:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1209:9:1209:9 | a [element 4] : | semmle.label | a [element 4] : | @@ -6085,6 +7489,8 @@ nodes | array_flow.rb:1212:10:1212:10 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:1212:10:1212:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1212:10:1212:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1214:5:1214:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1214:5:1214:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1214:9:1214:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1214:9:1214:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1214:9:1214:9 | a [element 4] : | semmle.label | a [element 4] : | @@ -6099,6 +7505,8 @@ nodes | array_flow.rb:1216:10:1216:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1216:10:1216:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1216:10:1216:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1218:5:1218:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1218:5:1218:5 | b [element 0] : | semmle.label | b [element 0] : | | array_flow.rb:1218:9:1218:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1218:9:1218:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1218:9:1218:21 | call to slice [element 0] : | semmle.label | call to slice [element 0] : | @@ -6107,6 +7515,8 @@ nodes | array_flow.rb:1219:10:1219:10 | b [element 0] : | semmle.label | b [element 0] : | | array_flow.rb:1219:10:1219:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1219:10:1219:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1223:5:1223:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1223:5:1223:5 | b [element 0] : | semmle.label | b [element 0] : | | array_flow.rb:1223:9:1223:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1223:9:1223:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1223:9:1223:22 | call to slice [element 0] : | semmle.label | call to slice [element 0] : | @@ -6115,6 +7525,8 @@ nodes | array_flow.rb:1224:10:1224:10 | b [element 0] : | semmle.label | b [element 0] : | | array_flow.rb:1224:10:1224:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1224:10:1224:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1228:5:1228:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1228:5:1228:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1228:9:1228:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1228:9:1228:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1228:9:1228:9 | a [element 4] : | semmle.label | a [element 4] : | @@ -6129,6 +7541,8 @@ nodes | array_flow.rb:1230:10:1230:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1230:10:1230:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1230:10:1230:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1232:5:1232:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1232:5:1232:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1232:9:1232:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1232:9:1232:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1232:9:1232:9 | a [element 4] : | semmle.label | a [element 4] : | @@ -6143,6 +7557,8 @@ nodes | array_flow.rb:1234:10:1234:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1234:10:1234:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1234:10:1234:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1236:5:1236:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1236:5:1236:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:1236:9:1236:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1236:9:1236:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1236:9:1236:20 | call to slice [element 2] : | semmle.label | call to slice [element 2] : | @@ -6151,6 +7567,8 @@ nodes | array_flow.rb:1239:10:1239:10 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:1239:10:1239:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1239:10:1239:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1241:5:1241:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1241:5:1241:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1241:9:1241:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1241:9:1241:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1241:9:1241:9 | a [element 4] : | semmle.label | a [element 4] : | @@ -6169,10 +7587,16 @@ nodes | array_flow.rb:1244:10:1244:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1244:10:1244:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1244:10:1244:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1248:5:1248:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1248:5:1248:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1248:5:1248:5 | a [element 4] : | semmle.label | a [element 4] : | +| array_flow.rb:1248:5:1248:5 | a [element 4] : | semmle.label | a [element 4] : | | array_flow.rb:1248:16:1248:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1248:16:1248:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1248:34:1248:46 | call to source : | semmle.label | call to source : | | array_flow.rb:1248:34:1248:46 | call to source : | semmle.label | call to source : | +| array_flow.rb:1249:5:1249:5 | b : | semmle.label | b : | +| array_flow.rb:1249:5:1249:5 | b : | semmle.label | b : | | array_flow.rb:1249:9:1249:9 | [post] a [element 3] : | semmle.label | [post] a [element 3] : | | array_flow.rb:1249:9:1249:9 | [post] a [element 3] : | semmle.label | [post] a [element 3] : | | array_flow.rb:1249:9:1249:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6187,10 +7611,18 @@ nodes | array_flow.rb:1254:10:1254:10 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1254:10:1254:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1254:10:1254:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1256:5:1256:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1256:5:1256:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1256:5:1256:5 | a [element 4] : | semmle.label | a [element 4] : | +| array_flow.rb:1256:5:1256:5 | a [element 4] : | semmle.label | a [element 4] : | | array_flow.rb:1256:16:1256:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1256:16:1256:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1256:34:1256:46 | call to source : | semmle.label | call to source : | | array_flow.rb:1256:34:1256:46 | call to source : | semmle.label | call to source : | +| array_flow.rb:1257:5:1257:5 | b : | semmle.label | b : | +| array_flow.rb:1257:5:1257:5 | b : | semmle.label | b : | +| array_flow.rb:1257:5:1257:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1257:5:1257:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1257:9:1257:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1257:9:1257:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1257:9:1257:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6224,10 +7656,18 @@ nodes | array_flow.rb:1265:10:1265:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1265:10:1265:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1265:10:1265:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1267:5:1267:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1267:5:1267:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1267:5:1267:5 | a [element 4] : | semmle.label | a [element 4] : | +| array_flow.rb:1267:5:1267:5 | a [element 4] : | semmle.label | a [element 4] : | | array_flow.rb:1267:16:1267:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1267:16:1267:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1267:34:1267:46 | call to source : | semmle.label | call to source : | | array_flow.rb:1267:34:1267:46 | call to source : | semmle.label | call to source : | +| array_flow.rb:1268:5:1268:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1268:5:1268:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1268:5:1268:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1268:5:1268:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:1268:9:1268:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1268:9:1268:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1268:9:1268:9 | a [element 4] : | semmle.label | a [element 4] : | @@ -6244,10 +7684,16 @@ nodes | array_flow.rb:1271:10:1271:10 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:1271:10:1271:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1271:10:1271:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1278:5:1278:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1278:5:1278:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1278:5:1278:5 | a [element 4] : | semmle.label | a [element 4] : | +| array_flow.rb:1278:5:1278:5 | a [element 4] : | semmle.label | a [element 4] : | | array_flow.rb:1278:16:1278:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1278:16:1278:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1278:34:1278:46 | call to source : | semmle.label | call to source : | | array_flow.rb:1278:34:1278:46 | call to source : | semmle.label | call to source : | +| array_flow.rb:1279:5:1279:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1279:5:1279:5 | b [element 0] : | semmle.label | b [element 0] : | | array_flow.rb:1279:9:1279:9 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | | array_flow.rb:1279:9:1279:9 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | | array_flow.rb:1279:9:1279:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6264,10 +7710,16 @@ nodes | array_flow.rb:1285:10:1285:10 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1285:10:1285:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1285:10:1285:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1289:5:1289:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1289:5:1289:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1289:5:1289:5 | a [element 4] : | semmle.label | a [element 4] : | +| array_flow.rb:1289:5:1289:5 | a [element 4] : | semmle.label | a [element 4] : | | array_flow.rb:1289:16:1289:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1289:16:1289:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1289:34:1289:46 | call to source : | semmle.label | call to source : | | array_flow.rb:1289:34:1289:46 | call to source : | semmle.label | call to source : | +| array_flow.rb:1290:5:1290:5 | b [element 0] : | semmle.label | b [element 0] : | +| array_flow.rb:1290:5:1290:5 | b [element 0] : | semmle.label | b [element 0] : | | array_flow.rb:1290:9:1290:9 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | | array_flow.rb:1290:9:1290:9 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | | array_flow.rb:1290:9:1290:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6284,10 +7736,16 @@ nodes | array_flow.rb:1296:10:1296:10 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1296:10:1296:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1296:10:1296:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1300:5:1300:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1300:5:1300:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1300:5:1300:5 | a [element 4] : | semmle.label | a [element 4] : | +| array_flow.rb:1300:5:1300:5 | a [element 4] : | semmle.label | a [element 4] : | | array_flow.rb:1300:16:1300:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1300:16:1300:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1300:34:1300:46 | call to source : | semmle.label | call to source : | | array_flow.rb:1300:34:1300:46 | call to source : | semmle.label | call to source : | +| array_flow.rb:1301:5:1301:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1301:5:1301:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1301:9:1301:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1301:9:1301:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1301:9:1301:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6320,10 +7778,16 @@ nodes | array_flow.rb:1307:10:1307:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:1307:10:1307:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1307:10:1307:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1309:5:1309:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1309:5:1309:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1309:5:1309:5 | a [element 4] : | semmle.label | a [element 4] : | +| array_flow.rb:1309:5:1309:5 | a [element 4] : | semmle.label | a [element 4] : | | array_flow.rb:1309:16:1309:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1309:16:1309:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1309:34:1309:46 | call to source : | semmle.label | call to source : | | array_flow.rb:1309:34:1309:46 | call to source : | semmle.label | call to source : | +| array_flow.rb:1310:5:1310:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1310:5:1310:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1310:9:1310:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1310:9:1310:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1310:9:1310:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6356,10 +7820,16 @@ nodes | array_flow.rb:1316:10:1316:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:1316:10:1316:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1316:10:1316:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1318:5:1318:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1318:5:1318:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1318:5:1318:5 | a [element 4] : | semmle.label | a [element 4] : | +| array_flow.rb:1318:5:1318:5 | a [element 4] : | semmle.label | a [element 4] : | | array_flow.rb:1318:16:1318:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1318:16:1318:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1318:34:1318:46 | call to source : | semmle.label | call to source : | | array_flow.rb:1318:34:1318:46 | call to source : | semmle.label | call to source : | +| array_flow.rb:1319:5:1319:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1319:5:1319:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1319:9:1319:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1319:9:1319:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1319:9:1319:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6392,10 +7862,16 @@ nodes | array_flow.rb:1325:10:1325:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:1325:10:1325:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1325:10:1325:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1327:5:1327:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1327:5:1327:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1327:5:1327:5 | a [element 4] : | semmle.label | a [element 4] : | +| array_flow.rb:1327:5:1327:5 | a [element 4] : | semmle.label | a [element 4] : | | array_flow.rb:1327:16:1327:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1327:16:1327:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1327:34:1327:46 | call to source : | semmle.label | call to source : | | array_flow.rb:1327:34:1327:46 | call to source : | semmle.label | call to source : | +| array_flow.rb:1328:5:1328:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1328:5:1328:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:1328:9:1328:9 | [post] a [element 1] : | semmle.label | [post] a [element 1] : | | array_flow.rb:1328:9:1328:9 | [post] a [element 1] : | semmle.label | [post] a [element 1] : | | array_flow.rb:1328:9:1328:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6412,10 +7888,16 @@ nodes | array_flow.rb:1333:10:1333:10 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:1333:10:1333:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1333:10:1333:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1336:5:1336:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1336:5:1336:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1336:5:1336:5 | a [element 4] : | semmle.label | a [element 4] : | +| array_flow.rb:1336:5:1336:5 | a [element 4] : | semmle.label | a [element 4] : | | array_flow.rb:1336:16:1336:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1336:16:1336:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1336:34:1336:46 | call to source : | semmle.label | call to source : | | array_flow.rb:1336:34:1336:46 | call to source : | semmle.label | call to source : | +| array_flow.rb:1337:5:1337:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1337:5:1337:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1337:9:1337:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1337:9:1337:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1337:9:1337:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6448,6 +7930,8 @@ nodes | array_flow.rb:1343:10:1343:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:1343:10:1343:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1343:10:1343:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1347:5:1347:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1347:5:1347:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1347:16:1347:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1347:16:1347:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1348:9:1348:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6456,6 +7940,8 @@ nodes | array_flow.rb:1348:27:1348:27 | x : | semmle.label | x : | | array_flow.rb:1349:14:1349:14 | x | semmle.label | x | | array_flow.rb:1349:14:1349:14 | x | semmle.label | x | +| array_flow.rb:1355:5:1355:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1355:5:1355:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1355:16:1355:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1355:16:1355:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1356:9:1356:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6464,6 +7950,8 @@ nodes | array_flow.rb:1356:28:1356:28 | x : | semmle.label | x : | | array_flow.rb:1357:14:1357:14 | x | semmle.label | x | | array_flow.rb:1357:14:1357:14 | x | semmle.label | x | +| array_flow.rb:1363:5:1363:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1363:5:1363:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1363:16:1363:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1363:16:1363:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1364:9:1364:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6476,8 +7964,12 @@ nodes | array_flow.rb:1365:14:1365:14 | x | semmle.label | x | | array_flow.rb:1366:14:1366:14 | y | semmle.label | y | | array_flow.rb:1366:14:1366:14 | y | semmle.label | y | +| array_flow.rb:1371:5:1371:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1371:5:1371:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1371:16:1371:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1371:16:1371:26 | call to source : | semmle.label | call to source : | +| array_flow.rb:1372:5:1372:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1372:5:1372:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1372:9:1372:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1372:9:1372:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1372:9:1372:14 | call to sort [element] : | semmle.label | call to sort [element] : | @@ -6490,6 +7982,8 @@ nodes | array_flow.rb:1374:10:1374:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1374:10:1374:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1374:10:1374:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1375:5:1375:5 | c [element] : | semmle.label | c [element] : | +| array_flow.rb:1375:5:1375:5 | c [element] : | semmle.label | c [element] : | | array_flow.rb:1375:9:1375:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1375:9:1375:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1375:9:1379:7 | call to sort [element] : | semmle.label | call to sort [element] : | @@ -6510,8 +8004,12 @@ nodes | array_flow.rb:1381:10:1381:10 | c [element] : | semmle.label | c [element] : | | array_flow.rb:1381:10:1381:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1381:10:1381:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1385:5:1385:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1385:5:1385:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1385:16:1385:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1385:16:1385:26 | call to source : | semmle.label | call to source : | +| array_flow.rb:1386:5:1386:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1386:5:1386:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1386:9:1386:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1386:9:1386:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1386:9:1386:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6534,8 +8032,12 @@ nodes | array_flow.rb:1390:10:1390:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:1390:10:1390:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1390:10:1390:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1392:5:1392:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1392:5:1392:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1392:16:1392:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1392:16:1392:26 | call to source : | semmle.label | call to source : | +| array_flow.rb:1393:5:1393:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1393:5:1393:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1393:9:1393:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1393:9:1393:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1393:9:1393:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6566,8 +8068,12 @@ nodes | array_flow.rb:1401:10:1401:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:1401:10:1401:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1401:10:1401:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1405:5:1405:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1405:5:1405:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1405:16:1405:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1405:16:1405:26 | call to source : | semmle.label | call to source : | +| array_flow.rb:1406:5:1406:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1406:5:1406:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1406:9:1406:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1406:9:1406:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1406:9:1409:7 | call to sort_by [element] : | semmle.label | call to sort_by [element] : | @@ -6584,8 +8090,12 @@ nodes | array_flow.rb:1411:10:1411:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1411:10:1411:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1411:10:1411:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1415:5:1415:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1415:5:1415:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1415:16:1415:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1415:16:1415:26 | call to source : | semmle.label | call to source : | +| array_flow.rb:1416:5:1416:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1416:5:1416:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1416:9:1416:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1416:9:1416:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1416:9:1416:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6612,6 +8122,8 @@ nodes | array_flow.rb:1423:10:1423:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1423:10:1423:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1423:10:1423:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1427:5:1427:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1427:5:1427:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1427:16:1427:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1427:16:1427:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1428:9:1428:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6620,10 +8132,18 @@ nodes | array_flow.rb:1428:19:1428:19 | x : | semmle.label | x : | | array_flow.rb:1429:14:1429:14 | x | semmle.label | x | | array_flow.rb:1429:14:1429:14 | x | semmle.label | x | +| array_flow.rb:1435:5:1435:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1435:5:1435:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1435:5:1435:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:1435:5:1435:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1435:16:1435:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1435:16:1435:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1435:31:1435:43 | call to source : | semmle.label | call to source : | | array_flow.rb:1435:31:1435:43 | call to source : | semmle.label | call to source : | +| array_flow.rb:1436:5:1436:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1436:5:1436:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1436:5:1436:5 | b [element 3] : | semmle.label | b [element 3] : | +| array_flow.rb:1436:5:1436:5 | b [element 3] : | semmle.label | b [element 3] : | | array_flow.rb:1436:9:1436:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1436:9:1436:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1436:9:1436:9 | a [element 3] : | semmle.label | a [element 3] : | @@ -6640,6 +8160,8 @@ nodes | array_flow.rb:1440:10:1440:10 | b [element 3] : | semmle.label | b [element 3] : | | array_flow.rb:1440:10:1440:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1440:10:1440:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1441:5:1441:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1441:5:1441:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:1441:9:1441:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1441:9:1441:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1441:9:1441:17 | call to take [element 2] : | semmle.label | call to take [element 2] : | @@ -6652,6 +8174,10 @@ nodes | array_flow.rb:1446:10:1446:10 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:1446:10:1446:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1446:10:1446:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1447:5:1447:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1447:5:1447:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1447:5:1447:5 | b [element 3] : | semmle.label | b [element 3] : | +| array_flow.rb:1447:5:1447:5 | b [element 3] : | semmle.label | b [element 3] : | | array_flow.rb:1447:9:1447:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1447:9:1447:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1447:9:1447:9 | a [element 3] : | semmle.label | a [element 3] : | @@ -6678,6 +8204,10 @@ nodes | array_flow.rb:1453:5:1453:5 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1453:12:1453:24 | call to source : | semmle.label | call to source : | | array_flow.rb:1453:12:1453:24 | call to source : | semmle.label | call to source : | +| array_flow.rb:1454:5:1454:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1454:5:1454:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1454:5:1454:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1454:5:1454:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1454:9:1454:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1454:9:1454:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1454:9:1454:9 | a [element] : | semmle.label | a [element] : | @@ -6692,8 +8222,12 @@ nodes | array_flow.rb:1455:10:1455:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1455:10:1455:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1455:10:1455:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1459:5:1459:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1459:5:1459:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1459:16:1459:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1459:16:1459:26 | call to source : | semmle.label | call to source : | +| array_flow.rb:1460:5:1460:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1460:5:1460:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:1460:9:1460:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1460:9:1460:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1460:9:1463:7 | call to take_while [element 2] : | semmle.label | call to take_while [element 2] : | @@ -6706,8 +8240,12 @@ nodes | array_flow.rb:1466:10:1466:10 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:1466:10:1466:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1466:10:1466:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1472:5:1472:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:1472:5:1472:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1472:19:1472:29 | call to source : | semmle.label | call to source : | | array_flow.rb:1472:19:1472:29 | call to source : | semmle.label | call to source : | +| array_flow.rb:1473:5:1473:5 | b [element 3] : | semmle.label | b [element 3] : | +| array_flow.rb:1473:5:1473:5 | b [element 3] : | semmle.label | b [element 3] : | | array_flow.rb:1473:9:1473:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1473:9:1473:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1473:9:1473:14 | call to to_a [element 3] : | semmle.label | call to to_a [element 3] : | @@ -6716,8 +8254,12 @@ nodes | array_flow.rb:1474:10:1474:10 | b [element 3] : | semmle.label | b [element 3] : | | array_flow.rb:1474:10:1474:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1474:10:1474:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1478:5:1478:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1478:5:1478:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1478:16:1478:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1478:16:1478:26 | call to source : | semmle.label | call to source : | +| array_flow.rb:1479:5:1479:5 | b [element 2] : | semmle.label | b [element 2] : | +| array_flow.rb:1479:5:1479:5 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:1479:9:1479:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1479:9:1479:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1479:9:1479:16 | call to to_ary [element 2] : | semmle.label | call to to_ary [element 2] : | @@ -6726,12 +8268,24 @@ nodes | array_flow.rb:1482:10:1482:10 | b [element 2] : | semmle.label | b [element 2] : | | array_flow.rb:1482:10:1482:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1482:10:1482:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1495:5:1495:5 | a [element 0, element 1] : | semmle.label | a [element 0, element 1] : | +| array_flow.rb:1495:5:1495:5 | a [element 0, element 1] : | semmle.label | a [element 0, element 1] : | +| array_flow.rb:1495:5:1495:5 | a [element 1, element 1] : | semmle.label | a [element 1, element 1] : | +| array_flow.rb:1495:5:1495:5 | a [element 1, element 1] : | semmle.label | a [element 1, element 1] : | +| array_flow.rb:1495:5:1495:5 | a [element 2, element 1] : | semmle.label | a [element 2, element 1] : | +| array_flow.rb:1495:5:1495:5 | a [element 2, element 1] : | semmle.label | a [element 2, element 1] : | | array_flow.rb:1495:14:1495:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1495:14:1495:26 | call to source : | semmle.label | call to source : | | array_flow.rb:1495:34:1495:46 | call to source : | semmle.label | call to source : | | array_flow.rb:1495:34:1495:46 | call to source : | semmle.label | call to source : | | array_flow.rb:1495:54:1495:66 | call to source : | semmle.label | call to source : | | array_flow.rb:1495:54:1495:66 | call to source : | semmle.label | call to source : | +| array_flow.rb:1496:5:1496:5 | b [element 1, element 0] : | semmle.label | b [element 1, element 0] : | +| array_flow.rb:1496:5:1496:5 | b [element 1, element 0] : | semmle.label | b [element 1, element 0] : | +| array_flow.rb:1496:5:1496:5 | b [element 1, element 1] : | semmle.label | b [element 1, element 1] : | +| array_flow.rb:1496:5:1496:5 | b [element 1, element 1] : | semmle.label | b [element 1, element 1] : | +| array_flow.rb:1496:5:1496:5 | b [element 1, element 2] : | semmle.label | b [element 1, element 2] : | +| array_flow.rb:1496:5:1496:5 | b [element 1, element 2] : | semmle.label | b [element 1, element 2] : | | array_flow.rb:1496:9:1496:9 | a [element 0, element 1] : | semmle.label | a [element 0, element 1] : | | array_flow.rb:1496:9:1496:9 | a [element 0, element 1] : | semmle.label | a [element 0, element 1] : | | array_flow.rb:1496:9:1496:9 | a [element 1, element 1] : | semmle.label | a [element 1, element 1] : | @@ -6762,12 +8316,20 @@ nodes | array_flow.rb:1502:10:1502:13 | ...[...] [element 2] : | semmle.label | ...[...] [element 2] : | | array_flow.rb:1502:10:1502:16 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1502:10:1502:16 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1506:5:1506:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1506:5:1506:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1506:16:1506:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1506:16:1506:28 | call to source : | semmle.label | call to source : | +| array_flow.rb:1507:5:1507:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:1507:5:1507:5 | b [element 1] : | semmle.label | b [element 1] : | | array_flow.rb:1507:13:1507:25 | call to source : | semmle.label | call to source : | | array_flow.rb:1507:13:1507:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:1508:5:1508:5 | c [element 1] : | semmle.label | c [element 1] : | +| array_flow.rb:1508:5:1508:5 | c [element 1] : | semmle.label | c [element 1] : | | array_flow.rb:1508:13:1508:25 | call to source : | semmle.label | call to source : | | array_flow.rb:1508:13:1508:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:1509:5:1509:5 | d [element] : | semmle.label | d [element] : | +| array_flow.rb:1509:5:1509:5 | d [element] : | semmle.label | d [element] : | | array_flow.rb:1509:9:1509:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1509:9:1509:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1509:9:1509:21 | call to union [element] : | semmle.label | call to union [element] : | @@ -6788,10 +8350,16 @@ nodes | array_flow.rb:1512:10:1512:10 | d [element] : | semmle.label | d [element] : | | array_flow.rb:1512:10:1512:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1512:10:1512:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1516:5:1516:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:1516:5:1516:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:1516:5:1516:5 | a [element 4] : | semmle.label | a [element 4] : | +| array_flow.rb:1516:5:1516:5 | a [element 4] : | semmle.label | a [element 4] : | | array_flow.rb:1516:19:1516:31 | call to source : | semmle.label | call to source : | | array_flow.rb:1516:19:1516:31 | call to source : | semmle.label | call to source : | | array_flow.rb:1516:34:1516:46 | call to source : | semmle.label | call to source : | | array_flow.rb:1516:34:1516:46 | call to source : | semmle.label | call to source : | +| array_flow.rb:1518:5:1518:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1518:5:1518:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1518:9:1518:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1518:9:1518:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1518:9:1518:9 | a [element 4] : | semmle.label | a [element 4] : | @@ -6806,6 +8374,8 @@ nodes | array_flow.rb:1520:10:1520:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1520:10:1520:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1520:10:1520:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1522:5:1522:5 | c [element] : | semmle.label | c [element] : | +| array_flow.rb:1522:5:1522:5 | c [element] : | semmle.label | c [element] : | | array_flow.rb:1522:9:1522:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1522:9:1522:9 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1522:9:1522:9 | a [element 4] : | semmle.label | a [element 4] : | @@ -6820,10 +8390,16 @@ nodes | array_flow.rb:1526:10:1526:10 | c [element] : | semmle.label | c [element] : | | array_flow.rb:1526:10:1526:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1526:10:1526:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1530:5:1530:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1530:5:1530:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1530:5:1530:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:1530:5:1530:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1530:16:1530:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1530:16:1530:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1530:31:1530:43 | call to source : | semmle.label | call to source : | | array_flow.rb:1530:31:1530:43 | call to source : | semmle.label | call to source : | +| array_flow.rb:1531:5:1531:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1531:5:1531:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1531:9:1531:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1531:9:1531:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1531:9:1531:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6848,10 +8424,16 @@ nodes | array_flow.rb:1535:10:1535:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:1535:10:1535:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1535:10:1535:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1537:5:1537:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1537:5:1537:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1537:5:1537:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:1537:5:1537:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1537:16:1537:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1537:16:1537:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1537:31:1537:43 | call to source : | semmle.label | call to source : | | array_flow.rb:1537:31:1537:43 | call to source : | semmle.label | call to source : | +| array_flow.rb:1538:5:1538:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1538:5:1538:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1538:9:1538:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1538:9:1538:9 | [post] a [element] : | semmle.label | [post] a [element] : | | array_flow.rb:1538:9:1538:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -6880,6 +8462,8 @@ nodes | array_flow.rb:1545:10:1545:10 | a [element] : | semmle.label | a [element] : | | array_flow.rb:1545:10:1545:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1545:10:1545:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1549:5:1549:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1549:5:1549:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1549:16:1549:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1549:16:1549:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1550:5:1550:5 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | @@ -6898,10 +8482,18 @@ nodes | array_flow.rb:1556:10:1556:10 | a [element 5] : | semmle.label | a [element 5] : | | array_flow.rb:1556:10:1556:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1556:10:1556:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1560:5:1560:5 | a [element 1] : | semmle.label | a [element 1] : | +| array_flow.rb:1560:5:1560:5 | a [element 1] : | semmle.label | a [element 1] : | +| array_flow.rb:1560:5:1560:5 | a [element 3] : | semmle.label | a [element 3] : | +| array_flow.rb:1560:5:1560:5 | a [element 3] : | semmle.label | a [element 3] : | | array_flow.rb:1560:13:1560:25 | call to source : | semmle.label | call to source : | | array_flow.rb:1560:13:1560:25 | call to source : | semmle.label | call to source : | | array_flow.rb:1560:31:1560:43 | call to source : | semmle.label | call to source : | | array_flow.rb:1560:31:1560:43 | call to source : | semmle.label | call to source : | +| array_flow.rb:1562:5:1562:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:1562:5:1562:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:1562:5:1562:5 | b [element 3] : | semmle.label | b [element 3] : | +| array_flow.rb:1562:5:1562:5 | b [element 3] : | semmle.label | b [element 3] : | | array_flow.rb:1562:9:1562:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:1562:9:1562:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:1562:9:1562:31 | call to values_at [element 1] : | semmle.label | call to values_at [element 1] : | @@ -6916,6 +8508,8 @@ nodes | array_flow.rb:1566:10:1566:10 | b [element 3] : | semmle.label | b [element 3] : | | array_flow.rb:1566:10:1566:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1566:10:1566:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1568:5:1568:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1568:5:1568:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1568:9:1568:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:1568:9:1568:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:1568:9:1568:9 | a [element 3] : | semmle.label | a [element 3] : | @@ -6930,6 +8524,8 @@ nodes | array_flow.rb:1570:10:1570:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1570:10:1570:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1570:10:1570:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1572:5:1572:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1572:5:1572:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1572:9:1572:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:1572:9:1572:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:1572:9:1572:9 | a [element 3] : | semmle.label | a [element 3] : | @@ -6944,6 +8540,10 @@ nodes | array_flow.rb:1574:10:1574:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1574:10:1574:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1574:10:1574:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1576:5:1576:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:1576:5:1576:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:1576:5:1576:5 | b [element] : | semmle.label | b [element] : | +| array_flow.rb:1576:5:1576:5 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1576:9:1576:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:1576:9:1576:9 | a [element 1] : | semmle.label | a [element 1] : | | array_flow.rb:1576:9:1576:9 | a [element 3] : | semmle.label | a [element 3] : | @@ -6970,12 +8570,24 @@ nodes | array_flow.rb:1580:10:1580:10 | b [element] : | semmle.label | b [element] : | | array_flow.rb:1580:10:1580:13 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1580:10:1580:13 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1584:5:1584:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1584:5:1584:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1584:16:1584:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1584:16:1584:28 | call to source : | semmle.label | call to source : | +| array_flow.rb:1585:5:1585:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:1585:5:1585:5 | b [element 1] : | semmle.label | b [element 1] : | | array_flow.rb:1585:13:1585:25 | call to source : | semmle.label | call to source : | | array_flow.rb:1585:13:1585:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:1586:5:1586:5 | c [element 0] : | semmle.label | c [element 0] : | +| array_flow.rb:1586:5:1586:5 | c [element 0] : | semmle.label | c [element 0] : | | array_flow.rb:1586:10:1586:22 | call to source : | semmle.label | call to source : | | array_flow.rb:1586:10:1586:22 | call to source : | semmle.label | call to source : | +| array_flow.rb:1587:5:1587:5 | d [element 0, element 2] : | semmle.label | d [element 0, element 2] : | +| array_flow.rb:1587:5:1587:5 | d [element 0, element 2] : | semmle.label | d [element 0, element 2] : | +| array_flow.rb:1587:5:1587:5 | d [element 1, element 1] : | semmle.label | d [element 1, element 1] : | +| array_flow.rb:1587:5:1587:5 | d [element 1, element 1] : | semmle.label | d [element 1, element 1] : | +| array_flow.rb:1587:5:1587:5 | d [element 2, element 0] : | semmle.label | d [element 2, element 0] : | +| array_flow.rb:1587:5:1587:5 | d [element 2, element 0] : | semmle.label | d [element 2, element 0] : | | array_flow.rb:1587:9:1587:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1587:9:1587:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1587:9:1587:19 | call to zip [element 0, element 2] : | semmle.label | call to zip [element 0, element 2] : | @@ -7030,10 +8642,16 @@ nodes | array_flow.rb:1595:14:1595:14 | x [element 2] : | semmle.label | x [element 2] : | | array_flow.rb:1595:14:1595:17 | ...[...] | semmle.label | ...[...] | | array_flow.rb:1595:14:1595:17 | ...[...] | semmle.label | ...[...] | +| array_flow.rb:1600:5:1600:5 | a [element 2] : | semmle.label | a [element 2] : | +| array_flow.rb:1600:5:1600:5 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1600:16:1600:28 | call to source : | semmle.label | call to source : | | array_flow.rb:1600:16:1600:28 | call to source : | semmle.label | call to source : | +| array_flow.rb:1601:5:1601:5 | b [element 1] : | semmle.label | b [element 1] : | +| array_flow.rb:1601:5:1601:5 | b [element 1] : | semmle.label | b [element 1] : | | array_flow.rb:1601:13:1601:25 | call to source : | semmle.label | call to source : | | array_flow.rb:1601:13:1601:25 | call to source : | semmle.label | call to source : | +| array_flow.rb:1602:5:1602:5 | c [element] : | semmle.label | c [element] : | +| array_flow.rb:1602:5:1602:5 | c [element] : | semmle.label | c [element] : | | array_flow.rb:1602:9:1602:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1602:9:1602:9 | a [element 2] : | semmle.label | a [element 2] : | | array_flow.rb:1602:9:1602:13 | ... \| ... [element] : | semmle.label | ... \| ... [element] : | diff --git a/ruby/ql/test/library-tests/dataflow/flow-summaries/semantics.expected b/ruby/ql/test/library-tests/dataflow/flow-summaries/semantics.expected index 4ef45d2ae92..db759c1f86a 100644 --- a/ruby/ql/test/library-tests/dataflow/flow-summaries/semantics.expected +++ b/ruby/ql/test/library-tests/dataflow/flow-summaries/semantics.expected @@ -1,19 +1,27 @@ failures edges -| semantics.rb:2:9:2:18 | call to source : | semantics.rb:3:9:3:9 | a : | -| semantics.rb:2:9:2:18 | call to source : | semantics.rb:3:9:3:9 | a : | +| semantics.rb:2:5:2:5 | a : | semantics.rb:3:9:3:9 | a : | +| semantics.rb:2:5:2:5 | a : | semantics.rb:3:9:3:9 | a : | +| semantics.rb:2:9:2:18 | call to source : | semantics.rb:2:5:2:5 | a : | +| semantics.rb:2:9:2:18 | call to source : | semantics.rb:2:5:2:5 | a : | +| semantics.rb:3:5:3:5 | x : | semantics.rb:4:10:4:10 | x | +| semantics.rb:3:5:3:5 | x : | semantics.rb:4:10:4:10 | x | | semantics.rb:3:9:3:9 | a : | semantics.rb:3:9:3:14 | call to s1 : | | semantics.rb:3:9:3:9 | a : | semantics.rb:3:9:3:14 | call to s1 : | -| semantics.rb:3:9:3:14 | call to s1 : | semantics.rb:4:10:4:10 | x | -| semantics.rb:3:9:3:14 | call to s1 : | semantics.rb:4:10:4:10 | x | -| semantics.rb:8:9:8:18 | call to source : | semantics.rb:9:10:9:10 | a : | -| semantics.rb:8:9:8:18 | call to source : | semantics.rb:9:10:9:10 | a : | +| semantics.rb:3:9:3:14 | call to s1 : | semantics.rb:3:5:3:5 | x : | +| semantics.rb:3:9:3:14 | call to s1 : | semantics.rb:3:5:3:5 | x : | +| semantics.rb:8:5:8:5 | a : | semantics.rb:9:10:9:10 | a : | +| semantics.rb:8:5:8:5 | a : | semantics.rb:9:10:9:10 | a : | +| semantics.rb:8:9:8:18 | call to source : | semantics.rb:8:5:8:5 | a : | +| semantics.rb:8:9:8:18 | call to source : | semantics.rb:8:5:8:5 | a : | | semantics.rb:9:5:9:5 | [post] x : | semantics.rb:10:10:10:10 | x | | semantics.rb:9:5:9:5 | [post] x : | semantics.rb:10:10:10:10 | x | | semantics.rb:9:10:9:10 | a : | semantics.rb:9:5:9:5 | [post] x : | | semantics.rb:9:10:9:10 | a : | semantics.rb:9:5:9:5 | [post] x : | -| semantics.rb:14:9:14:18 | call to source : | semantics.rb:15:8:15:8 | a : | -| semantics.rb:14:9:14:18 | call to source : | semantics.rb:15:8:15:8 | a : | +| semantics.rb:14:5:14:5 | a : | semantics.rb:15:8:15:8 | a : | +| semantics.rb:14:5:14:5 | a : | semantics.rb:15:8:15:8 | a : | +| semantics.rb:14:9:14:18 | call to source : | semantics.rb:14:5:14:5 | a : | +| semantics.rb:14:9:14:18 | call to source : | semantics.rb:14:5:14:5 | a : | | semantics.rb:15:8:15:8 | a : | semantics.rb:15:11:15:11 | [post] x : | | semantics.rb:15:8:15:8 | a : | semantics.rb:15:11:15:11 | [post] x : | | semantics.rb:15:11:15:11 | [post] x : | semantics.rb:16:10:16:10 | x | @@ -22,8 +30,10 @@ edges | semantics.rb:22:18:22:32 | call to source : | semantics.rb:22:10:22:33 | call to s4 | | semantics.rb:23:23:23:32 | call to source : | semantics.rb:23:10:23:33 | call to s4 | | semantics.rb:23:23:23:32 | call to source : | semantics.rb:23:10:23:33 | call to s4 | -| semantics.rb:28:9:28:18 | call to source : | semantics.rb:29:8:29:8 | a : | -| semantics.rb:28:9:28:18 | call to source : | semantics.rb:29:8:29:8 | a : | +| semantics.rb:28:5:28:5 | a : | semantics.rb:29:8:29:8 | a : | +| semantics.rb:28:5:28:5 | a : | semantics.rb:29:8:29:8 | a : | +| semantics.rb:28:9:28:18 | call to source : | semantics.rb:28:5:28:5 | a : | +| semantics.rb:28:9:28:18 | call to source : | semantics.rb:28:5:28:5 | a : | | semantics.rb:29:8:29:8 | a : | semantics.rb:29:14:29:14 | [post] y : | | semantics.rb:29:8:29:8 | a : | semantics.rb:29:14:29:14 | [post] y : | | semantics.rb:29:8:29:8 | a : | semantics.rb:29:17:29:17 | [post] z : | @@ -32,8 +42,10 @@ edges | semantics.rb:29:14:29:14 | [post] y : | semantics.rb:31:10:31:10 | y | | semantics.rb:29:17:29:17 | [post] z : | semantics.rb:32:10:32:10 | z | | semantics.rb:29:17:29:17 | [post] z : | semantics.rb:32:10:32:10 | z | -| semantics.rb:40:9:40:18 | call to source : | semantics.rb:41:8:41:8 | a : | -| semantics.rb:40:9:40:18 | call to source : | semantics.rb:41:8:41:8 | a : | +| semantics.rb:40:5:40:5 | a : | semantics.rb:41:8:41:8 | a : | +| semantics.rb:40:5:40:5 | a : | semantics.rb:41:8:41:8 | a : | +| semantics.rb:40:9:40:18 | call to source : | semantics.rb:40:5:40:5 | a : | +| semantics.rb:40:9:40:18 | call to source : | semantics.rb:40:5:40:5 | a : | | semantics.rb:41:8:41:8 | a : | semantics.rb:41:16:41:16 | [post] x : | | semantics.rb:41:8:41:8 | a : | semantics.rb:41:16:41:16 | [post] x : | | semantics.rb:41:16:41:16 | [post] x : | semantics.rb:42:10:42:10 | x | @@ -50,16 +62,18 @@ edges | semantics.rb:54:8:54:17 | call to source : | semantics.rb:54:24:54:24 | x : | | semantics.rb:54:24:54:24 | x : | semantics.rb:55:14:55:14 | x | | semantics.rb:54:24:54:24 | x : | semantics.rb:55:14:55:14 | x | -| semantics.rb:60:9:60:18 | call to source : | semantics.rb:61:14:61:14 | a : | -| semantics.rb:60:9:60:18 | call to source : | semantics.rb:61:14:61:14 | a : | -| semantics.rb:60:9:60:18 | call to source : | semantics.rb:62:17:62:17 | a : | -| semantics.rb:60:9:60:18 | call to source : | semantics.rb:62:17:62:17 | a : | -| semantics.rb:60:9:60:18 | call to source : | semantics.rb:63:19:63:19 | a : | -| semantics.rb:60:9:60:18 | call to source : | semantics.rb:63:19:63:19 | a : | -| semantics.rb:60:9:60:18 | call to source : | semantics.rb:64:27:64:27 | a : | -| semantics.rb:60:9:60:18 | call to source : | semantics.rb:64:27:64:27 | a : | -| semantics.rb:60:9:60:18 | call to source : | semantics.rb:66:14:66:15 | &... : | -| semantics.rb:60:9:60:18 | call to source : | semantics.rb:66:14:66:15 | &... : | +| semantics.rb:60:5:60:5 | a : | semantics.rb:61:14:61:14 | a : | +| semantics.rb:60:5:60:5 | a : | semantics.rb:61:14:61:14 | a : | +| semantics.rb:60:5:60:5 | a : | semantics.rb:62:17:62:17 | a : | +| semantics.rb:60:5:60:5 | a : | semantics.rb:62:17:62:17 | a : | +| semantics.rb:60:5:60:5 | a : | semantics.rb:63:19:63:19 | a : | +| semantics.rb:60:5:60:5 | a : | semantics.rb:63:19:63:19 | a : | +| semantics.rb:60:5:60:5 | a : | semantics.rb:64:27:64:27 | a : | +| semantics.rb:60:5:60:5 | a : | semantics.rb:64:27:64:27 | a : | +| semantics.rb:60:5:60:5 | a : | semantics.rb:66:14:66:15 | &... : | +| semantics.rb:60:5:60:5 | a : | semantics.rb:66:14:66:15 | &... : | +| semantics.rb:60:9:60:18 | call to source : | semantics.rb:60:5:60:5 | a : | +| semantics.rb:60:9:60:18 | call to source : | semantics.rb:60:5:60:5 | a : | | semantics.rb:61:14:61:14 | a : | semantics.rb:61:10:61:15 | call to s10 | | semantics.rb:61:14:61:14 | a : | semantics.rb:61:10:61:15 | call to s10 | | semantics.rb:62:17:62:17 | a : | semantics.rb:62:10:62:18 | call to s10 | @@ -70,8 +84,10 @@ edges | semantics.rb:64:27:64:27 | a : | semantics.rb:64:10:64:28 | call to s10 | | semantics.rb:66:14:66:15 | &... : | semantics.rb:66:10:66:16 | call to s10 | | semantics.rb:66:14:66:15 | &... : | semantics.rb:66:10:66:16 | call to s10 | -| semantics.rb:80:9:80:18 | call to source : | semantics.rb:81:5:81:5 | a : | -| semantics.rb:80:9:80:18 | call to source : | semantics.rb:81:5:81:5 | a : | +| semantics.rb:80:5:80:5 | a : | semantics.rb:81:5:81:5 | a : | +| semantics.rb:80:5:80:5 | a : | semantics.rb:81:5:81:5 | a : | +| semantics.rb:80:9:80:18 | call to source : | semantics.rb:80:5:80:5 | a : | +| semantics.rb:80:9:80:18 | call to source : | semantics.rb:80:5:80:5 | a : | | semantics.rb:81:5:81:5 | a : | semantics.rb:81:11:81:11 | [post] x : | | semantics.rb:81:5:81:5 | a : | semantics.rb:81:11:81:11 | [post] x : | | semantics.rb:81:5:81:5 | a : | semantics.rb:81:14:81:14 | [post] y : | @@ -84,18 +100,22 @@ edges | semantics.rb:81:14:81:14 | [post] y : | semantics.rb:83:10:83:10 | y | | semantics.rb:81:22:81:22 | [post] z : | semantics.rb:84:10:84:10 | z | | semantics.rb:81:22:81:22 | [post] z : | semantics.rb:84:10:84:10 | z | -| semantics.rb:89:9:89:18 | call to source : | semantics.rb:91:19:91:19 | a : | -| semantics.rb:89:9:89:18 | call to source : | semantics.rb:91:19:91:19 | a : | -| semantics.rb:89:9:89:18 | call to source : | semantics.rb:92:27:92:27 | a : | -| semantics.rb:89:9:89:18 | call to source : | semantics.rb:92:27:92:27 | a : | +| semantics.rb:89:5:89:5 | a : | semantics.rb:91:19:91:19 | a : | +| semantics.rb:89:5:89:5 | a : | semantics.rb:91:19:91:19 | a : | +| semantics.rb:89:5:89:5 | a : | semantics.rb:92:27:92:27 | a : | +| semantics.rb:89:5:89:5 | a : | semantics.rb:92:27:92:27 | a : | +| semantics.rb:89:9:89:18 | call to source : | semantics.rb:89:5:89:5 | a : | +| semantics.rb:89:9:89:18 | call to source : | semantics.rb:89:5:89:5 | a : | | semantics.rb:91:19:91:19 | a : | semantics.rb:91:10:91:20 | call to s13 | | semantics.rb:91:19:91:19 | a : | semantics.rb:91:10:91:20 | call to s13 | | semantics.rb:92:27:92:27 | a : | semantics.rb:92:10:92:28 | call to s13 | | semantics.rb:92:27:92:27 | a : | semantics.rb:92:10:92:28 | call to s13 | -| semantics.rb:97:9:97:18 | call to source : | semantics.rb:98:5:98:5 | a : | -| semantics.rb:97:9:97:18 | call to source : | semantics.rb:98:5:98:5 | a : | -| semantics.rb:97:9:97:18 | call to source : | semantics.rb:99:5:99:5 | a : | -| semantics.rb:97:9:97:18 | call to source : | semantics.rb:99:5:99:5 | a : | +| semantics.rb:97:5:97:5 | a : | semantics.rb:98:5:98:5 | a : | +| semantics.rb:97:5:97:5 | a : | semantics.rb:98:5:98:5 | a : | +| semantics.rb:97:5:97:5 | a : | semantics.rb:99:5:99:5 | a : | +| semantics.rb:97:5:97:5 | a : | semantics.rb:99:5:99:5 | a : | +| semantics.rb:97:9:97:18 | call to source : | semantics.rb:97:5:97:5 | a : | +| semantics.rb:97:9:97:18 | call to source : | semantics.rb:97:5:97:5 | a : | | semantics.rb:98:5:98:5 | a : | semantics.rb:98:19:98:19 | [post] x : | | semantics.rb:98:5:98:5 | a : | semantics.rb:98:19:98:19 | [post] x : | | semantics.rb:98:19:98:19 | [post] x : | semantics.rb:101:10:101:10 | x | @@ -108,20 +128,27 @@ edges | semantics.rb:99:16:99:16 | [post] y : | semantics.rb:102:10:102:10 | y | | semantics.rb:99:24:99:24 | [post] z : | semantics.rb:103:10:103:10 | z | | semantics.rb:99:24:99:24 | [post] z : | semantics.rb:103:10:103:10 | z | -| semantics.rb:107:9:107:18 | call to source : | semantics.rb:109:14:109:16 | ** ... : | -| semantics.rb:107:9:107:18 | call to source : | semantics.rb:110:28:110:30 | ** ... : | +| semantics.rb:107:5:107:5 | a : | semantics.rb:109:14:109:16 | ** ... : | +| semantics.rb:107:5:107:5 | a : | semantics.rb:110:28:110:30 | ** ... : | +| semantics.rb:107:9:107:18 | call to source : | semantics.rb:107:5:107:5 | a : | | semantics.rb:109:14:109:16 | ** ... : | semantics.rb:109:10:109:17 | call to s15 | | semantics.rb:110:28:110:30 | ** ... : | semantics.rb:110:10:110:31 | call to s15 | -| semantics.rb:114:9:114:18 | call to source : | semantics.rb:116:14:116:14 | a : | -| semantics.rb:114:9:114:18 | call to source : | semantics.rb:116:14:116:14 | a : | -| semantics.rb:114:9:114:18 | call to source : | semantics.rb:119:17:119:17 | a : | -| semantics.rb:114:9:114:18 | call to source : | semantics.rb:119:17:119:17 | a : | -| semantics.rb:115:9:115:18 | call to source : | semantics.rb:121:17:121:17 | b : | -| semantics.rb:115:9:115:18 | call to source : | semantics.rb:121:17:121:17 | b : | -| semantics.rb:116:14:116:14 | a : | semantics.rb:117:16:117:16 | h [element :a] : | -| semantics.rb:116:14:116:14 | a : | semantics.rb:117:16:117:16 | h [element :a] : | -| semantics.rb:116:14:116:14 | a : | semantics.rb:121:22:121:22 | h [element :a] : | -| semantics.rb:116:14:116:14 | a : | semantics.rb:121:22:121:22 | h [element :a] : | +| semantics.rb:114:5:114:5 | a : | semantics.rb:116:14:116:14 | a : | +| semantics.rb:114:5:114:5 | a : | semantics.rb:116:14:116:14 | a : | +| semantics.rb:114:5:114:5 | a : | semantics.rb:119:17:119:17 | a : | +| semantics.rb:114:5:114:5 | a : | semantics.rb:119:17:119:17 | a : | +| semantics.rb:114:9:114:18 | call to source : | semantics.rb:114:5:114:5 | a : | +| semantics.rb:114:9:114:18 | call to source : | semantics.rb:114:5:114:5 | a : | +| semantics.rb:115:5:115:5 | b : | semantics.rb:121:17:121:17 | b : | +| semantics.rb:115:5:115:5 | b : | semantics.rb:121:17:121:17 | b : | +| semantics.rb:115:9:115:18 | call to source : | semantics.rb:115:5:115:5 | b : | +| semantics.rb:115:9:115:18 | call to source : | semantics.rb:115:5:115:5 | b : | +| semantics.rb:116:5:116:5 | h [element :a] : | semantics.rb:117:16:117:16 | h [element :a] : | +| semantics.rb:116:5:116:5 | h [element :a] : | semantics.rb:117:16:117:16 | h [element :a] : | +| semantics.rb:116:5:116:5 | h [element :a] : | semantics.rb:121:22:121:22 | h [element :a] : | +| semantics.rb:116:5:116:5 | h [element :a] : | semantics.rb:121:22:121:22 | h [element :a] : | +| semantics.rb:116:14:116:14 | a : | semantics.rb:116:5:116:5 | h [element :a] : | +| semantics.rb:116:14:116:14 | a : | semantics.rb:116:5:116:5 | h [element :a] : | | semantics.rb:117:14:117:16 | ** ... [element :a] : | semantics.rb:117:10:117:17 | call to s16 | | semantics.rb:117:14:117:16 | ** ... [element :a] : | semantics.rb:117:10:117:17 | call to s16 | | semantics.rb:117:16:117:16 | h [element :a] : | semantics.rb:117:14:117:16 | ** ... [element :a] : | @@ -134,34 +161,46 @@ edges | semantics.rb:121:20:121:22 | ** ... [element :a] : | semantics.rb:121:10:121:23 | call to s16 | | semantics.rb:121:22:121:22 | h [element :a] : | semantics.rb:121:20:121:22 | ** ... [element :a] : | | semantics.rb:121:22:121:22 | h [element :a] : | semantics.rb:121:20:121:22 | ** ... [element :a] : | -| semantics.rb:125:9:125:18 | call to source : | semantics.rb:126:9:126:9 | a : | -| semantics.rb:125:9:125:18 | call to source : | semantics.rb:126:9:126:9 | a : | +| semantics.rb:125:5:125:5 | a : | semantics.rb:126:9:126:9 | a : | +| semantics.rb:125:5:125:5 | a : | semantics.rb:126:9:126:9 | a : | +| semantics.rb:125:9:125:18 | call to source : | semantics.rb:125:5:125:5 | a : | +| semantics.rb:125:9:125:18 | call to source : | semantics.rb:125:5:125:5 | a : | | semantics.rb:126:9:126:9 | a : | semantics.rb:126:12:126:14 | [post] ** ... : | | semantics.rb:126:9:126:9 | a : | semantics.rb:126:12:126:14 | [post] ** ... : | | semantics.rb:126:12:126:14 | [post] ** ... : | semantics.rb:127:10:127:10 | h | | semantics.rb:126:12:126:14 | [post] ** ... : | semantics.rb:127:10:127:10 | h | -| semantics.rb:141:9:141:18 | call to source : | semantics.rb:145:5:145:5 | [post] h [element] : | -| semantics.rb:141:9:141:18 | call to source : | semantics.rb:145:5:145:5 | [post] h [element] : | +| semantics.rb:141:5:141:5 | b : | semantics.rb:145:5:145:5 | [post] h [element] : | +| semantics.rb:141:5:141:5 | b : | semantics.rb:145:5:145:5 | [post] h [element] : | +| semantics.rb:141:9:141:18 | call to source : | semantics.rb:141:5:141:5 | b : | +| semantics.rb:141:9:141:18 | call to source : | semantics.rb:141:5:141:5 | b : | | semantics.rb:145:5:145:5 | [post] h [element] : | semantics.rb:147:14:147:14 | h [element] : | | semantics.rb:145:5:145:5 | [post] h [element] : | semantics.rb:147:14:147:14 | h [element] : | | semantics.rb:147:14:147:14 | h [element] : | semantics.rb:147:10:147:15 | call to s19 | | semantics.rb:147:14:147:14 | h [element] : | semantics.rb:147:10:147:15 | call to s19 | -| semantics.rb:151:9:151:18 | call to source : | semantics.rb:152:13:152:13 | a : | -| semantics.rb:151:9:151:18 | call to source : | semantics.rb:152:13:152:13 | a : | -| semantics.rb:152:9:152:14 | call to s20 [element] : | semantics.rb:153:10:153:10 | x [element] : | -| semantics.rb:152:9:152:14 | call to s20 [element] : | semantics.rb:153:10:153:10 | x [element] : | -| semantics.rb:152:9:152:14 | call to s20 [element] : | semantics.rb:154:10:154:10 | x [element] : | -| semantics.rb:152:9:152:14 | call to s20 [element] : | semantics.rb:154:10:154:10 | x [element] : | +| semantics.rb:151:5:151:5 | a : | semantics.rb:152:13:152:13 | a : | +| semantics.rb:151:5:151:5 | a : | semantics.rb:152:13:152:13 | a : | +| semantics.rb:151:9:151:18 | call to source : | semantics.rb:151:5:151:5 | a : | +| semantics.rb:151:9:151:18 | call to source : | semantics.rb:151:5:151:5 | a : | +| semantics.rb:152:5:152:5 | x [element] : | semantics.rb:153:10:153:10 | x [element] : | +| semantics.rb:152:5:152:5 | x [element] : | semantics.rb:153:10:153:10 | x [element] : | +| semantics.rb:152:5:152:5 | x [element] : | semantics.rb:154:10:154:10 | x [element] : | +| semantics.rb:152:5:152:5 | x [element] : | semantics.rb:154:10:154:10 | x [element] : | +| semantics.rb:152:9:152:14 | call to s20 [element] : | semantics.rb:152:5:152:5 | x [element] : | +| semantics.rb:152:9:152:14 | call to s20 [element] : | semantics.rb:152:5:152:5 | x [element] : | | semantics.rb:152:13:152:13 | a : | semantics.rb:152:9:152:14 | call to s20 [element] : | | semantics.rb:152:13:152:13 | a : | semantics.rb:152:9:152:14 | call to s20 [element] : | | semantics.rb:153:10:153:10 | x [element] : | semantics.rb:153:10:153:13 | ...[...] | | semantics.rb:153:10:153:10 | x [element] : | semantics.rb:153:10:153:13 | ...[...] | | semantics.rb:154:10:154:10 | x [element] : | semantics.rb:154:10:154:13 | ...[...] | | semantics.rb:154:10:154:10 | x [element] : | semantics.rb:154:10:154:13 | ...[...] | -| semantics.rb:158:9:158:18 | call to source : | semantics.rb:162:5:162:5 | [post] h [element 0] : | -| semantics.rb:158:9:158:18 | call to source : | semantics.rb:162:5:162:5 | [post] h [element 0] : | -| semantics.rb:159:9:159:18 | call to source : | semantics.rb:163:5:163:5 | [post] h [element] : | -| semantics.rb:159:9:159:18 | call to source : | semantics.rb:163:5:163:5 | [post] h [element] : | +| semantics.rb:158:5:158:5 | a : | semantics.rb:162:5:162:5 | [post] h [element 0] : | +| semantics.rb:158:5:158:5 | a : | semantics.rb:162:5:162:5 | [post] h [element 0] : | +| semantics.rb:158:9:158:18 | call to source : | semantics.rb:158:5:158:5 | a : | +| semantics.rb:158:9:158:18 | call to source : | semantics.rb:158:5:158:5 | a : | +| semantics.rb:159:5:159:5 | b : | semantics.rb:163:5:163:5 | [post] h [element] : | +| semantics.rb:159:5:159:5 | b : | semantics.rb:163:5:163:5 | [post] h [element] : | +| semantics.rb:159:9:159:18 | call to source : | semantics.rb:159:5:159:5 | b : | +| semantics.rb:159:9:159:18 | call to source : | semantics.rb:159:5:159:5 | b : | | semantics.rb:162:5:162:5 | [post] h [element 0] : | semantics.rb:165:14:165:14 | h [element 0] : | | semantics.rb:162:5:162:5 | [post] h [element 0] : | semantics.rb:165:14:165:14 | h [element 0] : | | semantics.rb:163:5:163:5 | [post] h [element] : | semantics.rb:165:14:165:14 | h [element] : | @@ -170,20 +209,26 @@ edges | semantics.rb:165:14:165:14 | h [element 0] : | semantics.rb:165:10:165:15 | call to s21 | | semantics.rb:165:14:165:14 | h [element] : | semantics.rb:165:10:165:15 | call to s21 | | semantics.rb:165:14:165:14 | h [element] : | semantics.rb:165:10:165:15 | call to s21 | -| semantics.rb:169:9:169:18 | call to source : | semantics.rb:170:13:170:13 | a : | -| semantics.rb:169:9:169:18 | call to source : | semantics.rb:170:13:170:13 | a : | -| semantics.rb:170:9:170:14 | call to s22 [element] : | semantics.rb:171:10:171:10 | x [element] : | -| semantics.rb:170:9:170:14 | call to s22 [element] : | semantics.rb:171:10:171:10 | x [element] : | -| semantics.rb:170:9:170:14 | call to s22 [element] : | semantics.rb:172:10:172:10 | x [element] : | -| semantics.rb:170:9:170:14 | call to s22 [element] : | semantics.rb:172:10:172:10 | x [element] : | +| semantics.rb:169:5:169:5 | a : | semantics.rb:170:13:170:13 | a : | +| semantics.rb:169:5:169:5 | a : | semantics.rb:170:13:170:13 | a : | +| semantics.rb:169:9:169:18 | call to source : | semantics.rb:169:5:169:5 | a : | +| semantics.rb:169:9:169:18 | call to source : | semantics.rb:169:5:169:5 | a : | +| semantics.rb:170:5:170:5 | x [element] : | semantics.rb:171:10:171:10 | x [element] : | +| semantics.rb:170:5:170:5 | x [element] : | semantics.rb:171:10:171:10 | x [element] : | +| semantics.rb:170:5:170:5 | x [element] : | semantics.rb:172:10:172:10 | x [element] : | +| semantics.rb:170:5:170:5 | x [element] : | semantics.rb:172:10:172:10 | x [element] : | +| semantics.rb:170:9:170:14 | call to s22 [element] : | semantics.rb:170:5:170:5 | x [element] : | +| semantics.rb:170:9:170:14 | call to s22 [element] : | semantics.rb:170:5:170:5 | x [element] : | | semantics.rb:170:13:170:13 | a : | semantics.rb:170:9:170:14 | call to s22 [element] : | | semantics.rb:170:13:170:13 | a : | semantics.rb:170:9:170:14 | call to s22 [element] : | | semantics.rb:171:10:171:10 | x [element] : | semantics.rb:171:10:171:13 | ...[...] | | semantics.rb:171:10:171:10 | x [element] : | semantics.rb:171:10:171:13 | ...[...] | | semantics.rb:172:10:172:10 | x [element] : | semantics.rb:172:10:172:13 | ...[...] | | semantics.rb:172:10:172:10 | x [element] : | semantics.rb:172:10:172:13 | ...[...] | -| semantics.rb:176:9:176:18 | call to source : | semantics.rb:179:5:179:5 | [post] h [element 0] : | -| semantics.rb:176:9:176:18 | call to source : | semantics.rb:179:5:179:5 | [post] h [element 0] : | +| semantics.rb:176:5:176:5 | a : | semantics.rb:179:5:179:5 | [post] h [element 0] : | +| semantics.rb:176:5:176:5 | a : | semantics.rb:179:5:179:5 | [post] h [element 0] : | +| semantics.rb:176:9:176:18 | call to source : | semantics.rb:176:5:176:5 | a : | +| semantics.rb:176:9:176:18 | call to source : | semantics.rb:176:5:176:5 | a : | | semantics.rb:179:5:179:5 | [post] h [element 0] : | semantics.rb:180:5:180:5 | h [element 0] : | | semantics.rb:179:5:179:5 | [post] h [element 0] : | semantics.rb:180:5:180:5 | h [element 0] : | | semantics.rb:180:5:180:5 | [post] h [element 0] : | semantics.rb:181:14:181:14 | h [element 0] : | @@ -192,20 +237,26 @@ edges | semantics.rb:180:5:180:5 | h [element 0] : | semantics.rb:180:5:180:5 | [post] h [element 0] : | | semantics.rb:181:14:181:14 | h [element 0] : | semantics.rb:181:10:181:15 | call to s23 | | semantics.rb:181:14:181:14 | h [element 0] : | semantics.rb:181:10:181:15 | call to s23 | -| semantics.rb:185:9:185:18 | call to source : | semantics.rb:186:13:186:13 | a : | -| semantics.rb:185:9:185:18 | call to source : | semantics.rb:186:13:186:13 | a : | -| semantics.rb:186:9:186:14 | call to s24 [element 0] : | semantics.rb:187:10:187:10 | x [element 0] : | -| semantics.rb:186:9:186:14 | call to s24 [element 0] : | semantics.rb:187:10:187:10 | x [element 0] : | -| semantics.rb:186:9:186:14 | call to s24 [element 0] : | semantics.rb:189:10:189:10 | x [element 0] : | -| semantics.rb:186:9:186:14 | call to s24 [element 0] : | semantics.rb:189:10:189:10 | x [element 0] : | +| semantics.rb:185:5:185:5 | a : | semantics.rb:186:13:186:13 | a : | +| semantics.rb:185:5:185:5 | a : | semantics.rb:186:13:186:13 | a : | +| semantics.rb:185:9:185:18 | call to source : | semantics.rb:185:5:185:5 | a : | +| semantics.rb:185:9:185:18 | call to source : | semantics.rb:185:5:185:5 | a : | +| semantics.rb:186:5:186:5 | x [element 0] : | semantics.rb:187:10:187:10 | x [element 0] : | +| semantics.rb:186:5:186:5 | x [element 0] : | semantics.rb:187:10:187:10 | x [element 0] : | +| semantics.rb:186:5:186:5 | x [element 0] : | semantics.rb:189:10:189:10 | x [element 0] : | +| semantics.rb:186:5:186:5 | x [element 0] : | semantics.rb:189:10:189:10 | x [element 0] : | +| semantics.rb:186:9:186:14 | call to s24 [element 0] : | semantics.rb:186:5:186:5 | x [element 0] : | +| semantics.rb:186:9:186:14 | call to s24 [element 0] : | semantics.rb:186:5:186:5 | x [element 0] : | | semantics.rb:186:13:186:13 | a : | semantics.rb:186:9:186:14 | call to s24 [element 0] : | | semantics.rb:186:13:186:13 | a : | semantics.rb:186:9:186:14 | call to s24 [element 0] : | | semantics.rb:187:10:187:10 | x [element 0] : | semantics.rb:187:10:187:13 | ...[...] | | semantics.rb:187:10:187:10 | x [element 0] : | semantics.rb:187:10:187:13 | ...[...] | | semantics.rb:189:10:189:10 | x [element 0] : | semantics.rb:189:10:189:13 | ...[...] | | semantics.rb:189:10:189:10 | x [element 0] : | semantics.rb:189:10:189:13 | ...[...] | -| semantics.rb:193:9:193:18 | call to source : | semantics.rb:196:5:196:5 | [post] h [element 0] : | -| semantics.rb:193:9:193:18 | call to source : | semantics.rb:196:5:196:5 | [post] h [element 0] : | +| semantics.rb:193:5:193:5 | a : | semantics.rb:196:5:196:5 | [post] h [element 0] : | +| semantics.rb:193:5:193:5 | a : | semantics.rb:196:5:196:5 | [post] h [element 0] : | +| semantics.rb:193:9:193:18 | call to source : | semantics.rb:193:5:193:5 | a : | +| semantics.rb:193:9:193:18 | call to source : | semantics.rb:193:5:193:5 | a : | | semantics.rb:196:5:196:5 | [post] h [element 0] : | semantics.rb:197:5:197:5 | h [element 0] : | | semantics.rb:196:5:196:5 | [post] h [element 0] : | semantics.rb:197:5:197:5 | h [element 0] : | | semantics.rb:197:5:197:5 | [post] h [element 0] : | semantics.rb:198:14:198:14 | h [element 0] : | @@ -214,24 +265,34 @@ edges | semantics.rb:197:5:197:5 | h [element 0] : | semantics.rb:197:5:197:5 | [post] h [element 0] : | | semantics.rb:198:14:198:14 | h [element 0] : | semantics.rb:198:10:198:15 | call to s25 | | semantics.rb:198:14:198:14 | h [element 0] : | semantics.rb:198:10:198:15 | call to s25 | -| semantics.rb:202:9:202:18 | call to source : | semantics.rb:203:13:203:13 | a : | -| semantics.rb:202:9:202:18 | call to source : | semantics.rb:203:13:203:13 | a : | -| semantics.rb:203:9:203:14 | call to s26 [element 0] : | semantics.rb:204:10:204:10 | x [element 0] : | -| semantics.rb:203:9:203:14 | call to s26 [element 0] : | semantics.rb:204:10:204:10 | x [element 0] : | -| semantics.rb:203:9:203:14 | call to s26 [element 0] : | semantics.rb:206:10:206:10 | x [element 0] : | -| semantics.rb:203:9:203:14 | call to s26 [element 0] : | semantics.rb:206:10:206:10 | x [element 0] : | +| semantics.rb:202:5:202:5 | a : | semantics.rb:203:13:203:13 | a : | +| semantics.rb:202:5:202:5 | a : | semantics.rb:203:13:203:13 | a : | +| semantics.rb:202:9:202:18 | call to source : | semantics.rb:202:5:202:5 | a : | +| semantics.rb:202:9:202:18 | call to source : | semantics.rb:202:5:202:5 | a : | +| semantics.rb:203:5:203:5 | x [element 0] : | semantics.rb:204:10:204:10 | x [element 0] : | +| semantics.rb:203:5:203:5 | x [element 0] : | semantics.rb:204:10:204:10 | x [element 0] : | +| semantics.rb:203:5:203:5 | x [element 0] : | semantics.rb:206:10:206:10 | x [element 0] : | +| semantics.rb:203:5:203:5 | x [element 0] : | semantics.rb:206:10:206:10 | x [element 0] : | +| semantics.rb:203:9:203:14 | call to s26 [element 0] : | semantics.rb:203:5:203:5 | x [element 0] : | +| semantics.rb:203:9:203:14 | call to s26 [element 0] : | semantics.rb:203:5:203:5 | x [element 0] : | | semantics.rb:203:13:203:13 | a : | semantics.rb:203:9:203:14 | call to s26 [element 0] : | | semantics.rb:203:13:203:13 | a : | semantics.rb:203:9:203:14 | call to s26 [element 0] : | | semantics.rb:204:10:204:10 | x [element 0] : | semantics.rb:204:10:204:13 | ...[...] | | semantics.rb:204:10:204:10 | x [element 0] : | semantics.rb:204:10:204:13 | ...[...] | | semantics.rb:206:10:206:10 | x [element 0] : | semantics.rb:206:10:206:13 | ...[...] | | semantics.rb:206:10:206:10 | x [element 0] : | semantics.rb:206:10:206:13 | ...[...] | -| semantics.rb:211:9:211:18 | call to source : | semantics.rb:217:5:217:5 | [post] h [element 1] : | -| semantics.rb:211:9:211:18 | call to source : | semantics.rb:217:5:217:5 | [post] h [element 1] : | -| semantics.rb:212:9:212:18 | call to source : | semantics.rb:218:5:218:5 | [post] h [element 2] : | -| semantics.rb:212:9:212:18 | call to source : | semantics.rb:218:5:218:5 | [post] h [element 2] : | -| semantics.rb:213:9:213:18 | call to source : | semantics.rb:219:5:219:5 | [post] h [element] : | -| semantics.rb:213:9:213:18 | call to source : | semantics.rb:219:5:219:5 | [post] h [element] : | +| semantics.rb:211:5:211:5 | b : | semantics.rb:217:5:217:5 | [post] h [element 1] : | +| semantics.rb:211:5:211:5 | b : | semantics.rb:217:5:217:5 | [post] h [element 1] : | +| semantics.rb:211:9:211:18 | call to source : | semantics.rb:211:5:211:5 | b : | +| semantics.rb:211:9:211:18 | call to source : | semantics.rb:211:5:211:5 | b : | +| semantics.rb:212:5:212:5 | c : | semantics.rb:218:5:218:5 | [post] h [element 2] : | +| semantics.rb:212:5:212:5 | c : | semantics.rb:218:5:218:5 | [post] h [element 2] : | +| semantics.rb:212:9:212:18 | call to source : | semantics.rb:212:5:212:5 | c : | +| semantics.rb:212:9:212:18 | call to source : | semantics.rb:212:5:212:5 | c : | +| semantics.rb:213:5:213:5 | d : | semantics.rb:219:5:219:5 | [post] h [element] : | +| semantics.rb:213:5:213:5 | d : | semantics.rb:219:5:219:5 | [post] h [element] : | +| semantics.rb:213:9:213:18 | call to source : | semantics.rb:213:5:213:5 | d : | +| semantics.rb:213:9:213:18 | call to source : | semantics.rb:213:5:213:5 | d : | | semantics.rb:217:5:217:5 | [post] h [element 1] : | semantics.rb:218:5:218:5 | h [element 1] : | | semantics.rb:217:5:217:5 | [post] h [element 1] : | semantics.rb:218:5:218:5 | h [element 1] : | | semantics.rb:218:5:218:5 | [post] h [element 1] : | semantics.rb:221:14:221:14 | h [element 1] : | @@ -248,16 +309,20 @@ edges | semantics.rb:221:14:221:14 | h [element 2] : | semantics.rb:221:10:221:15 | call to s27 | | semantics.rb:221:14:221:14 | h [element] : | semantics.rb:221:10:221:15 | call to s27 | | semantics.rb:221:14:221:14 | h [element] : | semantics.rb:221:10:221:15 | call to s27 | -| semantics.rb:225:9:225:18 | call to source : | semantics.rb:226:13:226:13 | a : | -| semantics.rb:225:9:225:18 | call to source : | semantics.rb:226:13:226:13 | a : | -| semantics.rb:226:9:226:14 | call to s28 [element] : | semantics.rb:227:10:227:10 | x [element] : | -| semantics.rb:226:9:226:14 | call to s28 [element] : | semantics.rb:227:10:227:10 | x [element] : | -| semantics.rb:226:9:226:14 | call to s28 [element] : | semantics.rb:228:10:228:10 | x [element] : | -| semantics.rb:226:9:226:14 | call to s28 [element] : | semantics.rb:228:10:228:10 | x [element] : | -| semantics.rb:226:9:226:14 | call to s28 [element] : | semantics.rb:229:10:229:10 | x [element] : | -| semantics.rb:226:9:226:14 | call to s28 [element] : | semantics.rb:229:10:229:10 | x [element] : | -| semantics.rb:226:9:226:14 | call to s28 [element] : | semantics.rb:230:10:230:10 | x [element] : | -| semantics.rb:226:9:226:14 | call to s28 [element] : | semantics.rb:230:10:230:10 | x [element] : | +| semantics.rb:225:5:225:5 | a : | semantics.rb:226:13:226:13 | a : | +| semantics.rb:225:5:225:5 | a : | semantics.rb:226:13:226:13 | a : | +| semantics.rb:225:9:225:18 | call to source : | semantics.rb:225:5:225:5 | a : | +| semantics.rb:225:9:225:18 | call to source : | semantics.rb:225:5:225:5 | a : | +| semantics.rb:226:5:226:5 | x [element] : | semantics.rb:227:10:227:10 | x [element] : | +| semantics.rb:226:5:226:5 | x [element] : | semantics.rb:227:10:227:10 | x [element] : | +| semantics.rb:226:5:226:5 | x [element] : | semantics.rb:228:10:228:10 | x [element] : | +| semantics.rb:226:5:226:5 | x [element] : | semantics.rb:228:10:228:10 | x [element] : | +| semantics.rb:226:5:226:5 | x [element] : | semantics.rb:229:10:229:10 | x [element] : | +| semantics.rb:226:5:226:5 | x [element] : | semantics.rb:229:10:229:10 | x [element] : | +| semantics.rb:226:5:226:5 | x [element] : | semantics.rb:230:10:230:10 | x [element] : | +| semantics.rb:226:5:226:5 | x [element] : | semantics.rb:230:10:230:10 | x [element] : | +| semantics.rb:226:9:226:14 | call to s28 [element] : | semantics.rb:226:5:226:5 | x [element] : | +| semantics.rb:226:9:226:14 | call to s28 [element] : | semantics.rb:226:5:226:5 | x [element] : | | semantics.rb:226:13:226:13 | a : | semantics.rb:226:9:226:14 | call to s28 [element] : | | semantics.rb:226:13:226:13 | a : | semantics.rb:226:9:226:14 | call to s28 [element] : | | semantics.rb:227:10:227:10 | x [element] : | semantics.rb:227:10:227:13 | ...[...] | @@ -268,10 +333,14 @@ edges | semantics.rb:229:10:229:10 | x [element] : | semantics.rb:229:10:229:13 | ...[...] | | semantics.rb:230:10:230:10 | x [element] : | semantics.rb:230:10:230:13 | ...[...] | | semantics.rb:230:10:230:10 | x [element] : | semantics.rb:230:10:230:13 | ...[...] | -| semantics.rb:235:9:235:18 | call to source : | semantics.rb:240:5:240:5 | [post] h [element 1] : | -| semantics.rb:235:9:235:18 | call to source : | semantics.rb:240:5:240:5 | [post] h [element 1] : | -| semantics.rb:236:9:236:18 | call to source : | semantics.rb:241:5:241:5 | [post] h [element 2] : | -| semantics.rb:236:9:236:18 | call to source : | semantics.rb:241:5:241:5 | [post] h [element 2] : | +| semantics.rb:235:5:235:5 | b : | semantics.rb:240:5:240:5 | [post] h [element 1] : | +| semantics.rb:235:5:235:5 | b : | semantics.rb:240:5:240:5 | [post] h [element 1] : | +| semantics.rb:235:9:235:18 | call to source : | semantics.rb:235:5:235:5 | b : | +| semantics.rb:235:9:235:18 | call to source : | semantics.rb:235:5:235:5 | b : | +| semantics.rb:236:5:236:5 | c : | semantics.rb:241:5:241:5 | [post] h [element 2] : | +| semantics.rb:236:5:236:5 | c : | semantics.rb:241:5:241:5 | [post] h [element 2] : | +| semantics.rb:236:9:236:18 | call to source : | semantics.rb:236:5:236:5 | c : | +| semantics.rb:236:9:236:18 | call to source : | semantics.rb:236:5:236:5 | c : | | semantics.rb:240:5:240:5 | [post] h [element 1] : | semantics.rb:241:5:241:5 | h [element 1] : | | semantics.rb:240:5:240:5 | [post] h [element 1] : | semantics.rb:241:5:241:5 | h [element 1] : | | semantics.rb:241:5:241:5 | [post] h [element 1] : | semantics.rb:244:14:244:14 | h [element 1] : | @@ -284,16 +353,20 @@ edges | semantics.rb:244:14:244:14 | h [element 1] : | semantics.rb:244:10:244:15 | call to s29 | | semantics.rb:244:14:244:14 | h [element 2] : | semantics.rb:244:10:244:15 | call to s29 | | semantics.rb:244:14:244:14 | h [element 2] : | semantics.rb:244:10:244:15 | call to s29 | -| semantics.rb:248:9:248:18 | call to source : | semantics.rb:249:13:249:13 | a : | -| semantics.rb:248:9:248:18 | call to source : | semantics.rb:249:13:249:13 | a : | -| semantics.rb:249:9:249:14 | call to s30 [element] : | semantics.rb:250:10:250:10 | x [element] : | -| semantics.rb:249:9:249:14 | call to s30 [element] : | semantics.rb:250:10:250:10 | x [element] : | -| semantics.rb:249:9:249:14 | call to s30 [element] : | semantics.rb:251:10:251:10 | x [element] : | -| semantics.rb:249:9:249:14 | call to s30 [element] : | semantics.rb:251:10:251:10 | x [element] : | -| semantics.rb:249:9:249:14 | call to s30 [element] : | semantics.rb:252:10:252:10 | x [element] : | -| semantics.rb:249:9:249:14 | call to s30 [element] : | semantics.rb:252:10:252:10 | x [element] : | -| semantics.rb:249:9:249:14 | call to s30 [element] : | semantics.rb:253:10:253:10 | x [element] : | -| semantics.rb:249:9:249:14 | call to s30 [element] : | semantics.rb:253:10:253:10 | x [element] : | +| semantics.rb:248:5:248:5 | a : | semantics.rb:249:13:249:13 | a : | +| semantics.rb:248:5:248:5 | a : | semantics.rb:249:13:249:13 | a : | +| semantics.rb:248:9:248:18 | call to source : | semantics.rb:248:5:248:5 | a : | +| semantics.rb:248:9:248:18 | call to source : | semantics.rb:248:5:248:5 | a : | +| semantics.rb:249:5:249:5 | x [element] : | semantics.rb:250:10:250:10 | x [element] : | +| semantics.rb:249:5:249:5 | x [element] : | semantics.rb:250:10:250:10 | x [element] : | +| semantics.rb:249:5:249:5 | x [element] : | semantics.rb:251:10:251:10 | x [element] : | +| semantics.rb:249:5:249:5 | x [element] : | semantics.rb:251:10:251:10 | x [element] : | +| semantics.rb:249:5:249:5 | x [element] : | semantics.rb:252:10:252:10 | x [element] : | +| semantics.rb:249:5:249:5 | x [element] : | semantics.rb:252:10:252:10 | x [element] : | +| semantics.rb:249:5:249:5 | x [element] : | semantics.rb:253:10:253:10 | x [element] : | +| semantics.rb:249:5:249:5 | x [element] : | semantics.rb:253:10:253:10 | x [element] : | +| semantics.rb:249:9:249:14 | call to s30 [element] : | semantics.rb:249:5:249:5 | x [element] : | +| semantics.rb:249:9:249:14 | call to s30 [element] : | semantics.rb:249:5:249:5 | x [element] : | | semantics.rb:249:13:249:13 | a : | semantics.rb:249:9:249:14 | call to s30 [element] : | | semantics.rb:249:13:249:13 | a : | semantics.rb:249:9:249:14 | call to s30 [element] : | | semantics.rb:250:10:250:10 | x [element] : | semantics.rb:250:10:250:13 | ...[...] | @@ -392,30 +465,36 @@ edges | semantics.rb:285:14:285:14 | h [element true] : | semantics.rb:285:10:285:15 | call to s33 | | semantics.rb:285:14:285:14 | h [element] : | semantics.rb:285:10:285:15 | call to s33 | | semantics.rb:285:14:285:14 | h [element] : | semantics.rb:285:10:285:15 | call to s33 | -| semantics.rb:289:9:289:24 | call to s35 [element :foo] : | semantics.rb:290:10:290:10 | x [element :foo] : | -| semantics.rb:289:9:289:24 | call to s35 [element :foo] : | semantics.rb:290:10:290:10 | x [element :foo] : | -| semantics.rb:289:9:289:24 | call to s35 [element :foo] : | semantics.rb:292:10:292:10 | x [element :foo] : | -| semantics.rb:289:9:289:24 | call to s35 [element :foo] : | semantics.rb:292:10:292:10 | x [element :foo] : | +| semantics.rb:289:5:289:5 | x [element :foo] : | semantics.rb:290:10:290:10 | x [element :foo] : | +| semantics.rb:289:5:289:5 | x [element :foo] : | semantics.rb:290:10:290:10 | x [element :foo] : | +| semantics.rb:289:5:289:5 | x [element :foo] : | semantics.rb:292:10:292:10 | x [element :foo] : | +| semantics.rb:289:5:289:5 | x [element :foo] : | semantics.rb:292:10:292:10 | x [element :foo] : | +| semantics.rb:289:9:289:24 | call to s35 [element :foo] : | semantics.rb:289:5:289:5 | x [element :foo] : | +| semantics.rb:289:9:289:24 | call to s35 [element :foo] : | semantics.rb:289:5:289:5 | x [element :foo] : | | semantics.rb:289:13:289:23 | call to source : | semantics.rb:289:9:289:24 | call to s35 [element :foo] : | | semantics.rb:289:13:289:23 | call to source : | semantics.rb:289:9:289:24 | call to s35 [element :foo] : | | semantics.rb:290:10:290:10 | x [element :foo] : | semantics.rb:290:10:290:16 | ...[...] | | semantics.rb:290:10:290:10 | x [element :foo] : | semantics.rb:290:10:290:16 | ...[...] | | semantics.rb:292:10:292:10 | x [element :foo] : | semantics.rb:292:10:292:13 | ...[...] | | semantics.rb:292:10:292:10 | x [element :foo] : | semantics.rb:292:10:292:13 | ...[...] | -| semantics.rb:296:9:296:24 | call to s36 [element foo] : | semantics.rb:298:10:298:10 | x [element foo] : | -| semantics.rb:296:9:296:24 | call to s36 [element foo] : | semantics.rb:298:10:298:10 | x [element foo] : | -| semantics.rb:296:9:296:24 | call to s36 [element foo] : | semantics.rb:300:10:300:10 | x [element foo] : | -| semantics.rb:296:9:296:24 | call to s36 [element foo] : | semantics.rb:300:10:300:10 | x [element foo] : | +| semantics.rb:296:5:296:5 | x [element foo] : | semantics.rb:298:10:298:10 | x [element foo] : | +| semantics.rb:296:5:296:5 | x [element foo] : | semantics.rb:298:10:298:10 | x [element foo] : | +| semantics.rb:296:5:296:5 | x [element foo] : | semantics.rb:300:10:300:10 | x [element foo] : | +| semantics.rb:296:5:296:5 | x [element foo] : | semantics.rb:300:10:300:10 | x [element foo] : | +| semantics.rb:296:9:296:24 | call to s36 [element foo] : | semantics.rb:296:5:296:5 | x [element foo] : | +| semantics.rb:296:9:296:24 | call to s36 [element foo] : | semantics.rb:296:5:296:5 | x [element foo] : | | semantics.rb:296:13:296:23 | call to source : | semantics.rb:296:9:296:24 | call to s36 [element foo] : | | semantics.rb:296:13:296:23 | call to source : | semantics.rb:296:9:296:24 | call to s36 [element foo] : | | semantics.rb:298:10:298:10 | x [element foo] : | semantics.rb:298:10:298:17 | ...[...] | | semantics.rb:298:10:298:10 | x [element foo] : | semantics.rb:298:10:298:17 | ...[...] | | semantics.rb:300:10:300:10 | x [element foo] : | semantics.rb:300:10:300:13 | ...[...] | | semantics.rb:300:10:300:10 | x [element foo] : | semantics.rb:300:10:300:13 | ...[...] | -| semantics.rb:304:9:304:24 | call to s37 [element true] : | semantics.rb:306:10:306:10 | x [element true] : | -| semantics.rb:304:9:304:24 | call to s37 [element true] : | semantics.rb:306:10:306:10 | x [element true] : | -| semantics.rb:304:9:304:24 | call to s37 [element true] : | semantics.rb:308:10:308:10 | x [element true] : | -| semantics.rb:304:9:304:24 | call to s37 [element true] : | semantics.rb:308:10:308:10 | x [element true] : | +| semantics.rb:304:5:304:5 | x [element true] : | semantics.rb:306:10:306:10 | x [element true] : | +| semantics.rb:304:5:304:5 | x [element true] : | semantics.rb:306:10:306:10 | x [element true] : | +| semantics.rb:304:5:304:5 | x [element true] : | semantics.rb:308:10:308:10 | x [element true] : | +| semantics.rb:304:5:304:5 | x [element true] : | semantics.rb:308:10:308:10 | x [element true] : | +| semantics.rb:304:9:304:24 | call to s37 [element true] : | semantics.rb:304:5:304:5 | x [element true] : | +| semantics.rb:304:9:304:24 | call to s37 [element true] : | semantics.rb:304:5:304:5 | x [element true] : | | semantics.rb:304:13:304:23 | call to source : | semantics.rb:304:9:304:24 | call to s37 [element true] : | | semantics.rb:304:13:304:23 | call to source : | semantics.rb:304:9:304:24 | call to s37 [element true] : | | semantics.rb:306:10:306:10 | x [element true] : | semantics.rb:306:10:306:16 | ...[...] | @@ -428,10 +507,12 @@ edges | semantics.rb:312:16:312:26 | call to source : | semantics.rb:312:5:312:5 | [post] h [element foo] : | | semantics.rb:315:14:315:14 | h [element foo] : | semantics.rb:315:10:315:15 | call to s38 | | semantics.rb:315:14:315:14 | h [element foo] : | semantics.rb:315:10:315:15 | call to s38 | -| semantics.rb:319:9:319:24 | call to s39 [element :foo] : | semantics.rb:321:10:321:10 | x [element :foo] : | -| semantics.rb:319:9:319:24 | call to s39 [element :foo] : | semantics.rb:321:10:321:10 | x [element :foo] : | -| semantics.rb:319:9:319:24 | call to s39 [element :foo] : | semantics.rb:322:10:322:10 | x [element :foo] : | -| semantics.rb:319:9:319:24 | call to s39 [element :foo] : | semantics.rb:322:10:322:10 | x [element :foo] : | +| semantics.rb:319:5:319:5 | x [element :foo] : | semantics.rb:321:10:321:10 | x [element :foo] : | +| semantics.rb:319:5:319:5 | x [element :foo] : | semantics.rb:321:10:321:10 | x [element :foo] : | +| semantics.rb:319:5:319:5 | x [element :foo] : | semantics.rb:322:10:322:10 | x [element :foo] : | +| semantics.rb:319:5:319:5 | x [element :foo] : | semantics.rb:322:10:322:10 | x [element :foo] : | +| semantics.rb:319:9:319:24 | call to s39 [element :foo] : | semantics.rb:319:5:319:5 | x [element :foo] : | +| semantics.rb:319:9:319:24 | call to s39 [element :foo] : | semantics.rb:319:5:319:5 | x [element :foo] : | | semantics.rb:319:13:319:23 | call to source : | semantics.rb:319:9:319:24 | call to s39 [element :foo] : | | semantics.rb:319:13:319:23 | call to source : | semantics.rb:319:9:319:24 | call to s39 [element :foo] : | | semantics.rb:321:10:321:10 | x [element :foo] : | semantics.rb:321:10:321:16 | ...[...] | @@ -444,8 +525,10 @@ edges | semantics.rb:327:13:327:23 | call to source : | semantics.rb:327:5:327:5 | [post] x [@foo] : | | semantics.rb:329:14:329:14 | x [@foo] : | semantics.rb:329:10:329:15 | call to s40 | | semantics.rb:329:14:329:14 | x [@foo] : | semantics.rb:329:10:329:15 | call to s40 | -| semantics.rb:333:9:333:24 | call to s41 [@foo] : | semantics.rb:334:10:334:10 | x [@foo] : | -| semantics.rb:333:9:333:24 | call to s41 [@foo] : | semantics.rb:334:10:334:10 | x [@foo] : | +| semantics.rb:333:5:333:5 | x [@foo] : | semantics.rb:334:10:334:10 | x [@foo] : | +| semantics.rb:333:5:333:5 | x [@foo] : | semantics.rb:334:10:334:10 | x [@foo] : | +| semantics.rb:333:9:333:24 | call to s41 [@foo] : | semantics.rb:333:5:333:5 | x [@foo] : | +| semantics.rb:333:9:333:24 | call to s41 [@foo] : | semantics.rb:333:5:333:5 | x [@foo] : | | semantics.rb:333:13:333:23 | call to source : | semantics.rb:333:9:333:24 | call to s41 [@foo] : | | semantics.rb:333:13:333:23 | call to source : | semantics.rb:333:9:333:24 | call to s41 [@foo] : | | semantics.rb:334:10:334:10 | x [@foo] : | semantics.rb:334:10:334:14 | call to foo | @@ -458,16 +541,20 @@ edges | semantics.rb:340:5:340:5 | [post] h [element] : | semantics.rb:342:13:342:13 | h [element] : | | semantics.rb:340:12:340:22 | call to source : | semantics.rb:340:5:340:5 | [post] h [element] : | | semantics.rb:340:12:340:22 | call to source : | semantics.rb:340:5:340:5 | [post] h [element] : | -| semantics.rb:342:9:342:14 | call to s42 [element 0] : | semantics.rb:344:10:344:10 | x [element 0] : | -| semantics.rb:342:9:342:14 | call to s42 [element 0] : | semantics.rb:344:10:344:10 | x [element 0] : | -| semantics.rb:342:9:342:14 | call to s42 [element 0] : | semantics.rb:346:10:346:10 | x [element 0] : | -| semantics.rb:342:9:342:14 | call to s42 [element 0] : | semantics.rb:346:10:346:10 | x [element 0] : | -| semantics.rb:342:9:342:14 | call to s42 [element] : | semantics.rb:344:10:344:10 | x [element] : | -| semantics.rb:342:9:342:14 | call to s42 [element] : | semantics.rb:344:10:344:10 | x [element] : | -| semantics.rb:342:9:342:14 | call to s42 [element] : | semantics.rb:345:10:345:10 | x [element] : | -| semantics.rb:342:9:342:14 | call to s42 [element] : | semantics.rb:345:10:345:10 | x [element] : | -| semantics.rb:342:9:342:14 | call to s42 [element] : | semantics.rb:346:10:346:10 | x [element] : | -| semantics.rb:342:9:342:14 | call to s42 [element] : | semantics.rb:346:10:346:10 | x [element] : | +| semantics.rb:342:5:342:5 | x [element 0] : | semantics.rb:344:10:344:10 | x [element 0] : | +| semantics.rb:342:5:342:5 | x [element 0] : | semantics.rb:344:10:344:10 | x [element 0] : | +| semantics.rb:342:5:342:5 | x [element 0] : | semantics.rb:346:10:346:10 | x [element 0] : | +| semantics.rb:342:5:342:5 | x [element 0] : | semantics.rb:346:10:346:10 | x [element 0] : | +| semantics.rb:342:5:342:5 | x [element] : | semantics.rb:344:10:344:10 | x [element] : | +| semantics.rb:342:5:342:5 | x [element] : | semantics.rb:344:10:344:10 | x [element] : | +| semantics.rb:342:5:342:5 | x [element] : | semantics.rb:345:10:345:10 | x [element] : | +| semantics.rb:342:5:342:5 | x [element] : | semantics.rb:345:10:345:10 | x [element] : | +| semantics.rb:342:5:342:5 | x [element] : | semantics.rb:346:10:346:10 | x [element] : | +| semantics.rb:342:5:342:5 | x [element] : | semantics.rb:346:10:346:10 | x [element] : | +| semantics.rb:342:9:342:14 | call to s42 [element 0] : | semantics.rb:342:5:342:5 | x [element 0] : | +| semantics.rb:342:9:342:14 | call to s42 [element 0] : | semantics.rb:342:5:342:5 | x [element 0] : | +| semantics.rb:342:9:342:14 | call to s42 [element] : | semantics.rb:342:5:342:5 | x [element] : | +| semantics.rb:342:9:342:14 | call to s42 [element] : | semantics.rb:342:5:342:5 | x [element] : | | semantics.rb:342:13:342:13 | h [element 0] : | semantics.rb:342:9:342:14 | call to s42 [element 0] : | | semantics.rb:342:13:342:13 | h [element 0] : | semantics.rb:342:9:342:14 | call to s42 [element 0] : | | semantics.rb:342:13:342:13 | h [element] : | semantics.rb:342:9:342:14 | call to s42 [element] : | @@ -486,10 +573,12 @@ edges | semantics.rb:350:5:350:5 | [post] h [element 0] : | semantics.rb:353:13:353:13 | h [element 0] : | | semantics.rb:350:12:350:22 | call to source : | semantics.rb:350:5:350:5 | [post] h [element 0] : | | semantics.rb:350:12:350:22 | call to source : | semantics.rb:350:5:350:5 | [post] h [element 0] : | -| semantics.rb:353:9:353:14 | call to s43 [element 0] : | semantics.rb:355:10:355:10 | x [element 0] : | -| semantics.rb:353:9:353:14 | call to s43 [element 0] : | semantics.rb:355:10:355:10 | x [element 0] : | -| semantics.rb:353:9:353:14 | call to s43 [element 0] : | semantics.rb:357:10:357:10 | x [element 0] : | -| semantics.rb:353:9:353:14 | call to s43 [element 0] : | semantics.rb:357:10:357:10 | x [element 0] : | +| semantics.rb:353:5:353:5 | x [element 0] : | semantics.rb:355:10:355:10 | x [element 0] : | +| semantics.rb:353:5:353:5 | x [element 0] : | semantics.rb:355:10:355:10 | x [element 0] : | +| semantics.rb:353:5:353:5 | x [element 0] : | semantics.rb:357:10:357:10 | x [element 0] : | +| semantics.rb:353:5:353:5 | x [element 0] : | semantics.rb:357:10:357:10 | x [element 0] : | +| semantics.rb:353:9:353:14 | call to s43 [element 0] : | semantics.rb:353:5:353:5 | x [element 0] : | +| semantics.rb:353:9:353:14 | call to s43 [element 0] : | semantics.rb:353:5:353:5 | x [element 0] : | | semantics.rb:353:13:353:13 | h [element 0] : | semantics.rb:353:9:353:14 | call to s43 [element 0] : | | semantics.rb:353:13:353:13 | h [element 0] : | semantics.rb:353:9:353:14 | call to s43 [element 0] : | | semantics.rb:355:10:355:10 | x [element 0] : | semantics.rb:355:10:355:13 | ...[...] | @@ -616,10 +705,12 @@ edges | semantics.rb:395:10:395:10 | h [element 1] : | semantics.rb:395:10:395:13 | ...[...] | | semantics.rb:395:10:395:10 | h [element] : | semantics.rb:395:10:395:13 | ...[...] | | semantics.rb:395:10:395:10 | h [element] : | semantics.rb:395:10:395:13 | ...[...] | -| semantics.rb:397:9:397:14 | call to s46 [element 1] : | semantics.rb:400:10:400:10 | x [element 1] : | -| semantics.rb:397:9:397:14 | call to s46 [element 1] : | semantics.rb:400:10:400:10 | x [element 1] : | -| semantics.rb:397:9:397:14 | call to s46 [element 1] : | semantics.rb:401:10:401:10 | x [element 1] : | -| semantics.rb:397:9:397:14 | call to s46 [element 1] : | semantics.rb:401:10:401:10 | x [element 1] : | +| semantics.rb:397:5:397:5 | x [element 1] : | semantics.rb:400:10:400:10 | x [element 1] : | +| semantics.rb:397:5:397:5 | x [element 1] : | semantics.rb:400:10:400:10 | x [element 1] : | +| semantics.rb:397:5:397:5 | x [element 1] : | semantics.rb:401:10:401:10 | x [element 1] : | +| semantics.rb:397:5:397:5 | x [element 1] : | semantics.rb:401:10:401:10 | x [element 1] : | +| semantics.rb:397:9:397:14 | call to s46 [element 1] : | semantics.rb:397:5:397:5 | x [element 1] : | +| semantics.rb:397:9:397:14 | call to s46 [element 1] : | semantics.rb:397:5:397:5 | x [element 1] : | | semantics.rb:397:13:397:13 | h [element 1] : | semantics.rb:397:9:397:14 | call to s46 [element 1] : | | semantics.rb:397:13:397:13 | h [element 1] : | semantics.rb:397:9:397:14 | call to s46 [element 1] : | | semantics.rb:400:10:400:10 | x [element 1] : | semantics.rb:400:10:400:13 | ...[...] | @@ -654,8 +745,10 @@ edges | semantics.rb:410:10:410:10 | h [element :bar] : | semantics.rb:410:10:410:16 | ...[...] | | semantics.rb:410:10:410:10 | h [element] : | semantics.rb:410:10:410:16 | ...[...] | | semantics.rb:410:10:410:10 | h [element] : | semantics.rb:410:10:410:16 | ...[...] | -| semantics.rb:412:9:412:14 | call to s47 [element :bar] : | semantics.rb:415:10:415:10 | x [element :bar] : | -| semantics.rb:412:9:412:14 | call to s47 [element :bar] : | semantics.rb:415:10:415:10 | x [element :bar] : | +| semantics.rb:412:5:412:5 | x [element :bar] : | semantics.rb:415:10:415:10 | x [element :bar] : | +| semantics.rb:412:5:412:5 | x [element :bar] : | semantics.rb:415:10:415:10 | x [element :bar] : | +| semantics.rb:412:9:412:14 | call to s47 [element :bar] : | semantics.rb:412:5:412:5 | x [element :bar] : | +| semantics.rb:412:9:412:14 | call to s47 [element :bar] : | semantics.rb:412:5:412:5 | x [element :bar] : | | semantics.rb:412:13:412:13 | h [element :bar] : | semantics.rb:412:9:412:14 | call to s47 [element :bar] : | | semantics.rb:412:13:412:13 | h [element :bar] : | semantics.rb:412:9:412:14 | call to s47 [element :bar] : | | semantics.rb:415:10:415:10 | x [element :bar] : | semantics.rb:415:10:415:16 | ...[...] | @@ -688,8 +781,10 @@ edges | semantics.rb:424:10:424:10 | h [element :bar] : | semantics.rb:424:10:424:16 | ...[...] | | semantics.rb:424:10:424:10 | h [element] : | semantics.rb:424:10:424:16 | ...[...] | | semantics.rb:424:10:424:10 | h [element] : | semantics.rb:424:10:424:16 | ...[...] | -| semantics.rb:426:9:426:14 | call to s48 [element :bar] : | semantics.rb:429:10:429:10 | x [element :bar] : | -| semantics.rb:426:9:426:14 | call to s48 [element :bar] : | semantics.rb:429:10:429:10 | x [element :bar] : | +| semantics.rb:426:5:426:5 | x [element :bar] : | semantics.rb:429:10:429:10 | x [element :bar] : | +| semantics.rb:426:5:426:5 | x [element :bar] : | semantics.rb:429:10:429:10 | x [element :bar] : | +| semantics.rb:426:9:426:14 | call to s48 [element :bar] : | semantics.rb:426:5:426:5 | x [element :bar] : | +| semantics.rb:426:9:426:14 | call to s48 [element :bar] : | semantics.rb:426:5:426:5 | x [element :bar] : | | semantics.rb:426:13:426:13 | h [element :bar] : | semantics.rb:426:9:426:14 | call to s48 [element :bar] : | | semantics.rb:426:13:426:13 | h [element :bar] : | semantics.rb:426:9:426:14 | call to s48 [element :bar] : | | semantics.rb:429:10:429:10 | x [element :bar] : | semantics.rb:429:10:429:16 | ...[...] | @@ -724,12 +819,16 @@ edges | semantics.rb:438:10:438:10 | h [element :bar] : | semantics.rb:438:10:438:16 | ...[...] | | semantics.rb:438:10:438:10 | h [element] : | semantics.rb:438:10:438:16 | ...[...] | | semantics.rb:438:10:438:10 | h [element] : | semantics.rb:438:10:438:16 | ...[...] | -| semantics.rb:440:9:440:14 | call to s49 [element :bar] : | semantics.rb:443:10:443:10 | x [element :bar] : | -| semantics.rb:440:9:440:14 | call to s49 [element :bar] : | semantics.rb:443:10:443:10 | x [element :bar] : | -| semantics.rb:440:9:440:14 | call to s49 [element] : | semantics.rb:442:10:442:10 | x [element] : | -| semantics.rb:440:9:440:14 | call to s49 [element] : | semantics.rb:442:10:442:10 | x [element] : | -| semantics.rb:440:9:440:14 | call to s49 [element] : | semantics.rb:443:10:443:10 | x [element] : | -| semantics.rb:440:9:440:14 | call to s49 [element] : | semantics.rb:443:10:443:10 | x [element] : | +| semantics.rb:440:5:440:5 | x [element :bar] : | semantics.rb:443:10:443:10 | x [element :bar] : | +| semantics.rb:440:5:440:5 | x [element :bar] : | semantics.rb:443:10:443:10 | x [element :bar] : | +| semantics.rb:440:5:440:5 | x [element] : | semantics.rb:442:10:442:10 | x [element] : | +| semantics.rb:440:5:440:5 | x [element] : | semantics.rb:442:10:442:10 | x [element] : | +| semantics.rb:440:5:440:5 | x [element] : | semantics.rb:443:10:443:10 | x [element] : | +| semantics.rb:440:5:440:5 | x [element] : | semantics.rb:443:10:443:10 | x [element] : | +| semantics.rb:440:9:440:14 | call to s49 [element :bar] : | semantics.rb:440:5:440:5 | x [element :bar] : | +| semantics.rb:440:9:440:14 | call to s49 [element :bar] : | semantics.rb:440:5:440:5 | x [element :bar] : | +| semantics.rb:440:9:440:14 | call to s49 [element] : | semantics.rb:440:5:440:5 | x [element] : | +| semantics.rb:440:9:440:14 | call to s49 [element] : | semantics.rb:440:5:440:5 | x [element] : | | semantics.rb:440:13:440:13 | h [element :bar] : | semantics.rb:440:9:440:14 | call to s49 [element :bar] : | | semantics.rb:440:13:440:13 | h [element :bar] : | semantics.rb:440:9:440:14 | call to s49 [element :bar] : | | semantics.rb:440:13:440:13 | h [element] : | semantics.rb:440:9:440:14 | call to s49 [element] : | @@ -882,10 +981,12 @@ edges | semantics.rb:494:10:494:10 | h [element :bar] : | semantics.rb:494:10:494:16 | ...[...] | | semantics.rb:494:10:494:10 | h [element] : | semantics.rb:494:10:494:16 | ...[...] | | semantics.rb:494:10:494:10 | h [element] : | semantics.rb:494:10:494:16 | ...[...] | +| semantics.rb:496:5:496:5 | x [element :bar] : | semantics.rb:499:10:499:10 | x [element :bar] : | +| semantics.rb:496:5:496:5 | x [element :bar] : | semantics.rb:499:10:499:10 | x [element :bar] : | | semantics.rb:496:9:496:9 | h [element :bar] : | semantics.rb:496:9:496:15 | call to s53 [element :bar] : | | semantics.rb:496:9:496:9 | h [element :bar] : | semantics.rb:496:9:496:15 | call to s53 [element :bar] : | -| semantics.rb:496:9:496:15 | call to s53 [element :bar] : | semantics.rb:499:10:499:10 | x [element :bar] : | -| semantics.rb:496:9:496:15 | call to s53 [element :bar] : | semantics.rb:499:10:499:10 | x [element :bar] : | +| semantics.rb:496:9:496:15 | call to s53 [element :bar] : | semantics.rb:496:5:496:5 | x [element :bar] : | +| semantics.rb:496:9:496:15 | call to s53 [element :bar] : | semantics.rb:496:5:496:5 | x [element :bar] : | | semantics.rb:499:10:499:10 | x [element :bar] : | semantics.rb:499:10:499:16 | ...[...] | | semantics.rb:499:10:499:10 | x [element :bar] : | semantics.rb:499:10:499:16 | ...[...] | | semantics.rb:501:10:501:20 | call to source : | semantics.rb:501:10:501:26 | call to s53 | @@ -918,21 +1019,29 @@ edges | semantics.rb:510:10:510:10 | h [element :bar] : | semantics.rb:510:10:510:16 | ...[...] | | semantics.rb:510:10:510:10 | h [element] : | semantics.rb:510:10:510:16 | ...[...] | | semantics.rb:510:10:510:10 | h [element] : | semantics.rb:510:10:510:16 | ...[...] | +| semantics.rb:512:5:512:5 | x [element :bar] : | semantics.rb:515:10:515:10 | x [element :bar] : | +| semantics.rb:512:5:512:5 | x [element :bar] : | semantics.rb:515:10:515:10 | x [element :bar] : | | semantics.rb:512:9:512:9 | h [element :bar] : | semantics.rb:512:9:512:15 | call to s54 [element :bar] : | | semantics.rb:512:9:512:9 | h [element :bar] : | semantics.rb:512:9:512:15 | call to s54 [element :bar] : | -| semantics.rb:512:9:512:15 | call to s54 [element :bar] : | semantics.rb:515:10:515:10 | x [element :bar] : | -| semantics.rb:512:9:512:15 | call to s54 [element :bar] : | semantics.rb:515:10:515:10 | x [element :bar] : | +| semantics.rb:512:9:512:15 | call to s54 [element :bar] : | semantics.rb:512:5:512:5 | x [element :bar] : | +| semantics.rb:512:9:512:15 | call to s54 [element :bar] : | semantics.rb:512:5:512:5 | x [element :bar] : | | semantics.rb:515:10:515:10 | x [element :bar] : | semantics.rb:515:10:515:16 | ...[...] | | semantics.rb:515:10:515:10 | x [element :bar] : | semantics.rb:515:10:515:16 | ...[...] | nodes +| semantics.rb:2:5:2:5 | a : | semmle.label | a : | +| semantics.rb:2:5:2:5 | a : | semmle.label | a : | | semantics.rb:2:9:2:18 | call to source : | semmle.label | call to source : | | semantics.rb:2:9:2:18 | call to source : | semmle.label | call to source : | +| semantics.rb:3:5:3:5 | x : | semmle.label | x : | +| semantics.rb:3:5:3:5 | x : | semmle.label | x : | | semantics.rb:3:9:3:9 | a : | semmle.label | a : | | semantics.rb:3:9:3:9 | a : | semmle.label | a : | | semantics.rb:3:9:3:14 | call to s1 : | semmle.label | call to s1 : | | semantics.rb:3:9:3:14 | call to s1 : | semmle.label | call to s1 : | | semantics.rb:4:10:4:10 | x | semmle.label | x | | semantics.rb:4:10:4:10 | x | semmle.label | x | +| semantics.rb:8:5:8:5 | a : | semmle.label | a : | +| semantics.rb:8:5:8:5 | a : | semmle.label | a : | | semantics.rb:8:9:8:18 | call to source : | semmle.label | call to source : | | semantics.rb:8:9:8:18 | call to source : | semmle.label | call to source : | | semantics.rb:9:5:9:5 | [post] x : | semmle.label | [post] x : | @@ -941,6 +1050,8 @@ nodes | semantics.rb:9:10:9:10 | a : | semmle.label | a : | | semantics.rb:10:10:10:10 | x | semmle.label | x | | semantics.rb:10:10:10:10 | x | semmle.label | x | +| semantics.rb:14:5:14:5 | a : | semmle.label | a : | +| semantics.rb:14:5:14:5 | a : | semmle.label | a : | | semantics.rb:14:9:14:18 | call to source : | semmle.label | call to source : | | semantics.rb:14:9:14:18 | call to source : | semmle.label | call to source : | | semantics.rb:15:8:15:8 | a : | semmle.label | a : | @@ -957,6 +1068,8 @@ nodes | semantics.rb:23:10:23:33 | call to s4 | semmle.label | call to s4 | | semantics.rb:23:23:23:32 | call to source : | semmle.label | call to source : | | semantics.rb:23:23:23:32 | call to source : | semmle.label | call to source : | +| semantics.rb:28:5:28:5 | a : | semmle.label | a : | +| semantics.rb:28:5:28:5 | a : | semmle.label | a : | | semantics.rb:28:9:28:18 | call to source : | semmle.label | call to source : | | semantics.rb:28:9:28:18 | call to source : | semmle.label | call to source : | | semantics.rb:29:8:29:8 | a : | semmle.label | a : | @@ -969,6 +1082,8 @@ nodes | semantics.rb:31:10:31:10 | y | semmle.label | y | | semantics.rb:32:10:32:10 | z | semmle.label | z | | semantics.rb:32:10:32:10 | z | semmle.label | z | +| semantics.rb:40:5:40:5 | a : | semmle.label | a : | +| semantics.rb:40:5:40:5 | a : | semmle.label | a : | | semantics.rb:40:9:40:18 | call to source : | semmle.label | call to source : | | semantics.rb:40:9:40:18 | call to source : | semmle.label | call to source : | | semantics.rb:41:8:41:8 | a : | semmle.label | a : | @@ -997,6 +1112,8 @@ nodes | semantics.rb:54:24:54:24 | x : | semmle.label | x : | | semantics.rb:55:14:55:14 | x | semmle.label | x | | semantics.rb:55:14:55:14 | x | semmle.label | x | +| semantics.rb:60:5:60:5 | a : | semmle.label | a : | +| semantics.rb:60:5:60:5 | a : | semmle.label | a : | | semantics.rb:60:9:60:18 | call to source : | semmle.label | call to source : | | semantics.rb:60:9:60:18 | call to source : | semmle.label | call to source : | | semantics.rb:61:10:61:15 | call to s10 | semmle.label | call to s10 | @@ -1019,6 +1136,8 @@ nodes | semantics.rb:66:10:66:16 | call to s10 | semmle.label | call to s10 | | semantics.rb:66:14:66:15 | &... : | semmle.label | &... : | | semantics.rb:66:14:66:15 | &... : | semmle.label | &... : | +| semantics.rb:80:5:80:5 | a : | semmle.label | a : | +| semantics.rb:80:5:80:5 | a : | semmle.label | a : | | semantics.rb:80:9:80:18 | call to source : | semmle.label | call to source : | | semantics.rb:80:9:80:18 | call to source : | semmle.label | call to source : | | semantics.rb:81:5:81:5 | a : | semmle.label | a : | @@ -1035,6 +1154,8 @@ nodes | semantics.rb:83:10:83:10 | y | semmle.label | y | | semantics.rb:84:10:84:10 | z | semmle.label | z | | semantics.rb:84:10:84:10 | z | semmle.label | z | +| semantics.rb:89:5:89:5 | a : | semmle.label | a : | +| semantics.rb:89:5:89:5 | a : | semmle.label | a : | | semantics.rb:89:9:89:18 | call to source : | semmle.label | call to source : | | semantics.rb:89:9:89:18 | call to source : | semmle.label | call to source : | | semantics.rb:91:10:91:20 | call to s13 | semmle.label | call to s13 | @@ -1045,6 +1166,8 @@ nodes | semantics.rb:92:10:92:28 | call to s13 | semmle.label | call to s13 | | semantics.rb:92:27:92:27 | a : | semmle.label | a : | | semantics.rb:92:27:92:27 | a : | semmle.label | a : | +| semantics.rb:97:5:97:5 | a : | semmle.label | a : | +| semantics.rb:97:5:97:5 | a : | semmle.label | a : | | semantics.rb:97:9:97:18 | call to source : | semmle.label | call to source : | | semantics.rb:97:9:97:18 | call to source : | semmle.label | call to source : | | semantics.rb:98:5:98:5 | a : | semmle.label | a : | @@ -1063,15 +1186,22 @@ nodes | semantics.rb:102:10:102:10 | y | semmle.label | y | | semantics.rb:103:10:103:10 | z | semmle.label | z | | semantics.rb:103:10:103:10 | z | semmle.label | z | +| semantics.rb:107:5:107:5 | a : | semmle.label | a : | | semantics.rb:107:9:107:18 | call to source : | semmle.label | call to source : | | semantics.rb:109:10:109:17 | call to s15 | semmle.label | call to s15 | | semantics.rb:109:14:109:16 | ** ... : | semmle.label | ** ... : | | semantics.rb:110:10:110:31 | call to s15 | semmle.label | call to s15 | | semantics.rb:110:28:110:30 | ** ... : | semmle.label | ** ... : | +| semantics.rb:114:5:114:5 | a : | semmle.label | a : | +| semantics.rb:114:5:114:5 | a : | semmle.label | a : | | semantics.rb:114:9:114:18 | call to source : | semmle.label | call to source : | | semantics.rb:114:9:114:18 | call to source : | semmle.label | call to source : | +| semantics.rb:115:5:115:5 | b : | semmle.label | b : | +| semantics.rb:115:5:115:5 | b : | semmle.label | b : | | semantics.rb:115:9:115:18 | call to source : | semmle.label | call to source : | | semantics.rb:115:9:115:18 | call to source : | semmle.label | call to source : | +| semantics.rb:116:5:116:5 | h [element :a] : | semmle.label | h [element :a] : | +| semantics.rb:116:5:116:5 | h [element :a] : | semmle.label | h [element :a] : | | semantics.rb:116:14:116:14 | a : | semmle.label | a : | | semantics.rb:116:14:116:14 | a : | semmle.label | a : | | semantics.rb:117:10:117:17 | call to s16 | semmle.label | call to s16 | @@ -1092,6 +1222,8 @@ nodes | semantics.rb:121:20:121:22 | ** ... [element :a] : | semmle.label | ** ... [element :a] : | | semantics.rb:121:22:121:22 | h [element :a] : | semmle.label | h [element :a] : | | semantics.rb:121:22:121:22 | h [element :a] : | semmle.label | h [element :a] : | +| semantics.rb:125:5:125:5 | a : | semmle.label | a : | +| semantics.rb:125:5:125:5 | a : | semmle.label | a : | | semantics.rb:125:9:125:18 | call to source : | semmle.label | call to source : | | semantics.rb:125:9:125:18 | call to source : | semmle.label | call to source : | | semantics.rb:126:9:126:9 | a : | semmle.label | a : | @@ -1100,6 +1232,8 @@ nodes | semantics.rb:126:12:126:14 | [post] ** ... : | semmle.label | [post] ** ... : | | semantics.rb:127:10:127:10 | h | semmle.label | h | | semantics.rb:127:10:127:10 | h | semmle.label | h | +| semantics.rb:141:5:141:5 | b : | semmle.label | b : | +| semantics.rb:141:5:141:5 | b : | semmle.label | b : | | semantics.rb:141:9:141:18 | call to source : | semmle.label | call to source : | | semantics.rb:141:9:141:18 | call to source : | semmle.label | call to source : | | semantics.rb:145:5:145:5 | [post] h [element] : | semmle.label | [post] h [element] : | @@ -1108,8 +1242,12 @@ nodes | semantics.rb:147:10:147:15 | call to s19 | semmle.label | call to s19 | | semantics.rb:147:14:147:14 | h [element] : | semmle.label | h [element] : | | semantics.rb:147:14:147:14 | h [element] : | semmle.label | h [element] : | +| semantics.rb:151:5:151:5 | a : | semmle.label | a : | +| semantics.rb:151:5:151:5 | a : | semmle.label | a : | | semantics.rb:151:9:151:18 | call to source : | semmle.label | call to source : | | semantics.rb:151:9:151:18 | call to source : | semmle.label | call to source : | +| semantics.rb:152:5:152:5 | x [element] : | semmle.label | x [element] : | +| semantics.rb:152:5:152:5 | x [element] : | semmle.label | x [element] : | | semantics.rb:152:9:152:14 | call to s20 [element] : | semmle.label | call to s20 [element] : | | semantics.rb:152:9:152:14 | call to s20 [element] : | semmle.label | call to s20 [element] : | | semantics.rb:152:13:152:13 | a : | semmle.label | a : | @@ -1122,8 +1260,12 @@ nodes | semantics.rb:154:10:154:10 | x [element] : | semmle.label | x [element] : | | semantics.rb:154:10:154:13 | ...[...] | semmle.label | ...[...] | | semantics.rb:154:10:154:13 | ...[...] | semmle.label | ...[...] | +| semantics.rb:158:5:158:5 | a : | semmle.label | a : | +| semantics.rb:158:5:158:5 | a : | semmle.label | a : | | semantics.rb:158:9:158:18 | call to source : | semmle.label | call to source : | | semantics.rb:158:9:158:18 | call to source : | semmle.label | call to source : | +| semantics.rb:159:5:159:5 | b : | semmle.label | b : | +| semantics.rb:159:5:159:5 | b : | semmle.label | b : | | semantics.rb:159:9:159:18 | call to source : | semmle.label | call to source : | | semantics.rb:159:9:159:18 | call to source : | semmle.label | call to source : | | semantics.rb:162:5:162:5 | [post] h [element 0] : | semmle.label | [post] h [element 0] : | @@ -1136,8 +1278,12 @@ nodes | semantics.rb:165:14:165:14 | h [element 0] : | semmle.label | h [element 0] : | | semantics.rb:165:14:165:14 | h [element] : | semmle.label | h [element] : | | semantics.rb:165:14:165:14 | h [element] : | semmle.label | h [element] : | +| semantics.rb:169:5:169:5 | a : | semmle.label | a : | +| semantics.rb:169:5:169:5 | a : | semmle.label | a : | | semantics.rb:169:9:169:18 | call to source : | semmle.label | call to source : | | semantics.rb:169:9:169:18 | call to source : | semmle.label | call to source : | +| semantics.rb:170:5:170:5 | x [element] : | semmle.label | x [element] : | +| semantics.rb:170:5:170:5 | x [element] : | semmle.label | x [element] : | | semantics.rb:170:9:170:14 | call to s22 [element] : | semmle.label | call to s22 [element] : | | semantics.rb:170:9:170:14 | call to s22 [element] : | semmle.label | call to s22 [element] : | | semantics.rb:170:13:170:13 | a : | semmle.label | a : | @@ -1150,6 +1296,8 @@ nodes | semantics.rb:172:10:172:10 | x [element] : | semmle.label | x [element] : | | semantics.rb:172:10:172:13 | ...[...] | semmle.label | ...[...] | | semantics.rb:172:10:172:13 | ...[...] | semmle.label | ...[...] | +| semantics.rb:176:5:176:5 | a : | semmle.label | a : | +| semantics.rb:176:5:176:5 | a : | semmle.label | a : | | semantics.rb:176:9:176:18 | call to source : | semmle.label | call to source : | | semantics.rb:176:9:176:18 | call to source : | semmle.label | call to source : | | semantics.rb:179:5:179:5 | [post] h [element 0] : | semmle.label | [post] h [element 0] : | @@ -1162,8 +1310,12 @@ nodes | semantics.rb:181:10:181:15 | call to s23 | semmle.label | call to s23 | | semantics.rb:181:14:181:14 | h [element 0] : | semmle.label | h [element 0] : | | semantics.rb:181:14:181:14 | h [element 0] : | semmle.label | h [element 0] : | +| semantics.rb:185:5:185:5 | a : | semmle.label | a : | +| semantics.rb:185:5:185:5 | a : | semmle.label | a : | | semantics.rb:185:9:185:18 | call to source : | semmle.label | call to source : | | semantics.rb:185:9:185:18 | call to source : | semmle.label | call to source : | +| semantics.rb:186:5:186:5 | x [element 0] : | semmle.label | x [element 0] : | +| semantics.rb:186:5:186:5 | x [element 0] : | semmle.label | x [element 0] : | | semantics.rb:186:9:186:14 | call to s24 [element 0] : | semmle.label | call to s24 [element 0] : | | semantics.rb:186:9:186:14 | call to s24 [element 0] : | semmle.label | call to s24 [element 0] : | | semantics.rb:186:13:186:13 | a : | semmle.label | a : | @@ -1176,6 +1328,8 @@ nodes | semantics.rb:189:10:189:10 | x [element 0] : | semmle.label | x [element 0] : | | semantics.rb:189:10:189:13 | ...[...] | semmle.label | ...[...] | | semantics.rb:189:10:189:13 | ...[...] | semmle.label | ...[...] | +| semantics.rb:193:5:193:5 | a : | semmle.label | a : | +| semantics.rb:193:5:193:5 | a : | semmle.label | a : | | semantics.rb:193:9:193:18 | call to source : | semmle.label | call to source : | | semantics.rb:193:9:193:18 | call to source : | semmle.label | call to source : | | semantics.rb:196:5:196:5 | [post] h [element 0] : | semmle.label | [post] h [element 0] : | @@ -1188,8 +1342,12 @@ nodes | semantics.rb:198:10:198:15 | call to s25 | semmle.label | call to s25 | | semantics.rb:198:14:198:14 | h [element 0] : | semmle.label | h [element 0] : | | semantics.rb:198:14:198:14 | h [element 0] : | semmle.label | h [element 0] : | +| semantics.rb:202:5:202:5 | a : | semmle.label | a : | +| semantics.rb:202:5:202:5 | a : | semmle.label | a : | | semantics.rb:202:9:202:18 | call to source : | semmle.label | call to source : | | semantics.rb:202:9:202:18 | call to source : | semmle.label | call to source : | +| semantics.rb:203:5:203:5 | x [element 0] : | semmle.label | x [element 0] : | +| semantics.rb:203:5:203:5 | x [element 0] : | semmle.label | x [element 0] : | | semantics.rb:203:9:203:14 | call to s26 [element 0] : | semmle.label | call to s26 [element 0] : | | semantics.rb:203:9:203:14 | call to s26 [element 0] : | semmle.label | call to s26 [element 0] : | | semantics.rb:203:13:203:13 | a : | semmle.label | a : | @@ -1202,10 +1360,16 @@ nodes | semantics.rb:206:10:206:10 | x [element 0] : | semmle.label | x [element 0] : | | semantics.rb:206:10:206:13 | ...[...] | semmle.label | ...[...] | | semantics.rb:206:10:206:13 | ...[...] | semmle.label | ...[...] | +| semantics.rb:211:5:211:5 | b : | semmle.label | b : | +| semantics.rb:211:5:211:5 | b : | semmle.label | b : | | semantics.rb:211:9:211:18 | call to source : | semmle.label | call to source : | | semantics.rb:211:9:211:18 | call to source : | semmle.label | call to source : | +| semantics.rb:212:5:212:5 | c : | semmle.label | c : | +| semantics.rb:212:5:212:5 | c : | semmle.label | c : | | semantics.rb:212:9:212:18 | call to source : | semmle.label | call to source : | | semantics.rb:212:9:212:18 | call to source : | semmle.label | call to source : | +| semantics.rb:213:5:213:5 | d : | semmle.label | d : | +| semantics.rb:213:5:213:5 | d : | semmle.label | d : | | semantics.rb:213:9:213:18 | call to source : | semmle.label | call to source : | | semantics.rb:213:9:213:18 | call to source : | semmle.label | call to source : | | semantics.rb:217:5:217:5 | [post] h [element 1] : | semmle.label | [post] h [element 1] : | @@ -1226,8 +1390,12 @@ nodes | semantics.rb:221:14:221:14 | h [element 2] : | semmle.label | h [element 2] : | | semantics.rb:221:14:221:14 | h [element] : | semmle.label | h [element] : | | semantics.rb:221:14:221:14 | h [element] : | semmle.label | h [element] : | +| semantics.rb:225:5:225:5 | a : | semmle.label | a : | +| semantics.rb:225:5:225:5 | a : | semmle.label | a : | | semantics.rb:225:9:225:18 | call to source : | semmle.label | call to source : | | semantics.rb:225:9:225:18 | call to source : | semmle.label | call to source : | +| semantics.rb:226:5:226:5 | x [element] : | semmle.label | x [element] : | +| semantics.rb:226:5:226:5 | x [element] : | semmle.label | x [element] : | | semantics.rb:226:9:226:14 | call to s28 [element] : | semmle.label | call to s28 [element] : | | semantics.rb:226:9:226:14 | call to s28 [element] : | semmle.label | call to s28 [element] : | | semantics.rb:226:13:226:13 | a : | semmle.label | a : | @@ -1248,8 +1416,12 @@ nodes | semantics.rb:230:10:230:10 | x [element] : | semmle.label | x [element] : | | semantics.rb:230:10:230:13 | ...[...] | semmle.label | ...[...] | | semantics.rb:230:10:230:13 | ...[...] | semmle.label | ...[...] | +| semantics.rb:235:5:235:5 | b : | semmle.label | b : | +| semantics.rb:235:5:235:5 | b : | semmle.label | b : | | semantics.rb:235:9:235:18 | call to source : | semmle.label | call to source : | | semantics.rb:235:9:235:18 | call to source : | semmle.label | call to source : | +| semantics.rb:236:5:236:5 | c : | semmle.label | c : | +| semantics.rb:236:5:236:5 | c : | semmle.label | c : | | semantics.rb:236:9:236:18 | call to source : | semmle.label | call to source : | | semantics.rb:236:9:236:18 | call to source : | semmle.label | call to source : | | semantics.rb:240:5:240:5 | [post] h [element 1] : | semmle.label | [post] h [element 1] : | @@ -1266,8 +1438,12 @@ nodes | semantics.rb:244:14:244:14 | h [element 1] : | semmle.label | h [element 1] : | | semantics.rb:244:14:244:14 | h [element 2] : | semmle.label | h [element 2] : | | semantics.rb:244:14:244:14 | h [element 2] : | semmle.label | h [element 2] : | +| semantics.rb:248:5:248:5 | a : | semmle.label | a : | +| semantics.rb:248:5:248:5 | a : | semmle.label | a : | | semantics.rb:248:9:248:18 | call to source : | semmle.label | call to source : | | semantics.rb:248:9:248:18 | call to source : | semmle.label | call to source : | +| semantics.rb:249:5:249:5 | x [element] : | semmle.label | x [element] : | +| semantics.rb:249:5:249:5 | x [element] : | semmle.label | x [element] : | | semantics.rb:249:9:249:14 | call to s30 [element] : | semmle.label | call to s30 [element] : | | semantics.rb:249:9:249:14 | call to s30 [element] : | semmle.label | call to s30 [element] : | | semantics.rb:249:13:249:13 | a : | semmle.label | a : | @@ -1382,6 +1558,8 @@ nodes | semantics.rb:285:14:285:14 | h [element true] : | semmle.label | h [element true] : | | semantics.rb:285:14:285:14 | h [element] : | semmle.label | h [element] : | | semantics.rb:285:14:285:14 | h [element] : | semmle.label | h [element] : | +| semantics.rb:289:5:289:5 | x [element :foo] : | semmle.label | x [element :foo] : | +| semantics.rb:289:5:289:5 | x [element :foo] : | semmle.label | x [element :foo] : | | semantics.rb:289:9:289:24 | call to s35 [element :foo] : | semmle.label | call to s35 [element :foo] : | | semantics.rb:289:9:289:24 | call to s35 [element :foo] : | semmle.label | call to s35 [element :foo] : | | semantics.rb:289:13:289:23 | call to source : | semmle.label | call to source : | @@ -1394,6 +1572,8 @@ nodes | semantics.rb:292:10:292:10 | x [element :foo] : | semmle.label | x [element :foo] : | | semantics.rb:292:10:292:13 | ...[...] | semmle.label | ...[...] | | semantics.rb:292:10:292:13 | ...[...] | semmle.label | ...[...] | +| semantics.rb:296:5:296:5 | x [element foo] : | semmle.label | x [element foo] : | +| semantics.rb:296:5:296:5 | x [element foo] : | semmle.label | x [element foo] : | | semantics.rb:296:9:296:24 | call to s36 [element foo] : | semmle.label | call to s36 [element foo] : | | semantics.rb:296:9:296:24 | call to s36 [element foo] : | semmle.label | call to s36 [element foo] : | | semantics.rb:296:13:296:23 | call to source : | semmle.label | call to source : | @@ -1406,6 +1586,8 @@ nodes | semantics.rb:300:10:300:10 | x [element foo] : | semmle.label | x [element foo] : | | semantics.rb:300:10:300:13 | ...[...] | semmle.label | ...[...] | | semantics.rb:300:10:300:13 | ...[...] | semmle.label | ...[...] | +| semantics.rb:304:5:304:5 | x [element true] : | semmle.label | x [element true] : | +| semantics.rb:304:5:304:5 | x [element true] : | semmle.label | x [element true] : | | semantics.rb:304:9:304:24 | call to s37 [element true] : | semmle.label | call to s37 [element true] : | | semantics.rb:304:9:304:24 | call to s37 [element true] : | semmle.label | call to s37 [element true] : | | semantics.rb:304:13:304:23 | call to source : | semmle.label | call to source : | @@ -1426,6 +1608,8 @@ nodes | semantics.rb:315:10:315:15 | call to s38 | semmle.label | call to s38 | | semantics.rb:315:14:315:14 | h [element foo] : | semmle.label | h [element foo] : | | semantics.rb:315:14:315:14 | h [element foo] : | semmle.label | h [element foo] : | +| semantics.rb:319:5:319:5 | x [element :foo] : | semmle.label | x [element :foo] : | +| semantics.rb:319:5:319:5 | x [element :foo] : | semmle.label | x [element :foo] : | | semantics.rb:319:9:319:24 | call to s39 [element :foo] : | semmle.label | call to s39 [element :foo] : | | semantics.rb:319:9:319:24 | call to s39 [element :foo] : | semmle.label | call to s39 [element :foo] : | | semantics.rb:319:13:319:23 | call to source : | semmle.label | call to source : | @@ -1446,6 +1630,8 @@ nodes | semantics.rb:329:10:329:15 | call to s40 | semmle.label | call to s40 | | semantics.rb:329:14:329:14 | x [@foo] : | semmle.label | x [@foo] : | | semantics.rb:329:14:329:14 | x [@foo] : | semmle.label | x [@foo] : | +| semantics.rb:333:5:333:5 | x [@foo] : | semmle.label | x [@foo] : | +| semantics.rb:333:5:333:5 | x [@foo] : | semmle.label | x [@foo] : | | semantics.rb:333:9:333:24 | call to s41 [@foo] : | semmle.label | call to s41 [@foo] : | | semantics.rb:333:9:333:24 | call to s41 [@foo] : | semmle.label | call to s41 [@foo] : | | semantics.rb:333:13:333:23 | call to source : | semmle.label | call to source : | @@ -1462,6 +1648,10 @@ nodes | semantics.rb:340:5:340:5 | [post] h [element] : | semmle.label | [post] h [element] : | | semantics.rb:340:12:340:22 | call to source : | semmle.label | call to source : | | semantics.rb:340:12:340:22 | call to source : | semmle.label | call to source : | +| semantics.rb:342:5:342:5 | x [element 0] : | semmle.label | x [element 0] : | +| semantics.rb:342:5:342:5 | x [element 0] : | semmle.label | x [element 0] : | +| semantics.rb:342:5:342:5 | x [element] : | semmle.label | x [element] : | +| semantics.rb:342:5:342:5 | x [element] : | semmle.label | x [element] : | | semantics.rb:342:9:342:14 | call to s42 [element 0] : | semmle.label | call to s42 [element 0] : | | semantics.rb:342:9:342:14 | call to s42 [element 0] : | semmle.label | call to s42 [element 0] : | | semantics.rb:342:9:342:14 | call to s42 [element] : | semmle.label | call to s42 [element] : | @@ -1490,6 +1680,8 @@ nodes | semantics.rb:350:5:350:5 | [post] h [element 0] : | semmle.label | [post] h [element 0] : | | semantics.rb:350:12:350:22 | call to source : | semmle.label | call to source : | | semantics.rb:350:12:350:22 | call to source : | semmle.label | call to source : | +| semantics.rb:353:5:353:5 | x [element 0] : | semmle.label | x [element 0] : | +| semantics.rb:353:5:353:5 | x [element 0] : | semmle.label | x [element 0] : | | semantics.rb:353:9:353:14 | call to s43 [element 0] : | semmle.label | call to s43 [element 0] : | | semantics.rb:353:9:353:14 | call to s43 [element 0] : | semmle.label | call to s43 [element 0] : | | semantics.rb:353:13:353:13 | h [element 0] : | semmle.label | h [element 0] : | @@ -1614,6 +1806,8 @@ nodes | semantics.rb:395:10:395:10 | h [element] : | semmle.label | h [element] : | | semantics.rb:395:10:395:13 | ...[...] | semmle.label | ...[...] | | semantics.rb:395:10:395:13 | ...[...] | semmle.label | ...[...] | +| semantics.rb:397:5:397:5 | x [element 1] : | semmle.label | x [element 1] : | +| semantics.rb:397:5:397:5 | x [element 1] : | semmle.label | x [element 1] : | | semantics.rb:397:9:397:14 | call to s46 [element 1] : | semmle.label | call to s46 [element 1] : | | semantics.rb:397:9:397:14 | call to s46 [element 1] : | semmle.label | call to s46 [element 1] : | | semantics.rb:397:13:397:13 | h [element 1] : | semmle.label | h [element 1] : | @@ -1654,6 +1848,8 @@ nodes | semantics.rb:410:10:410:10 | h [element] : | semmle.label | h [element] : | | semantics.rb:410:10:410:16 | ...[...] | semmle.label | ...[...] | | semantics.rb:410:10:410:16 | ...[...] | semmle.label | ...[...] | +| semantics.rb:412:5:412:5 | x [element :bar] : | semmle.label | x [element :bar] : | +| semantics.rb:412:5:412:5 | x [element :bar] : | semmle.label | x [element :bar] : | | semantics.rb:412:9:412:14 | call to s47 [element :bar] : | semmle.label | call to s47 [element :bar] : | | semantics.rb:412:9:412:14 | call to s47 [element :bar] : | semmle.label | call to s47 [element :bar] : | | semantics.rb:412:13:412:13 | h [element :bar] : | semmle.label | h [element :bar] : | @@ -1690,6 +1886,8 @@ nodes | semantics.rb:424:10:424:10 | h [element] : | semmle.label | h [element] : | | semantics.rb:424:10:424:16 | ...[...] | semmle.label | ...[...] | | semantics.rb:424:10:424:16 | ...[...] | semmle.label | ...[...] | +| semantics.rb:426:5:426:5 | x [element :bar] : | semmle.label | x [element :bar] : | +| semantics.rb:426:5:426:5 | x [element :bar] : | semmle.label | x [element :bar] : | | semantics.rb:426:9:426:14 | call to s48 [element :bar] : | semmle.label | call to s48 [element :bar] : | | semantics.rb:426:9:426:14 | call to s48 [element :bar] : | semmle.label | call to s48 [element :bar] : | | semantics.rb:426:13:426:13 | h [element :bar] : | semmle.label | h [element :bar] : | @@ -1726,6 +1924,10 @@ nodes | semantics.rb:438:10:438:10 | h [element] : | semmle.label | h [element] : | | semantics.rb:438:10:438:16 | ...[...] | semmle.label | ...[...] | | semantics.rb:438:10:438:16 | ...[...] | semmle.label | ...[...] | +| semantics.rb:440:5:440:5 | x [element :bar] : | semmle.label | x [element :bar] : | +| semantics.rb:440:5:440:5 | x [element :bar] : | semmle.label | x [element :bar] : | +| semantics.rb:440:5:440:5 | x [element] : | semmle.label | x [element] : | +| semantics.rb:440:5:440:5 | x [element] : | semmle.label | x [element] : | | semantics.rb:440:9:440:14 | call to s49 [element :bar] : | semmle.label | call to s49 [element :bar] : | | semantics.rb:440:9:440:14 | call to s49 [element :bar] : | semmle.label | call to s49 [element :bar] : | | semantics.rb:440:9:440:14 | call to s49 [element] : | semmle.label | call to s49 [element] : | @@ -1890,6 +2092,8 @@ nodes | semantics.rb:494:10:494:10 | h [element] : | semmle.label | h [element] : | | semantics.rb:494:10:494:16 | ...[...] | semmle.label | ...[...] | | semantics.rb:494:10:494:16 | ...[...] | semmle.label | ...[...] | +| semantics.rb:496:5:496:5 | x [element :bar] : | semmle.label | x [element :bar] : | +| semantics.rb:496:5:496:5 | x [element :bar] : | semmle.label | x [element :bar] : | | semantics.rb:496:9:496:9 | h [element :bar] : | semmle.label | h [element :bar] : | | semantics.rb:496:9:496:9 | h [element :bar] : | semmle.label | h [element :bar] : | | semantics.rb:496:9:496:15 | call to s53 [element :bar] : | semmle.label | call to s53 [element :bar] : | @@ -1930,6 +2134,8 @@ nodes | semantics.rb:510:10:510:10 | h [element] : | semmle.label | h [element] : | | semantics.rb:510:10:510:16 | ...[...] | semmle.label | ...[...] | | semantics.rb:510:10:510:16 | ...[...] | semmle.label | ...[...] | +| semantics.rb:512:5:512:5 | x [element :bar] : | semmle.label | x [element :bar] : | +| semantics.rb:512:5:512:5 | x [element :bar] : | semmle.label | x [element :bar] : | | semantics.rb:512:9:512:9 | h [element :bar] : | semmle.label | h [element :bar] : | | semantics.rb:512:9:512:9 | h [element :bar] : | semmle.label | h [element :bar] : | | semantics.rb:512:9:512:15 | call to s54 [element :bar] : | semmle.label | call to s54 [element :bar] : | diff --git a/ruby/ql/test/library-tests/dataflow/global/Flow.expected b/ruby/ql/test/library-tests/dataflow/global/Flow.expected index a6dd85ee0a1..ef1eb189de9 100644 --- a/ruby/ql/test/library-tests/dataflow/global/Flow.expected +++ b/ruby/ql/test/library-tests/dataflow/global/Flow.expected @@ -207,8 +207,10 @@ edges | instance_variables.rb:114:6:114:10 | foo13 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | | instance_variables.rb:114:6:114:10 | foo13 [@field] : | instance_variables.rb:114:6:114:20 | call to get_field | | instance_variables.rb:114:6:114:10 | foo13 [@field] : | instance_variables.rb:114:6:114:20 | call to get_field | -| instance_variables.rb:116:9:116:26 | call to new [@field] : | instance_variables.rb:117:6:117:10 | foo15 [@field] : | -| instance_variables.rb:116:9:116:26 | call to new [@field] : | instance_variables.rb:117:6:117:10 | foo15 [@field] : | +| instance_variables.rb:116:1:116:5 | foo15 [@field] : | instance_variables.rb:117:6:117:10 | foo15 [@field] : | +| instance_variables.rb:116:1:116:5 | foo15 [@field] : | instance_variables.rb:117:6:117:10 | foo15 [@field] : | +| instance_variables.rb:116:9:116:26 | call to new [@field] : | instance_variables.rb:116:1:116:5 | foo15 [@field] : | +| instance_variables.rb:116:9:116:26 | call to new [@field] : | instance_variables.rb:116:1:116:5 | foo15 [@field] : | | instance_variables.rb:116:17:116:25 | call to taint : | instance_variables.rb:22:20:22:24 | field : | | instance_variables.rb:116:17:116:25 | call to taint : | instance_variables.rb:22:20:22:24 | field : | | instance_variables.rb:116:17:116:25 | call to taint : | instance_variables.rb:116:9:116:26 | call to new [@field] : | @@ -227,8 +229,10 @@ edges | instance_variables.rb:120:6:120:10 | foo16 [@field] : | instance_variables.rb:13:5:15:7 | self in get_field [@field] : | | instance_variables.rb:120:6:120:10 | foo16 [@field] : | instance_variables.rb:120:6:120:20 | call to get_field | | instance_variables.rb:120:6:120:10 | foo16 [@field] : | instance_variables.rb:120:6:120:20 | call to get_field | -| instance_variables.rb:121:7:121:24 | call to new : | instance_variables.rb:122:6:122:8 | bar | -| instance_variables.rb:121:7:121:24 | call to new : | instance_variables.rb:122:6:122:8 | bar | +| instance_variables.rb:121:1:121:3 | bar : | instance_variables.rb:122:6:122:8 | bar | +| instance_variables.rb:121:1:121:3 | bar : | instance_variables.rb:122:6:122:8 | bar | +| instance_variables.rb:121:7:121:24 | call to new : | instance_variables.rb:121:1:121:3 | bar : | +| instance_variables.rb:121:7:121:24 | call to new : | instance_variables.rb:121:1:121:3 | bar : | nodes | captured_variables.rb:1:24:1:24 | x : | semmle.label | x : | | captured_variables.rb:1:24:1:24 | x : | semmle.label | x : | @@ -424,6 +428,8 @@ nodes | instance_variables.rb:114:6:114:10 | foo13 [@field] : | semmle.label | foo13 [@field] : | | instance_variables.rb:114:6:114:20 | call to get_field | semmle.label | call to get_field | | instance_variables.rb:114:6:114:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:116:1:116:5 | foo15 [@field] : | semmle.label | foo15 [@field] : | +| instance_variables.rb:116:1:116:5 | foo15 [@field] : | semmle.label | foo15 [@field] : | | instance_variables.rb:116:9:116:26 | call to new [@field] : | semmle.label | call to new [@field] : | | instance_variables.rb:116:9:116:26 | call to new [@field] : | semmle.label | call to new [@field] : | | instance_variables.rb:116:17:116:25 | call to taint : | semmle.label | call to taint : | @@ -442,6 +448,8 @@ nodes | instance_variables.rb:120:6:120:10 | foo16 [@field] : | semmle.label | foo16 [@field] : | | instance_variables.rb:120:6:120:20 | call to get_field | semmle.label | call to get_field | | instance_variables.rb:120:6:120:20 | call to get_field | semmle.label | call to get_field | +| instance_variables.rb:121:1:121:3 | bar : | semmle.label | bar : | +| instance_variables.rb:121:1:121:3 | bar : | semmle.label | bar : | | instance_variables.rb:121:7:121:24 | call to new : | semmle.label | call to new : | | instance_variables.rb:121:7:121:24 | call to new : | semmle.label | call to new : | | instance_variables.rb:122:6:122:8 | bar | semmle.label | bar | diff --git a/ruby/ql/test/library-tests/dataflow/hash-flow/hash-flow.expected b/ruby/ql/test/library-tests/dataflow/hash-flow/hash-flow.expected index 2dc14a20525..57c6d4c0627 100644 --- a/ruby/ql/test/library-tests/dataflow/hash-flow/hash-flow.expected +++ b/ruby/ql/test/library-tests/dataflow/hash-flow/hash-flow.expected @@ -1,10 +1,15 @@ failures edges -| hash_flow.rb:11:15:11:24 | call to taint : | hash_flow.rb:22:10:22:13 | hash [element :a] : | -| hash_flow.rb:13:12:13:21 | call to taint : | hash_flow.rb:24:10:24:13 | hash [element :c] : | -| hash_flow.rb:15:14:15:23 | call to taint : | hash_flow.rb:26:10:26:13 | hash [element e] : | -| hash_flow.rb:17:16:17:25 | call to taint : | hash_flow.rb:28:10:28:13 | hash [element g] : | -| hash_flow.rb:19:14:19:23 | call to taint : | hash_flow.rb:30:10:30:13 | hash [element 0] : | +| hash_flow.rb:10:5:10:8 | hash [element 0] : | hash_flow.rb:30:10:30:13 | hash [element 0] : | +| hash_flow.rb:10:5:10:8 | hash [element :a] : | hash_flow.rb:22:10:22:13 | hash [element :a] : | +| hash_flow.rb:10:5:10:8 | hash [element :c] : | hash_flow.rb:24:10:24:13 | hash [element :c] : | +| hash_flow.rb:10:5:10:8 | hash [element e] : | hash_flow.rb:26:10:26:13 | hash [element e] : | +| hash_flow.rb:10:5:10:8 | hash [element g] : | hash_flow.rb:28:10:28:13 | hash [element g] : | +| hash_flow.rb:11:15:11:24 | call to taint : | hash_flow.rb:10:5:10:8 | hash [element :a] : | +| hash_flow.rb:13:12:13:21 | call to taint : | hash_flow.rb:10:5:10:8 | hash [element :c] : | +| hash_flow.rb:15:14:15:23 | call to taint : | hash_flow.rb:10:5:10:8 | hash [element e] : | +| hash_flow.rb:17:16:17:25 | call to taint : | hash_flow.rb:10:5:10:8 | hash [element g] : | +| hash_flow.rb:19:14:19:23 | call to taint : | hash_flow.rb:10:5:10:8 | hash [element 0] : | | hash_flow.rb:22:10:22:13 | hash [element :a] : | hash_flow.rb:22:10:22:17 | ...[...] | | hash_flow.rb:24:10:24:13 | hash [element :c] : | hash_flow.rb:24:10:24:17 | ...[...] | | hash_flow.rb:26:10:26:13 | hash [element e] : | hash_flow.rb:26:10:26:18 | ...[...] | @@ -37,161 +42,214 @@ edges | hash_flow.rb:44:10:44:13 | hash [element 0] : | hash_flow.rb:44:10:44:16 | ...[...] | | hash_flow.rb:46:10:46:13 | hash [element :a] : | hash_flow.rb:46:10:46:17 | ...[...] | | hash_flow.rb:48:10:48:13 | hash [element a] : | hash_flow.rb:48:10:48:18 | ...[...] | -| hash_flow.rb:55:13:55:37 | ...[...] [element :a] : | hash_flow.rb:56:10:56:14 | hash1 [element :a] : | +| hash_flow.rb:55:5:55:9 | hash1 [element :a] : | hash_flow.rb:56:10:56:14 | hash1 [element :a] : | +| hash_flow.rb:55:13:55:37 | ...[...] [element :a] : | hash_flow.rb:55:5:55:9 | hash1 [element :a] : | | hash_flow.rb:55:21:55:30 | call to taint : | hash_flow.rb:55:13:55:37 | ...[...] [element :a] : | | hash_flow.rb:56:10:56:14 | hash1 [element :a] : | hash_flow.rb:56:10:56:18 | ...[...] | -| hash_flow.rb:59:13:59:22 | call to taint : | hash_flow.rb:60:18:60:18 | x [element :a] : | -| hash_flow.rb:60:13:60:19 | ...[...] [element :a] : | hash_flow.rb:61:10:61:14 | hash2 [element :a] : | +| hash_flow.rb:59:5:59:5 | x [element :a] : | hash_flow.rb:60:18:60:18 | x [element :a] : | +| hash_flow.rb:59:13:59:22 | call to taint : | hash_flow.rb:59:5:59:5 | x [element :a] : | +| hash_flow.rb:60:5:60:9 | hash2 [element :a] : | hash_flow.rb:61:10:61:14 | hash2 [element :a] : | +| hash_flow.rb:60:13:60:19 | ...[...] [element :a] : | hash_flow.rb:60:5:60:9 | hash2 [element :a] : | | hash_flow.rb:60:18:60:18 | x [element :a] : | hash_flow.rb:60:13:60:19 | ...[...] [element :a] : | | hash_flow.rb:61:10:61:14 | hash2 [element :a] : | hash_flow.rb:61:10:61:18 | ...[...] | -| hash_flow.rb:64:13:64:45 | ...[...] [element] : | hash_flow.rb:65:10:65:14 | hash3 [element] : | -| hash_flow.rb:64:13:64:45 | ...[...] [element] : | hash_flow.rb:66:10:66:14 | hash3 [element] : | +| hash_flow.rb:64:5:64:9 | hash3 [element] : | hash_flow.rb:65:10:65:14 | hash3 [element] : | +| hash_flow.rb:64:5:64:9 | hash3 [element] : | hash_flow.rb:66:10:66:14 | hash3 [element] : | +| hash_flow.rb:64:13:64:45 | ...[...] [element] : | hash_flow.rb:64:5:64:9 | hash3 [element] : | | hash_flow.rb:64:24:64:33 | call to taint : | hash_flow.rb:64:13:64:45 | ...[...] [element] : | | hash_flow.rb:65:10:65:14 | hash3 [element] : | hash_flow.rb:65:10:65:18 | ...[...] | | hash_flow.rb:66:10:66:14 | hash3 [element] : | hash_flow.rb:66:10:66:18 | ...[...] | -| hash_flow.rb:68:13:68:39 | ...[...] [element :a] : | hash_flow.rb:69:10:69:14 | hash4 [element :a] : | +| hash_flow.rb:68:5:68:9 | hash4 [element :a] : | hash_flow.rb:69:10:69:14 | hash4 [element :a] : | +| hash_flow.rb:68:13:68:39 | ...[...] [element :a] : | hash_flow.rb:68:5:68:9 | hash4 [element :a] : | | hash_flow.rb:68:22:68:31 | call to taint : | hash_flow.rb:68:13:68:39 | ...[...] [element :a] : | | hash_flow.rb:69:10:69:14 | hash4 [element :a] : | hash_flow.rb:69:10:69:18 | ...[...] | -| hash_flow.rb:72:13:72:45 | ...[...] [element a] : | hash_flow.rb:73:10:73:14 | hash5 [element a] : | +| hash_flow.rb:72:5:72:9 | hash5 [element a] : | hash_flow.rb:73:10:73:14 | hash5 [element a] : | +| hash_flow.rb:72:13:72:45 | ...[...] [element a] : | hash_flow.rb:72:5:72:9 | hash5 [element a] : | | hash_flow.rb:72:25:72:34 | call to taint : | hash_flow.rb:72:13:72:45 | ...[...] [element a] : | | hash_flow.rb:73:10:73:14 | hash5 [element a] : | hash_flow.rb:73:10:73:19 | ...[...] | -| hash_flow.rb:76:13:76:47 | ...[...] [element a] : | hash_flow.rb:77:10:77:14 | hash6 [element a] : | +| hash_flow.rb:76:5:76:9 | hash6 [element a] : | hash_flow.rb:77:10:77:14 | hash6 [element a] : | +| hash_flow.rb:76:13:76:47 | ...[...] [element a] : | hash_flow.rb:76:5:76:9 | hash6 [element a] : | | hash_flow.rb:76:26:76:35 | call to taint : | hash_flow.rb:76:13:76:47 | ...[...] [element a] : | | hash_flow.rb:77:10:77:14 | hash6 [element a] : | hash_flow.rb:77:10:77:19 | ...[...] | -| hash_flow.rb:84:13:84:42 | call to [] [element :a] : | hash_flow.rb:85:10:85:14 | hash1 [element :a] : | +| hash_flow.rb:84:5:84:9 | hash1 [element :a] : | hash_flow.rb:85:10:85:14 | hash1 [element :a] : | +| hash_flow.rb:84:13:84:42 | call to [] [element :a] : | hash_flow.rb:84:5:84:9 | hash1 [element :a] : | | hash_flow.rb:84:26:84:35 | call to taint : | hash_flow.rb:84:13:84:42 | call to [] [element :a] : | | hash_flow.rb:85:10:85:14 | hash1 [element :a] : | hash_flow.rb:85:10:85:18 | ...[...] | -| hash_flow.rb:93:15:93:24 | call to taint : | hash_flow.rb:96:30:96:33 | hash [element :a] : | -| hash_flow.rb:96:13:96:34 | call to try_convert [element :a] : | hash_flow.rb:97:10:97:14 | hash2 [element :a] : | +| hash_flow.rb:92:5:92:8 | hash [element :a] : | hash_flow.rb:96:30:96:33 | hash [element :a] : | +| hash_flow.rb:93:15:93:24 | call to taint : | hash_flow.rb:92:5:92:8 | hash [element :a] : | +| hash_flow.rb:96:5:96:9 | hash2 [element :a] : | hash_flow.rb:97:10:97:14 | hash2 [element :a] : | +| hash_flow.rb:96:13:96:34 | call to try_convert [element :a] : | hash_flow.rb:96:5:96:9 | hash2 [element :a] : | | hash_flow.rb:96:30:96:33 | hash [element :a] : | hash_flow.rb:96:13:96:34 | call to try_convert [element :a] : | | hash_flow.rb:97:10:97:14 | hash2 [element :a] : | hash_flow.rb:97:10:97:18 | ...[...] | -| hash_flow.rb:105:21:105:30 | call to taint : | hash_flow.rb:106:10:106:10 | b | +| hash_flow.rb:105:5:105:5 | b : | hash_flow.rb:106:10:106:10 | b | +| hash_flow.rb:105:21:105:30 | __synth__0 : | hash_flow.rb:105:5:105:5 | b : | +| hash_flow.rb:105:21:105:30 | call to taint : | hash_flow.rb:105:21:105:30 | __synth__0 : | +| hash_flow.rb:113:5:113:5 | b : | hash_flow.rb:115:10:115:10 | b | | hash_flow.rb:113:9:113:12 | [post] hash [element :a] : | hash_flow.rb:114:10:114:13 | hash [element :a] : | -| hash_flow.rb:113:9:113:34 | call to store : | hash_flow.rb:115:10:115:10 | b | +| hash_flow.rb:113:9:113:34 | call to store : | hash_flow.rb:113:5:113:5 | b : | | hash_flow.rb:113:24:113:33 | call to taint : | hash_flow.rb:113:9:113:12 | [post] hash [element :a] : | | hash_flow.rb:113:24:113:33 | call to taint : | hash_flow.rb:113:9:113:34 | call to store : | | hash_flow.rb:114:10:114:13 | hash [element :a] : | hash_flow.rb:114:10:114:17 | ...[...] | +| hash_flow.rb:118:5:118:5 | c : | hash_flow.rb:121:10:121:10 | c | | hash_flow.rb:118:9:118:12 | [post] hash [element] : | hash_flow.rb:119:10:119:13 | hash [element] : | | hash_flow.rb:118:9:118:12 | [post] hash [element] : | hash_flow.rb:120:10:120:13 | hash [element] : | -| hash_flow.rb:118:9:118:33 | call to store : | hash_flow.rb:121:10:121:10 | c | +| hash_flow.rb:118:9:118:33 | call to store : | hash_flow.rb:118:5:118:5 | c : | | hash_flow.rb:118:23:118:32 | call to taint : | hash_flow.rb:118:9:118:12 | [post] hash [element] : | | hash_flow.rb:118:23:118:32 | call to taint : | hash_flow.rb:118:9:118:33 | call to store : | | hash_flow.rb:119:10:119:13 | hash [element] : | hash_flow.rb:119:10:119:17 | ...[...] | | hash_flow.rb:120:10:120:13 | hash [element] : | hash_flow.rb:120:10:120:17 | ...[...] | -| hash_flow.rb:128:15:128:24 | call to taint : | hash_flow.rb:131:5:131:8 | hash [element :a] : | -| hash_flow.rb:128:15:128:24 | call to taint : | hash_flow.rb:134:5:134:8 | hash [element :a] : | +| hash_flow.rb:127:5:127:8 | hash [element :a] : | hash_flow.rb:131:5:131:8 | hash [element :a] : | +| hash_flow.rb:127:5:127:8 | hash [element :a] : | hash_flow.rb:134:5:134:8 | hash [element :a] : | +| hash_flow.rb:128:15:128:24 | call to taint : | hash_flow.rb:127:5:127:8 | hash [element :a] : | | hash_flow.rb:131:5:131:8 | hash [element :a] : | hash_flow.rb:131:18:131:29 | key_or_value : | | hash_flow.rb:131:18:131:29 | key_or_value : | hash_flow.rb:132:14:132:25 | key_or_value | | hash_flow.rb:134:5:134:8 | hash [element :a] : | hash_flow.rb:134:22:134:26 | value : | | hash_flow.rb:134:22:134:26 | value : | hash_flow.rb:136:14:136:18 | value | -| hash_flow.rb:144:15:144:25 | call to taint : | hash_flow.rb:147:9:147:12 | hash [element :a] : | -| hash_flow.rb:144:15:144:25 | call to taint : | hash_flow.rb:151:9:151:12 | hash [element :a] : | +| hash_flow.rb:143:5:143:8 | hash [element :a] : | hash_flow.rb:147:9:147:12 | hash [element :a] : | +| hash_flow.rb:143:5:143:8 | hash [element :a] : | hash_flow.rb:151:9:151:12 | hash [element :a] : | +| hash_flow.rb:144:15:144:25 | call to taint : | hash_flow.rb:143:5:143:8 | hash [element :a] : | +| hash_flow.rb:147:5:147:5 | b [element 1] : | hash_flow.rb:149:10:149:10 | b [element 1] : | +| hash_flow.rb:147:5:147:5 | b [element 1] : | hash_flow.rb:150:10:150:10 | b [element 1] : | | hash_flow.rb:147:9:147:12 | hash [element :a] : | hash_flow.rb:147:9:147:22 | call to assoc [element 1] : | -| hash_flow.rb:147:9:147:22 | call to assoc [element 1] : | hash_flow.rb:149:10:149:10 | b [element 1] : | -| hash_flow.rb:147:9:147:22 | call to assoc [element 1] : | hash_flow.rb:150:10:150:10 | b [element 1] : | +| hash_flow.rb:147:9:147:22 | call to assoc [element 1] : | hash_flow.rb:147:5:147:5 | b [element 1] : | | hash_flow.rb:149:10:149:10 | b [element 1] : | hash_flow.rb:149:10:149:13 | ...[...] | | hash_flow.rb:150:10:150:10 | b [element 1] : | hash_flow.rb:150:10:150:13 | ...[...] | +| hash_flow.rb:151:5:151:5 | c [element 1] : | hash_flow.rb:152:10:152:10 | c [element 1] : | | hash_flow.rb:151:9:151:12 | hash [element :a] : | hash_flow.rb:151:9:151:21 | call to assoc [element 1] : | -| hash_flow.rb:151:9:151:21 | call to assoc [element 1] : | hash_flow.rb:152:10:152:10 | c [element 1] : | +| hash_flow.rb:151:9:151:21 | call to assoc [element 1] : | hash_flow.rb:151:5:151:5 | c [element 1] : | | hash_flow.rb:152:10:152:10 | c [element 1] : | hash_flow.rb:152:10:152:13 | ...[...] | -| hash_flow.rb:170:15:170:25 | call to taint : | hash_flow.rb:173:9:173:12 | hash [element :a] : | +| hash_flow.rb:169:5:169:8 | hash [element :a] : | hash_flow.rb:173:9:173:12 | hash [element :a] : | +| hash_flow.rb:170:15:170:25 | call to taint : | hash_flow.rb:169:5:169:8 | hash [element :a] : | +| hash_flow.rb:173:5:173:5 | a [element :a] : | hash_flow.rb:174:10:174:10 | a [element :a] : | | hash_flow.rb:173:9:173:12 | hash [element :a] : | hash_flow.rb:173:9:173:20 | call to compact [element :a] : | -| hash_flow.rb:173:9:173:20 | call to compact [element :a] : | hash_flow.rb:174:10:174:10 | a [element :a] : | +| hash_flow.rb:173:9:173:20 | call to compact [element :a] : | hash_flow.rb:173:5:173:5 | a [element :a] : | | hash_flow.rb:174:10:174:10 | a [element :a] : | hash_flow.rb:174:10:174:14 | ...[...] | -| hash_flow.rb:182:15:182:25 | call to taint : | hash_flow.rb:185:9:185:12 | hash [element :a] : | +| hash_flow.rb:181:5:181:8 | hash [element :a] : | hash_flow.rb:185:9:185:12 | hash [element :a] : | +| hash_flow.rb:182:15:182:25 | call to taint : | hash_flow.rb:181:5:181:8 | hash [element :a] : | +| hash_flow.rb:185:5:185:5 | a : | hash_flow.rb:186:10:186:10 | a | | hash_flow.rb:185:9:185:12 | hash [element :a] : | hash_flow.rb:185:9:185:23 | call to delete : | -| hash_flow.rb:185:9:185:23 | call to delete : | hash_flow.rb:186:10:186:10 | a | -| hash_flow.rb:194:15:194:25 | call to taint : | hash_flow.rb:197:9:197:12 | hash [element :a] : | +| hash_flow.rb:185:9:185:23 | call to delete : | hash_flow.rb:185:5:185:5 | a : | +| hash_flow.rb:193:5:193:8 | hash [element :a] : | hash_flow.rb:197:9:197:12 | hash [element :a] : | +| hash_flow.rb:194:15:194:25 | call to taint : | hash_flow.rb:193:5:193:8 | hash [element :a] : | +| hash_flow.rb:197:5:197:5 | a [element :a] : | hash_flow.rb:201:10:201:10 | a [element :a] : | | hash_flow.rb:197:9:197:12 | [post] hash [element :a] : | hash_flow.rb:202:10:202:13 | hash [element :a] : | | hash_flow.rb:197:9:197:12 | hash [element :a] : | hash_flow.rb:197:9:197:12 | [post] hash [element :a] : | | hash_flow.rb:197:9:197:12 | hash [element :a] : | hash_flow.rb:197:9:200:7 | call to delete_if [element :a] : | | hash_flow.rb:197:9:197:12 | hash [element :a] : | hash_flow.rb:197:33:197:37 | value : | -| hash_flow.rb:197:9:200:7 | call to delete_if [element :a] : | hash_flow.rb:201:10:201:10 | a [element :a] : | +| hash_flow.rb:197:9:200:7 | call to delete_if [element :a] : | hash_flow.rb:197:5:197:5 | a [element :a] : | | hash_flow.rb:197:33:197:37 | value : | hash_flow.rb:199:14:199:18 | value | | hash_flow.rb:201:10:201:10 | a [element :a] : | hash_flow.rb:201:10:201:14 | ...[...] | | hash_flow.rb:202:10:202:13 | hash [element :a] : | hash_flow.rb:202:10:202:17 | ...[...] | -| hash_flow.rb:210:15:210:25 | call to taint : | hash_flow.rb:217:10:217:13 | hash [element :a] : | -| hash_flow.rb:213:19:213:29 | call to taint : | hash_flow.rb:219:10:219:13 | hash [element :c, element :d] : | +| hash_flow.rb:209:5:209:8 | hash [element :a] : | hash_flow.rb:217:10:217:13 | hash [element :a] : | +| hash_flow.rb:209:5:209:8 | hash [element :c, element :d] : | hash_flow.rb:219:10:219:13 | hash [element :c, element :d] : | +| hash_flow.rb:210:15:210:25 | call to taint : | hash_flow.rb:209:5:209:8 | hash [element :a] : | +| hash_flow.rb:213:19:213:29 | call to taint : | hash_flow.rb:209:5:209:8 | hash [element :c, element :d] : | | hash_flow.rb:217:10:217:13 | hash [element :a] : | hash_flow.rb:217:10:217:21 | call to dig | | hash_flow.rb:219:10:219:13 | hash [element :c, element :d] : | hash_flow.rb:219:10:219:24 | call to dig | -| hash_flow.rb:227:15:227:25 | call to taint : | hash_flow.rb:230:9:230:12 | hash [element :a] : | +| hash_flow.rb:226:5:226:8 | hash [element :a] : | hash_flow.rb:230:9:230:12 | hash [element :a] : | +| hash_flow.rb:227:15:227:25 | call to taint : | hash_flow.rb:226:5:226:8 | hash [element :a] : | +| hash_flow.rb:230:5:230:5 | x [element :a] : | hash_flow.rb:234:10:234:10 | x [element :a] : | | hash_flow.rb:230:9:230:12 | hash [element :a] : | hash_flow.rb:230:9:233:7 | call to each [element :a] : | | hash_flow.rb:230:9:230:12 | hash [element :a] : | hash_flow.rb:230:28:230:32 | value : | -| hash_flow.rb:230:9:233:7 | call to each [element :a] : | hash_flow.rb:234:10:234:10 | x [element :a] : | +| hash_flow.rb:230:9:233:7 | call to each [element :a] : | hash_flow.rb:230:5:230:5 | x [element :a] : | | hash_flow.rb:230:28:230:32 | value : | hash_flow.rb:232:14:232:18 | value | | hash_flow.rb:234:10:234:10 | x [element :a] : | hash_flow.rb:234:10:234:14 | ...[...] | -| hash_flow.rb:242:15:242:25 | call to taint : | hash_flow.rb:245:9:245:12 | hash [element :a] : | +| hash_flow.rb:241:5:241:8 | hash [element :a] : | hash_flow.rb:245:9:245:12 | hash [element :a] : | +| hash_flow.rb:242:15:242:25 | call to taint : | hash_flow.rb:241:5:241:8 | hash [element :a] : | +| hash_flow.rb:245:5:245:5 | x [element :a] : | hash_flow.rb:248:10:248:10 | x [element :a] : | | hash_flow.rb:245:9:245:12 | hash [element :a] : | hash_flow.rb:245:9:247:7 | call to each_key [element :a] : | -| hash_flow.rb:245:9:247:7 | call to each_key [element :a] : | hash_flow.rb:248:10:248:10 | x [element :a] : | +| hash_flow.rb:245:9:247:7 | call to each_key [element :a] : | hash_flow.rb:245:5:245:5 | x [element :a] : | | hash_flow.rb:248:10:248:10 | x [element :a] : | hash_flow.rb:248:10:248:14 | ...[...] | -| hash_flow.rb:256:15:256:25 | call to taint : | hash_flow.rb:259:9:259:12 | hash [element :a] : | +| hash_flow.rb:255:5:255:8 | hash [element :a] : | hash_flow.rb:259:9:259:12 | hash [element :a] : | +| hash_flow.rb:256:15:256:25 | call to taint : | hash_flow.rb:255:5:255:8 | hash [element :a] : | +| hash_flow.rb:259:5:259:5 | x [element :a] : | hash_flow.rb:263:10:263:10 | x [element :a] : | | hash_flow.rb:259:9:259:12 | hash [element :a] : | hash_flow.rb:259:9:262:7 | call to each_pair [element :a] : | | hash_flow.rb:259:9:259:12 | hash [element :a] : | hash_flow.rb:259:33:259:37 | value : | -| hash_flow.rb:259:9:262:7 | call to each_pair [element :a] : | hash_flow.rb:263:10:263:10 | x [element :a] : | +| hash_flow.rb:259:9:262:7 | call to each_pair [element :a] : | hash_flow.rb:259:5:259:5 | x [element :a] : | | hash_flow.rb:259:33:259:37 | value : | hash_flow.rb:261:14:261:18 | value | | hash_flow.rb:263:10:263:10 | x [element :a] : | hash_flow.rb:263:10:263:14 | ...[...] | -| hash_flow.rb:271:15:271:25 | call to taint : | hash_flow.rb:274:9:274:12 | hash [element :a] : | +| hash_flow.rb:270:5:270:8 | hash [element :a] : | hash_flow.rb:274:9:274:12 | hash [element :a] : | +| hash_flow.rb:271:15:271:25 | call to taint : | hash_flow.rb:270:5:270:8 | hash [element :a] : | +| hash_flow.rb:274:5:274:5 | x [element :a] : | hash_flow.rb:277:10:277:10 | x [element :a] : | | hash_flow.rb:274:9:274:12 | hash [element :a] : | hash_flow.rb:274:9:276:7 | call to each_value [element :a] : | | hash_flow.rb:274:9:274:12 | hash [element :a] : | hash_flow.rb:274:29:274:33 | value : | -| hash_flow.rb:274:9:276:7 | call to each_value [element :a] : | hash_flow.rb:277:10:277:10 | x [element :a] : | +| hash_flow.rb:274:9:276:7 | call to each_value [element :a] : | hash_flow.rb:274:5:274:5 | x [element :a] : | | hash_flow.rb:274:29:274:33 | value : | hash_flow.rb:275:14:275:18 | value | | hash_flow.rb:277:10:277:10 | x [element :a] : | hash_flow.rb:277:10:277:14 | ...[...] | -| hash_flow.rb:287:15:287:25 | call to taint : | hash_flow.rb:290:9:290:12 | hash [element :c] : | +| hash_flow.rb:284:5:284:8 | hash [element :c] : | hash_flow.rb:290:9:290:12 | hash [element :c] : | +| hash_flow.rb:287:15:287:25 | call to taint : | hash_flow.rb:284:5:284:8 | hash [element :c] : | +| hash_flow.rb:290:5:290:5 | x [element :c] : | hash_flow.rb:293:10:293:10 | x [element :c] : | | hash_flow.rb:290:9:290:12 | hash [element :c] : | hash_flow.rb:290:9:290:28 | call to except [element :c] : | -| hash_flow.rb:290:9:290:28 | call to except [element :c] : | hash_flow.rb:293:10:293:10 | x [element :c] : | +| hash_flow.rb:290:9:290:28 | call to except [element :c] : | hash_flow.rb:290:5:290:5 | x [element :c] : | | hash_flow.rb:293:10:293:10 | x [element :c] : | hash_flow.rb:293:10:293:14 | ...[...] | -| hash_flow.rb:301:15:301:25 | call to taint : | hash_flow.rb:305:9:305:12 | hash [element :a] : | -| hash_flow.rb:301:15:301:25 | call to taint : | hash_flow.rb:309:9:309:12 | hash [element :a] : | -| hash_flow.rb:301:15:301:25 | call to taint : | hash_flow.rb:311:9:311:12 | hash [element :a] : | -| hash_flow.rb:301:15:301:25 | call to taint : | hash_flow.rb:315:9:315:12 | hash [element :a] : | -| hash_flow.rb:303:15:303:25 | call to taint : | hash_flow.rb:305:9:305:12 | hash [element :c] : | -| hash_flow.rb:303:15:303:25 | call to taint : | hash_flow.rb:315:9:315:12 | hash [element :c] : | +| hash_flow.rb:300:5:300:8 | hash [element :a] : | hash_flow.rb:305:9:305:12 | hash [element :a] : | +| hash_flow.rb:300:5:300:8 | hash [element :a] : | hash_flow.rb:309:9:309:12 | hash [element :a] : | +| hash_flow.rb:300:5:300:8 | hash [element :a] : | hash_flow.rb:311:9:311:12 | hash [element :a] : | +| hash_flow.rb:300:5:300:8 | hash [element :a] : | hash_flow.rb:315:9:315:12 | hash [element :a] : | +| hash_flow.rb:300:5:300:8 | hash [element :c] : | hash_flow.rb:305:9:305:12 | hash [element :c] : | +| hash_flow.rb:300:5:300:8 | hash [element :c] : | hash_flow.rb:315:9:315:12 | hash [element :c] : | +| hash_flow.rb:301:15:301:25 | call to taint : | hash_flow.rb:300:5:300:8 | hash [element :a] : | +| hash_flow.rb:303:15:303:25 | call to taint : | hash_flow.rb:300:5:300:8 | hash [element :c] : | +| hash_flow.rb:305:5:305:5 | b : | hash_flow.rb:308:10:308:10 | b | | hash_flow.rb:305:9:305:12 | hash [element :a] : | hash_flow.rb:305:9:307:7 | call to fetch : | | hash_flow.rb:305:9:305:12 | hash [element :c] : | hash_flow.rb:305:9:307:7 | call to fetch : | -| hash_flow.rb:305:9:307:7 | call to fetch : | hash_flow.rb:308:10:308:10 | b | +| hash_flow.rb:305:9:307:7 | call to fetch : | hash_flow.rb:305:5:305:5 | b : | | hash_flow.rb:305:20:305:30 | call to taint : | hash_flow.rb:305:37:305:37 | x : | | hash_flow.rb:305:37:305:37 | x : | hash_flow.rb:306:14:306:14 | x | +| hash_flow.rb:309:5:309:5 | b : | hash_flow.rb:310:10:310:10 | b | | hash_flow.rb:309:9:309:12 | hash [element :a] : | hash_flow.rb:309:9:309:22 | call to fetch : | -| hash_flow.rb:309:9:309:22 | call to fetch : | hash_flow.rb:310:10:310:10 | b | +| hash_flow.rb:309:9:309:22 | call to fetch : | hash_flow.rb:309:5:309:5 | b : | +| hash_flow.rb:311:5:311:5 | b : | hash_flow.rb:312:10:312:10 | b | | hash_flow.rb:311:9:311:12 | hash [element :a] : | hash_flow.rb:311:9:311:35 | call to fetch : | -| hash_flow.rb:311:9:311:35 | call to fetch : | hash_flow.rb:312:10:312:10 | b | +| hash_flow.rb:311:9:311:35 | call to fetch : | hash_flow.rb:311:5:311:5 | b : | | hash_flow.rb:311:24:311:34 | call to taint : | hash_flow.rb:311:9:311:35 | call to fetch : | -| hash_flow.rb:313:9:313:35 | call to fetch : | hash_flow.rb:314:10:314:10 | b | +| hash_flow.rb:313:5:313:5 | b : | hash_flow.rb:314:10:314:10 | b | +| hash_flow.rb:313:9:313:35 | call to fetch : | hash_flow.rb:313:5:313:5 | b : | | hash_flow.rb:313:24:313:34 | call to taint : | hash_flow.rb:313:9:313:35 | call to fetch : | +| hash_flow.rb:315:5:315:5 | b : | hash_flow.rb:316:10:316:10 | b | | hash_flow.rb:315:9:315:12 | hash [element :a] : | hash_flow.rb:315:9:315:34 | call to fetch : | | hash_flow.rb:315:9:315:12 | hash [element :c] : | hash_flow.rb:315:9:315:34 | call to fetch : | -| hash_flow.rb:315:9:315:34 | call to fetch : | hash_flow.rb:316:10:316:10 | b | +| hash_flow.rb:315:9:315:34 | call to fetch : | hash_flow.rb:315:5:315:5 | b : | | hash_flow.rb:315:23:315:33 | call to taint : | hash_flow.rb:315:9:315:34 | call to fetch : | -| hash_flow.rb:323:15:323:25 | call to taint : | hash_flow.rb:327:9:327:12 | hash [element :a] : | -| hash_flow.rb:323:15:323:25 | call to taint : | hash_flow.rb:332:9:332:12 | hash [element :a] : | -| hash_flow.rb:323:15:323:25 | call to taint : | hash_flow.rb:334:9:334:12 | hash [element :a] : | -| hash_flow.rb:325:15:325:25 | call to taint : | hash_flow.rb:327:9:327:12 | hash [element :c] : | -| hash_flow.rb:325:15:325:25 | call to taint : | hash_flow.rb:334:9:334:12 | hash [element :c] : | +| hash_flow.rb:322:5:322:8 | hash [element :a] : | hash_flow.rb:327:9:327:12 | hash [element :a] : | +| hash_flow.rb:322:5:322:8 | hash [element :a] : | hash_flow.rb:332:9:332:12 | hash [element :a] : | +| hash_flow.rb:322:5:322:8 | hash [element :a] : | hash_flow.rb:334:9:334:12 | hash [element :a] : | +| hash_flow.rb:322:5:322:8 | hash [element :c] : | hash_flow.rb:327:9:327:12 | hash [element :c] : | +| hash_flow.rb:322:5:322:8 | hash [element :c] : | hash_flow.rb:334:9:334:12 | hash [element :c] : | +| hash_flow.rb:323:15:323:25 | call to taint : | hash_flow.rb:322:5:322:8 | hash [element :a] : | +| hash_flow.rb:325:15:325:25 | call to taint : | hash_flow.rb:322:5:322:8 | hash [element :c] : | +| hash_flow.rb:327:5:327:5 | b [element] : | hash_flow.rb:331:10:331:10 | b [element] : | | hash_flow.rb:327:9:327:12 | hash [element :a] : | hash_flow.rb:327:9:330:7 | call to fetch_values [element] : | | hash_flow.rb:327:9:327:12 | hash [element :c] : | hash_flow.rb:327:9:330:7 | call to fetch_values [element] : | -| hash_flow.rb:327:9:330:7 | call to fetch_values [element] : | hash_flow.rb:331:10:331:10 | b [element] : | +| hash_flow.rb:327:9:330:7 | call to fetch_values [element] : | hash_flow.rb:327:5:327:5 | b [element] : | | hash_flow.rb:327:27:327:37 | call to taint : | hash_flow.rb:327:44:327:44 | x : | | hash_flow.rb:327:44:327:44 | x : | hash_flow.rb:328:14:328:14 | x | | hash_flow.rb:329:9:329:19 | call to taint : | hash_flow.rb:327:9:330:7 | call to fetch_values [element] : | | hash_flow.rb:331:10:331:10 | b [element] : | hash_flow.rb:331:10:331:13 | ...[...] | +| hash_flow.rb:332:5:332:5 | b [element] : | hash_flow.rb:333:10:333:10 | b [element] : | | hash_flow.rb:332:9:332:12 | hash [element :a] : | hash_flow.rb:332:9:332:29 | call to fetch_values [element] : | -| hash_flow.rb:332:9:332:29 | call to fetch_values [element] : | hash_flow.rb:333:10:333:10 | b [element] : | +| hash_flow.rb:332:9:332:29 | call to fetch_values [element] : | hash_flow.rb:332:5:332:5 | b [element] : | | hash_flow.rb:333:10:333:10 | b [element] : | hash_flow.rb:333:10:333:13 | ...[...] | +| hash_flow.rb:334:5:334:5 | b [element] : | hash_flow.rb:335:10:335:10 | b [element] : | | hash_flow.rb:334:9:334:12 | hash [element :a] : | hash_flow.rb:334:9:334:31 | call to fetch_values [element] : | | hash_flow.rb:334:9:334:12 | hash [element :c] : | hash_flow.rb:334:9:334:31 | call to fetch_values [element] : | -| hash_flow.rb:334:9:334:31 | call to fetch_values [element] : | hash_flow.rb:335:10:335:10 | b [element] : | +| hash_flow.rb:334:9:334:31 | call to fetch_values [element] : | hash_flow.rb:334:5:334:5 | b [element] : | | hash_flow.rb:335:10:335:10 | b [element] : | hash_flow.rb:335:10:335:13 | ...[...] | -| hash_flow.rb:342:15:342:25 | call to taint : | hash_flow.rb:346:9:346:12 | hash [element :a] : | -| hash_flow.rb:344:15:344:25 | call to taint : | hash_flow.rb:346:9:346:12 | hash [element :c] : | +| hash_flow.rb:341:5:341:8 | hash [element :a] : | hash_flow.rb:346:9:346:12 | hash [element :a] : | +| hash_flow.rb:341:5:341:8 | hash [element :c] : | hash_flow.rb:346:9:346:12 | hash [element :c] : | +| hash_flow.rb:342:15:342:25 | call to taint : | hash_flow.rb:341:5:341:8 | hash [element :a] : | +| hash_flow.rb:344:15:344:25 | call to taint : | hash_flow.rb:341:5:341:8 | hash [element :c] : | +| hash_flow.rb:346:5:346:5 | b [element :a] : | hash_flow.rb:351:11:351:11 | b [element :a] : | | hash_flow.rb:346:9:346:12 | hash [element :a] : | hash_flow.rb:346:9:350:7 | call to filter [element :a] : | | hash_flow.rb:346:9:346:12 | hash [element :a] : | hash_flow.rb:346:30:346:34 | value : | | hash_flow.rb:346:9:346:12 | hash [element :c] : | hash_flow.rb:346:30:346:34 | value : | -| hash_flow.rb:346:9:350:7 | call to filter [element :a] : | hash_flow.rb:351:11:351:11 | b [element :a] : | +| hash_flow.rb:346:9:350:7 | call to filter [element :a] : | hash_flow.rb:346:5:346:5 | b [element :a] : | | hash_flow.rb:346:30:346:34 | value : | hash_flow.rb:348:14:348:18 | value | | hash_flow.rb:351:11:351:11 | b [element :a] : | hash_flow.rb:351:11:351:15 | ...[...] : | | hash_flow.rb:351:11:351:15 | ...[...] : | hash_flow.rb:351:10:351:16 | ( ... ) | -| hash_flow.rb:358:15:358:25 | call to taint : | hash_flow.rb:362:5:362:8 | hash [element :a] : | -| hash_flow.rb:360:15:360:25 | call to taint : | hash_flow.rb:362:5:362:8 | hash [element :c] : | +| hash_flow.rb:357:5:357:8 | hash [element :a] : | hash_flow.rb:362:5:362:8 | hash [element :a] : | +| hash_flow.rb:357:5:357:8 | hash [element :c] : | hash_flow.rb:362:5:362:8 | hash [element :c] : | +| hash_flow.rb:358:15:358:25 | call to taint : | hash_flow.rb:357:5:357:8 | hash [element :a] : | +| hash_flow.rb:360:15:360:25 | call to taint : | hash_flow.rb:357:5:357:8 | hash [element :c] : | | hash_flow.rb:362:5:362:8 | [post] hash [element :a] : | hash_flow.rb:367:11:367:14 | hash [element :a] : | | hash_flow.rb:362:5:362:8 | hash [element :a] : | hash_flow.rb:362:5:362:8 | [post] hash [element :a] : | | hash_flow.rb:362:5:362:8 | hash [element :a] : | hash_flow.rb:362:27:362:31 | value : | @@ -199,40 +257,54 @@ edges | hash_flow.rb:362:27:362:31 | value : | hash_flow.rb:364:14:364:18 | value | | hash_flow.rb:367:11:367:14 | hash [element :a] : | hash_flow.rb:367:11:367:18 | ...[...] : | | hash_flow.rb:367:11:367:18 | ...[...] : | hash_flow.rb:367:10:367:19 | ( ... ) | -| hash_flow.rb:374:15:374:25 | call to taint : | hash_flow.rb:378:9:378:12 | hash [element :a] : | -| hash_flow.rb:376:15:376:25 | call to taint : | hash_flow.rb:378:9:378:12 | hash [element :c] : | +| hash_flow.rb:373:5:373:8 | hash [element :a] : | hash_flow.rb:378:9:378:12 | hash [element :a] : | +| hash_flow.rb:373:5:373:8 | hash [element :c] : | hash_flow.rb:378:9:378:12 | hash [element :c] : | +| hash_flow.rb:374:15:374:25 | call to taint : | hash_flow.rb:373:5:373:8 | hash [element :a] : | +| hash_flow.rb:376:15:376:25 | call to taint : | hash_flow.rb:373:5:373:8 | hash [element :c] : | +| hash_flow.rb:378:5:378:5 | b [element] : | hash_flow.rb:379:11:379:11 | b [element] : | | hash_flow.rb:378:9:378:12 | hash [element :a] : | hash_flow.rb:378:9:378:20 | call to flatten [element] : | | hash_flow.rb:378:9:378:12 | hash [element :c] : | hash_flow.rb:378:9:378:20 | call to flatten [element] : | -| hash_flow.rb:378:9:378:20 | call to flatten [element] : | hash_flow.rb:379:11:379:11 | b [element] : | +| hash_flow.rb:378:9:378:20 | call to flatten [element] : | hash_flow.rb:378:5:378:5 | b [element] : | | hash_flow.rb:379:11:379:11 | b [element] : | hash_flow.rb:379:11:379:14 | ...[...] : | | hash_flow.rb:379:11:379:14 | ...[...] : | hash_flow.rb:379:10:379:15 | ( ... ) | -| hash_flow.rb:386:15:386:25 | call to taint : | hash_flow.rb:390:9:390:12 | hash [element :a] : | -| hash_flow.rb:388:15:388:25 | call to taint : | hash_flow.rb:390:9:390:12 | hash [element :c] : | +| hash_flow.rb:385:5:385:8 | hash [element :a] : | hash_flow.rb:390:9:390:12 | hash [element :a] : | +| hash_flow.rb:385:5:385:8 | hash [element :c] : | hash_flow.rb:390:9:390:12 | hash [element :c] : | +| hash_flow.rb:386:15:386:25 | call to taint : | hash_flow.rb:385:5:385:8 | hash [element :a] : | +| hash_flow.rb:388:15:388:25 | call to taint : | hash_flow.rb:385:5:385:8 | hash [element :c] : | +| hash_flow.rb:390:5:390:5 | b [element :a] : | hash_flow.rb:396:11:396:11 | b [element :a] : | | hash_flow.rb:390:9:390:12 | [post] hash [element :a] : | hash_flow.rb:395:11:395:14 | hash [element :a] : | | hash_flow.rb:390:9:390:12 | hash [element :a] : | hash_flow.rb:390:9:390:12 | [post] hash [element :a] : | | hash_flow.rb:390:9:390:12 | hash [element :a] : | hash_flow.rb:390:9:394:7 | call to keep_if [element :a] : | | hash_flow.rb:390:9:390:12 | hash [element :a] : | hash_flow.rb:390:31:390:35 | value : | | hash_flow.rb:390:9:390:12 | hash [element :c] : | hash_flow.rb:390:31:390:35 | value : | -| hash_flow.rb:390:9:394:7 | call to keep_if [element :a] : | hash_flow.rb:396:11:396:11 | b [element :a] : | +| hash_flow.rb:390:9:394:7 | call to keep_if [element :a] : | hash_flow.rb:390:5:390:5 | b [element :a] : | | hash_flow.rb:390:31:390:35 | value : | hash_flow.rb:392:14:392:18 | value | | hash_flow.rb:395:11:395:14 | hash [element :a] : | hash_flow.rb:395:11:395:18 | ...[...] : | | hash_flow.rb:395:11:395:18 | ...[...] : | hash_flow.rb:395:10:395:19 | ( ... ) | | hash_flow.rb:396:11:396:11 | b [element :a] : | hash_flow.rb:396:11:396:15 | ...[...] : | | hash_flow.rb:396:11:396:15 | ...[...] : | hash_flow.rb:396:10:396:16 | ( ... ) | -| hash_flow.rb:403:15:403:25 | call to taint : | hash_flow.rb:412:12:412:16 | hash1 [element :a] : | -| hash_flow.rb:405:15:405:25 | call to taint : | hash_flow.rb:412:12:412:16 | hash1 [element :c] : | -| hash_flow.rb:408:15:408:25 | call to taint : | hash_flow.rb:412:24:412:28 | hash2 [element :d] : | -| hash_flow.rb:410:15:410:25 | call to taint : | hash_flow.rb:412:24:412:28 | hash2 [element :f] : | +| hash_flow.rb:402:5:402:9 | hash1 [element :a] : | hash_flow.rb:412:12:412:16 | hash1 [element :a] : | +| hash_flow.rb:402:5:402:9 | hash1 [element :c] : | hash_flow.rb:412:12:412:16 | hash1 [element :c] : | +| hash_flow.rb:403:15:403:25 | call to taint : | hash_flow.rb:402:5:402:9 | hash1 [element :a] : | +| hash_flow.rb:405:15:405:25 | call to taint : | hash_flow.rb:402:5:402:9 | hash1 [element :c] : | +| hash_flow.rb:407:5:407:9 | hash2 [element :d] : | hash_flow.rb:412:24:412:28 | hash2 [element :d] : | +| hash_flow.rb:407:5:407:9 | hash2 [element :f] : | hash_flow.rb:412:24:412:28 | hash2 [element :f] : | +| hash_flow.rb:408:15:408:25 | call to taint : | hash_flow.rb:407:5:407:9 | hash2 [element :d] : | +| hash_flow.rb:410:15:410:25 | call to taint : | hash_flow.rb:407:5:407:9 | hash2 [element :f] : | +| hash_flow.rb:412:5:412:8 | hash [element :a] : | hash_flow.rb:417:11:417:14 | hash [element :a] : | +| hash_flow.rb:412:5:412:8 | hash [element :c] : | hash_flow.rb:419:11:419:14 | hash [element :c] : | +| hash_flow.rb:412:5:412:8 | hash [element :d] : | hash_flow.rb:420:11:420:14 | hash [element :d] : | +| hash_flow.rb:412:5:412:8 | hash [element :f] : | hash_flow.rb:422:11:422:14 | hash [element :f] : | | hash_flow.rb:412:12:412:16 | hash1 [element :a] : | hash_flow.rb:412:12:416:7 | call to merge [element :a] : | | hash_flow.rb:412:12:412:16 | hash1 [element :a] : | hash_flow.rb:412:40:412:48 | old_value : | | hash_flow.rb:412:12:412:16 | hash1 [element :a] : | hash_flow.rb:412:51:412:59 | new_value : | | hash_flow.rb:412:12:412:16 | hash1 [element :c] : | hash_flow.rb:412:12:416:7 | call to merge [element :c] : | | hash_flow.rb:412:12:412:16 | hash1 [element :c] : | hash_flow.rb:412:40:412:48 | old_value : | | hash_flow.rb:412:12:412:16 | hash1 [element :c] : | hash_flow.rb:412:51:412:59 | new_value : | -| hash_flow.rb:412:12:416:7 | call to merge [element :a] : | hash_flow.rb:417:11:417:14 | hash [element :a] : | -| hash_flow.rb:412:12:416:7 | call to merge [element :c] : | hash_flow.rb:419:11:419:14 | hash [element :c] : | -| hash_flow.rb:412:12:416:7 | call to merge [element :d] : | hash_flow.rb:420:11:420:14 | hash [element :d] : | -| hash_flow.rb:412:12:416:7 | call to merge [element :f] : | hash_flow.rb:422:11:422:14 | hash [element :f] : | +| hash_flow.rb:412:12:416:7 | call to merge [element :a] : | hash_flow.rb:412:5:412:8 | hash [element :a] : | +| hash_flow.rb:412:12:416:7 | call to merge [element :c] : | hash_flow.rb:412:5:412:8 | hash [element :c] : | +| hash_flow.rb:412:12:416:7 | call to merge [element :d] : | hash_flow.rb:412:5:412:8 | hash [element :d] : | +| hash_flow.rb:412:12:416:7 | call to merge [element :f] : | hash_flow.rb:412:5:412:8 | hash [element :f] : | | hash_flow.rb:412:24:412:28 | hash2 [element :d] : | hash_flow.rb:412:12:416:7 | call to merge [element :d] : | | hash_flow.rb:412:24:412:28 | hash2 [element :d] : | hash_flow.rb:412:40:412:48 | old_value : | | hash_flow.rb:412:24:412:28 | hash2 [element :d] : | hash_flow.rb:412:51:412:59 | new_value : | @@ -249,10 +321,18 @@ edges | hash_flow.rb:420:11:420:18 | ...[...] : | hash_flow.rb:420:10:420:19 | ( ... ) | | hash_flow.rb:422:11:422:14 | hash [element :f] : | hash_flow.rb:422:11:422:18 | ...[...] : | | hash_flow.rb:422:11:422:18 | ...[...] : | hash_flow.rb:422:10:422:19 | ( ... ) | -| hash_flow.rb:429:15:429:25 | call to taint : | hash_flow.rb:438:12:438:16 | hash1 [element :a] : | -| hash_flow.rb:431:15:431:25 | call to taint : | hash_flow.rb:438:12:438:16 | hash1 [element :c] : | -| hash_flow.rb:434:15:434:25 | call to taint : | hash_flow.rb:438:25:438:29 | hash2 [element :d] : | -| hash_flow.rb:436:15:436:25 | call to taint : | hash_flow.rb:438:25:438:29 | hash2 [element :f] : | +| hash_flow.rb:428:5:428:9 | hash1 [element :a] : | hash_flow.rb:438:12:438:16 | hash1 [element :a] : | +| hash_flow.rb:428:5:428:9 | hash1 [element :c] : | hash_flow.rb:438:12:438:16 | hash1 [element :c] : | +| hash_flow.rb:429:15:429:25 | call to taint : | hash_flow.rb:428:5:428:9 | hash1 [element :a] : | +| hash_flow.rb:431:15:431:25 | call to taint : | hash_flow.rb:428:5:428:9 | hash1 [element :c] : | +| hash_flow.rb:433:5:433:9 | hash2 [element :d] : | hash_flow.rb:438:25:438:29 | hash2 [element :d] : | +| hash_flow.rb:433:5:433:9 | hash2 [element :f] : | hash_flow.rb:438:25:438:29 | hash2 [element :f] : | +| hash_flow.rb:434:15:434:25 | call to taint : | hash_flow.rb:433:5:433:9 | hash2 [element :d] : | +| hash_flow.rb:436:15:436:25 | call to taint : | hash_flow.rb:433:5:433:9 | hash2 [element :f] : | +| hash_flow.rb:438:5:438:8 | hash [element :a] : | hash_flow.rb:443:11:443:14 | hash [element :a] : | +| hash_flow.rb:438:5:438:8 | hash [element :c] : | hash_flow.rb:445:11:445:14 | hash [element :c] : | +| hash_flow.rb:438:5:438:8 | hash [element :d] : | hash_flow.rb:446:11:446:14 | hash [element :d] : | +| hash_flow.rb:438:5:438:8 | hash [element :f] : | hash_flow.rb:448:11:448:14 | hash [element :f] : | | hash_flow.rb:438:12:438:16 | [post] hash1 [element :a] : | hash_flow.rb:450:11:450:15 | hash1 [element :a] : | | hash_flow.rb:438:12:438:16 | [post] hash1 [element :c] : | hash_flow.rb:452:11:452:15 | hash1 [element :c] : | | hash_flow.rb:438:12:438:16 | [post] hash1 [element :d] : | hash_flow.rb:453:11:453:15 | hash1 [element :d] : | @@ -265,10 +345,10 @@ edges | hash_flow.rb:438:12:438:16 | hash1 [element :c] : | hash_flow.rb:438:12:442:7 | call to merge! [element :c] : | | hash_flow.rb:438:12:438:16 | hash1 [element :c] : | hash_flow.rb:438:41:438:49 | old_value : | | hash_flow.rb:438:12:438:16 | hash1 [element :c] : | hash_flow.rb:438:52:438:60 | new_value : | -| hash_flow.rb:438:12:442:7 | call to merge! [element :a] : | hash_flow.rb:443:11:443:14 | hash [element :a] : | -| hash_flow.rb:438:12:442:7 | call to merge! [element :c] : | hash_flow.rb:445:11:445:14 | hash [element :c] : | -| hash_flow.rb:438:12:442:7 | call to merge! [element :d] : | hash_flow.rb:446:11:446:14 | hash [element :d] : | -| hash_flow.rb:438:12:442:7 | call to merge! [element :f] : | hash_flow.rb:448:11:448:14 | hash [element :f] : | +| hash_flow.rb:438:12:442:7 | call to merge! [element :a] : | hash_flow.rb:438:5:438:8 | hash [element :a] : | +| hash_flow.rb:438:12:442:7 | call to merge! [element :c] : | hash_flow.rb:438:5:438:8 | hash [element :c] : | +| hash_flow.rb:438:12:442:7 | call to merge! [element :d] : | hash_flow.rb:438:5:438:8 | hash [element :d] : | +| hash_flow.rb:438:12:442:7 | call to merge! [element :f] : | hash_flow.rb:438:5:438:8 | hash [element :f] : | | hash_flow.rb:438:25:438:29 | hash2 [element :d] : | hash_flow.rb:438:12:438:16 | [post] hash1 [element :d] : | | hash_flow.rb:438:25:438:29 | hash2 [element :d] : | hash_flow.rb:438:12:442:7 | call to merge! [element :d] : | | hash_flow.rb:438:25:438:29 | hash2 [element :d] : | hash_flow.rb:438:41:438:49 | old_value : | @@ -295,27 +375,35 @@ edges | hash_flow.rb:453:11:453:19 | ...[...] : | hash_flow.rb:453:10:453:20 | ( ... ) | | hash_flow.rb:455:11:455:15 | hash1 [element :f] : | hash_flow.rb:455:11:455:19 | ...[...] : | | hash_flow.rb:455:11:455:19 | ...[...] : | hash_flow.rb:455:10:455:20 | ( ... ) | -| hash_flow.rb:462:15:462:25 | call to taint : | hash_flow.rb:465:9:465:12 | hash [element :a] : | +| hash_flow.rb:461:5:461:8 | hash [element :a] : | hash_flow.rb:465:9:465:12 | hash [element :a] : | +| hash_flow.rb:462:15:462:25 | call to taint : | hash_flow.rb:461:5:461:8 | hash [element :a] : | +| hash_flow.rb:465:5:465:5 | b [element 1] : | hash_flow.rb:467:10:467:10 | b [element 1] : | | hash_flow.rb:465:9:465:12 | hash [element :a] : | hash_flow.rb:465:9:465:22 | call to rassoc [element 1] : | -| hash_flow.rb:465:9:465:22 | call to rassoc [element 1] : | hash_flow.rb:467:10:467:10 | b [element 1] : | +| hash_flow.rb:465:9:465:22 | call to rassoc [element 1] : | hash_flow.rb:465:5:465:5 | b [element 1] : | | hash_flow.rb:467:10:467:10 | b [element 1] : | hash_flow.rb:467:10:467:13 | ...[...] | -| hash_flow.rb:474:15:474:25 | call to taint : | hash_flow.rb:477:9:477:12 | hash [element :a] : | +| hash_flow.rb:473:5:473:8 | hash [element :a] : | hash_flow.rb:477:9:477:12 | hash [element :a] : | +| hash_flow.rb:474:15:474:25 | call to taint : | hash_flow.rb:473:5:473:8 | hash [element :a] : | +| hash_flow.rb:477:5:477:5 | b [element :a] : | hash_flow.rb:482:10:482:10 | b [element :a] : | | hash_flow.rb:477:9:477:12 | hash [element :a] : | hash_flow.rb:477:9:481:7 | call to reject [element :a] : | | hash_flow.rb:477:9:477:12 | hash [element :a] : | hash_flow.rb:477:29:477:33 | value : | -| hash_flow.rb:477:9:481:7 | call to reject [element :a] : | hash_flow.rb:482:10:482:10 | b [element :a] : | +| hash_flow.rb:477:9:481:7 | call to reject [element :a] : | hash_flow.rb:477:5:477:5 | b [element :a] : | | hash_flow.rb:477:29:477:33 | value : | hash_flow.rb:479:14:479:18 | value | | hash_flow.rb:482:10:482:10 | b [element :a] : | hash_flow.rb:482:10:482:14 | ...[...] | -| hash_flow.rb:489:15:489:25 | call to taint : | hash_flow.rb:492:9:492:12 | hash [element :a] : | +| hash_flow.rb:488:5:488:8 | hash [element :a] : | hash_flow.rb:492:9:492:12 | hash [element :a] : | +| hash_flow.rb:489:15:489:25 | call to taint : | hash_flow.rb:488:5:488:8 | hash [element :a] : | +| hash_flow.rb:492:5:492:5 | b [element :a] : | hash_flow.rb:497:10:497:10 | b [element :a] : | | hash_flow.rb:492:9:492:12 | [post] hash [element :a] : | hash_flow.rb:498:10:498:13 | hash [element :a] : | | hash_flow.rb:492:9:492:12 | hash [element :a] : | hash_flow.rb:492:9:492:12 | [post] hash [element :a] : | | hash_flow.rb:492:9:492:12 | hash [element :a] : | hash_flow.rb:492:9:496:7 | call to reject! [element :a] : | | hash_flow.rb:492:9:492:12 | hash [element :a] : | hash_flow.rb:492:30:492:34 | value : | -| hash_flow.rb:492:9:496:7 | call to reject! [element :a] : | hash_flow.rb:497:10:497:10 | b [element :a] : | +| hash_flow.rb:492:9:496:7 | call to reject! [element :a] : | hash_flow.rb:492:5:492:5 | b [element :a] : | | hash_flow.rb:492:30:492:34 | value : | hash_flow.rb:494:14:494:18 | value | | hash_flow.rb:497:10:497:10 | b [element :a] : | hash_flow.rb:497:10:497:14 | ...[...] | | hash_flow.rb:498:10:498:13 | hash [element :a] : | hash_flow.rb:498:10:498:17 | ...[...] | -| hash_flow.rb:505:15:505:25 | call to taint : | hash_flow.rb:512:19:512:22 | hash [element :a] : | -| hash_flow.rb:507:15:507:25 | call to taint : | hash_flow.rb:512:19:512:22 | hash [element :c] : | +| hash_flow.rb:504:5:504:8 | hash [element :a] : | hash_flow.rb:512:19:512:22 | hash [element :a] : | +| hash_flow.rb:504:5:504:8 | hash [element :c] : | hash_flow.rb:512:19:512:22 | hash [element :c] : | +| hash_flow.rb:505:15:505:25 | call to taint : | hash_flow.rb:504:5:504:8 | hash [element :a] : | +| hash_flow.rb:507:15:507:25 | call to taint : | hash_flow.rb:504:5:504:8 | hash [element :c] : | | hash_flow.rb:512:5:512:9 | [post] hash2 [element :a] : | hash_flow.rb:513:11:513:15 | hash2 [element :a] : | | hash_flow.rb:512:5:512:9 | [post] hash2 [element :c] : | hash_flow.rb:515:11:515:15 | hash2 [element :c] : | | hash_flow.rb:512:19:512:22 | hash [element :a] : | hash_flow.rb:512:5:512:9 | [post] hash2 [element :a] : | @@ -324,17 +412,22 @@ edges | hash_flow.rb:513:11:513:19 | ...[...] : | hash_flow.rb:513:10:513:20 | ( ... ) | | hash_flow.rb:515:11:515:15 | hash2 [element :c] : | hash_flow.rb:515:11:515:19 | ...[...] : | | hash_flow.rb:515:11:515:19 | ...[...] : | hash_flow.rb:515:10:515:20 | ( ... ) | -| hash_flow.rb:520:15:520:25 | call to taint : | hash_flow.rb:524:9:524:12 | hash [element :a] : | -| hash_flow.rb:522:15:522:25 | call to taint : | hash_flow.rb:524:9:524:12 | hash [element :c] : | +| hash_flow.rb:519:5:519:8 | hash [element :a] : | hash_flow.rb:524:9:524:12 | hash [element :a] : | +| hash_flow.rb:519:5:519:8 | hash [element :c] : | hash_flow.rb:524:9:524:12 | hash [element :c] : | +| hash_flow.rb:520:15:520:25 | call to taint : | hash_flow.rb:519:5:519:8 | hash [element :a] : | +| hash_flow.rb:522:15:522:25 | call to taint : | hash_flow.rb:519:5:519:8 | hash [element :c] : | +| hash_flow.rb:524:5:524:5 | b [element :a] : | hash_flow.rb:529:11:529:11 | b [element :a] : | | hash_flow.rb:524:9:524:12 | hash [element :a] : | hash_flow.rb:524:9:528:7 | call to select [element :a] : | | hash_flow.rb:524:9:524:12 | hash [element :a] : | hash_flow.rb:524:30:524:34 | value : | | hash_flow.rb:524:9:524:12 | hash [element :c] : | hash_flow.rb:524:30:524:34 | value : | -| hash_flow.rb:524:9:528:7 | call to select [element :a] : | hash_flow.rb:529:11:529:11 | b [element :a] : | +| hash_flow.rb:524:9:528:7 | call to select [element :a] : | hash_flow.rb:524:5:524:5 | b [element :a] : | | hash_flow.rb:524:30:524:34 | value : | hash_flow.rb:526:14:526:18 | value | | hash_flow.rb:529:11:529:11 | b [element :a] : | hash_flow.rb:529:11:529:15 | ...[...] : | | hash_flow.rb:529:11:529:15 | ...[...] : | hash_flow.rb:529:10:529:16 | ( ... ) | -| hash_flow.rb:536:15:536:25 | call to taint : | hash_flow.rb:540:5:540:8 | hash [element :a] : | -| hash_flow.rb:538:15:538:25 | call to taint : | hash_flow.rb:540:5:540:8 | hash [element :c] : | +| hash_flow.rb:535:5:535:8 | hash [element :a] : | hash_flow.rb:540:5:540:8 | hash [element :a] : | +| hash_flow.rb:535:5:535:8 | hash [element :c] : | hash_flow.rb:540:5:540:8 | hash [element :c] : | +| hash_flow.rb:536:15:536:25 | call to taint : | hash_flow.rb:535:5:535:8 | hash [element :a] : | +| hash_flow.rb:538:15:538:25 | call to taint : | hash_flow.rb:535:5:535:8 | hash [element :c] : | | hash_flow.rb:540:5:540:8 | [post] hash [element :a] : | hash_flow.rb:545:11:545:14 | hash [element :a] : | | hash_flow.rb:540:5:540:8 | hash [element :a] : | hash_flow.rb:540:5:540:8 | [post] hash [element :a] : | | hash_flow.rb:540:5:540:8 | hash [element :a] : | hash_flow.rb:540:27:540:31 | value : | @@ -342,74 +435,95 @@ edges | hash_flow.rb:540:27:540:31 | value : | hash_flow.rb:542:14:542:18 | value | | hash_flow.rb:545:11:545:14 | hash [element :a] : | hash_flow.rb:545:11:545:18 | ...[...] : | | hash_flow.rb:545:11:545:18 | ...[...] : | hash_flow.rb:545:10:545:19 | ( ... ) | -| hash_flow.rb:552:15:552:25 | call to taint : | hash_flow.rb:556:9:556:12 | hash [element :a] : | -| hash_flow.rb:554:15:554:25 | call to taint : | hash_flow.rb:556:9:556:12 | hash [element :c] : | +| hash_flow.rb:551:5:551:8 | hash [element :a] : | hash_flow.rb:556:9:556:12 | hash [element :a] : | +| hash_flow.rb:551:5:551:8 | hash [element :c] : | hash_flow.rb:556:9:556:12 | hash [element :c] : | +| hash_flow.rb:552:15:552:25 | call to taint : | hash_flow.rb:551:5:551:8 | hash [element :a] : | +| hash_flow.rb:554:15:554:25 | call to taint : | hash_flow.rb:551:5:551:8 | hash [element :c] : | +| hash_flow.rb:556:5:556:5 | b [element 1] : | hash_flow.rb:559:11:559:11 | b [element 1] : | | hash_flow.rb:556:9:556:12 | [post] hash [element :a] : | hash_flow.rb:557:11:557:14 | hash [element :a] : | | hash_flow.rb:556:9:556:12 | hash [element :a] : | hash_flow.rb:556:9:556:12 | [post] hash [element :a] : | | hash_flow.rb:556:9:556:12 | hash [element :a] : | hash_flow.rb:556:9:556:18 | call to shift [element 1] : | | hash_flow.rb:556:9:556:12 | hash [element :c] : | hash_flow.rb:556:9:556:18 | call to shift [element 1] : | -| hash_flow.rb:556:9:556:18 | call to shift [element 1] : | hash_flow.rb:559:11:559:11 | b [element 1] : | +| hash_flow.rb:556:9:556:18 | call to shift [element 1] : | hash_flow.rb:556:5:556:5 | b [element 1] : | | hash_flow.rb:557:11:557:14 | hash [element :a] : | hash_flow.rb:557:11:557:18 | ...[...] : | | hash_flow.rb:557:11:557:18 | ...[...] : | hash_flow.rb:557:10:557:19 | ( ... ) | | hash_flow.rb:559:11:559:11 | b [element 1] : | hash_flow.rb:559:11:559:14 | ...[...] : | | hash_flow.rb:559:11:559:14 | ...[...] : | hash_flow.rb:559:10:559:15 | ( ... ) | -| hash_flow.rb:566:15:566:25 | call to taint : | hash_flow.rb:570:9:570:12 | hash [element :a] : | -| hash_flow.rb:566:15:566:25 | call to taint : | hash_flow.rb:575:9:575:12 | hash [element :a] : | -| hash_flow.rb:568:15:568:25 | call to taint : | hash_flow.rb:575:9:575:12 | hash [element :c] : | +| hash_flow.rb:565:5:565:8 | hash [element :a] : | hash_flow.rb:570:9:570:12 | hash [element :a] : | +| hash_flow.rb:565:5:565:8 | hash [element :a] : | hash_flow.rb:575:9:575:12 | hash [element :a] : | +| hash_flow.rb:565:5:565:8 | hash [element :c] : | hash_flow.rb:575:9:575:12 | hash [element :c] : | +| hash_flow.rb:566:15:566:25 | call to taint : | hash_flow.rb:565:5:565:8 | hash [element :a] : | +| hash_flow.rb:568:15:568:25 | call to taint : | hash_flow.rb:565:5:565:8 | hash [element :c] : | +| hash_flow.rb:570:5:570:5 | b [element :a] : | hash_flow.rb:571:11:571:11 | b [element :a] : | | hash_flow.rb:570:9:570:12 | hash [element :a] : | hash_flow.rb:570:9:570:26 | call to slice [element :a] : | -| hash_flow.rb:570:9:570:26 | call to slice [element :a] : | hash_flow.rb:571:11:571:11 | b [element :a] : | +| hash_flow.rb:570:9:570:26 | call to slice [element :a] : | hash_flow.rb:570:5:570:5 | b [element :a] : | | hash_flow.rb:571:11:571:11 | b [element :a] : | hash_flow.rb:571:11:571:15 | ...[...] : | | hash_flow.rb:571:11:571:15 | ...[...] : | hash_flow.rb:571:10:571:16 | ( ... ) | +| hash_flow.rb:575:5:575:5 | c [element :a] : | hash_flow.rb:576:11:576:11 | c [element :a] : | +| hash_flow.rb:575:5:575:5 | c [element :c] : | hash_flow.rb:578:11:578:11 | c [element :c] : | | hash_flow.rb:575:9:575:12 | hash [element :a] : | hash_flow.rb:575:9:575:25 | call to slice [element :a] : | | hash_flow.rb:575:9:575:12 | hash [element :c] : | hash_flow.rb:575:9:575:25 | call to slice [element :c] : | -| hash_flow.rb:575:9:575:25 | call to slice [element :a] : | hash_flow.rb:576:11:576:11 | c [element :a] : | -| hash_flow.rb:575:9:575:25 | call to slice [element :c] : | hash_flow.rb:578:11:578:11 | c [element :c] : | +| hash_flow.rb:575:9:575:25 | call to slice [element :a] : | hash_flow.rb:575:5:575:5 | c [element :a] : | +| hash_flow.rb:575:9:575:25 | call to slice [element :c] : | hash_flow.rb:575:5:575:5 | c [element :c] : | | hash_flow.rb:576:11:576:11 | c [element :a] : | hash_flow.rb:576:11:576:15 | ...[...] : | | hash_flow.rb:576:11:576:15 | ...[...] : | hash_flow.rb:576:10:576:16 | ( ... ) | | hash_flow.rb:578:11:578:11 | c [element :c] : | hash_flow.rb:578:11:578:15 | ...[...] : | | hash_flow.rb:578:11:578:15 | ...[...] : | hash_flow.rb:578:10:578:16 | ( ... ) | -| hash_flow.rb:585:15:585:25 | call to taint : | hash_flow.rb:589:9:589:12 | hash [element :a] : | -| hash_flow.rb:587:15:587:25 | call to taint : | hash_flow.rb:589:9:589:12 | hash [element :c] : | +| hash_flow.rb:584:5:584:8 | hash [element :a] : | hash_flow.rb:589:9:589:12 | hash [element :a] : | +| hash_flow.rb:584:5:584:8 | hash [element :c] : | hash_flow.rb:589:9:589:12 | hash [element :c] : | +| hash_flow.rb:585:15:585:25 | call to taint : | hash_flow.rb:584:5:584:8 | hash [element :a] : | +| hash_flow.rb:587:15:587:25 | call to taint : | hash_flow.rb:584:5:584:8 | hash [element :c] : | +| hash_flow.rb:589:5:589:5 | a [element, element 1] : | hash_flow.rb:591:11:591:11 | a [element, element 1] : | | hash_flow.rb:589:9:589:12 | hash [element :a] : | hash_flow.rb:589:9:589:17 | call to to_a [element, element 1] : | | hash_flow.rb:589:9:589:12 | hash [element :c] : | hash_flow.rb:589:9:589:17 | call to to_a [element, element 1] : | -| hash_flow.rb:589:9:589:17 | call to to_a [element, element 1] : | hash_flow.rb:591:11:591:11 | a [element, element 1] : | +| hash_flow.rb:589:9:589:17 | call to to_a [element, element 1] : | hash_flow.rb:589:5:589:5 | a [element, element 1] : | | hash_flow.rb:591:11:591:11 | a [element, element 1] : | hash_flow.rb:591:11:591:14 | ...[...] [element 1] : | | hash_flow.rb:591:11:591:14 | ...[...] [element 1] : | hash_flow.rb:591:11:591:17 | ...[...] : | | hash_flow.rb:591:11:591:17 | ...[...] : | hash_flow.rb:591:10:591:18 | ( ... ) | -| hash_flow.rb:598:15:598:25 | call to taint : | hash_flow.rb:602:9:602:12 | hash [element :a] : | -| hash_flow.rb:598:15:598:25 | call to taint : | hash_flow.rb:607:9:607:12 | hash [element :a] : | -| hash_flow.rb:600:15:600:25 | call to taint : | hash_flow.rb:602:9:602:12 | hash [element :c] : | -| hash_flow.rb:600:15:600:25 | call to taint : | hash_flow.rb:607:9:607:12 | hash [element :c] : | +| hash_flow.rb:597:5:597:8 | hash [element :a] : | hash_flow.rb:602:9:602:12 | hash [element :a] : | +| hash_flow.rb:597:5:597:8 | hash [element :a] : | hash_flow.rb:607:9:607:12 | hash [element :a] : | +| hash_flow.rb:597:5:597:8 | hash [element :c] : | hash_flow.rb:602:9:602:12 | hash [element :c] : | +| hash_flow.rb:597:5:597:8 | hash [element :c] : | hash_flow.rb:607:9:607:12 | hash [element :c] : | +| hash_flow.rb:598:15:598:25 | call to taint : | hash_flow.rb:597:5:597:8 | hash [element :a] : | +| hash_flow.rb:600:15:600:25 | call to taint : | hash_flow.rb:597:5:597:8 | hash [element :c] : | +| hash_flow.rb:602:5:602:5 | a [element :a] : | hash_flow.rb:603:11:603:11 | a [element :a] : | +| hash_flow.rb:602:5:602:5 | a [element :c] : | hash_flow.rb:605:11:605:11 | a [element :c] : | | hash_flow.rb:602:9:602:12 | hash [element :a] : | hash_flow.rb:602:9:602:17 | call to to_h [element :a] : | | hash_flow.rb:602:9:602:12 | hash [element :c] : | hash_flow.rb:602:9:602:17 | call to to_h [element :c] : | -| hash_flow.rb:602:9:602:17 | call to to_h [element :a] : | hash_flow.rb:603:11:603:11 | a [element :a] : | -| hash_flow.rb:602:9:602:17 | call to to_h [element :c] : | hash_flow.rb:605:11:605:11 | a [element :c] : | +| hash_flow.rb:602:9:602:17 | call to to_h [element :a] : | hash_flow.rb:602:5:602:5 | a [element :a] : | +| hash_flow.rb:602:9:602:17 | call to to_h [element :c] : | hash_flow.rb:602:5:602:5 | a [element :c] : | | hash_flow.rb:603:11:603:11 | a [element :a] : | hash_flow.rb:603:11:603:15 | ...[...] : | | hash_flow.rb:603:11:603:15 | ...[...] : | hash_flow.rb:603:10:603:16 | ( ... ) | | hash_flow.rb:605:11:605:11 | a [element :c] : | hash_flow.rb:605:11:605:15 | ...[...] : | | hash_flow.rb:605:11:605:15 | ...[...] : | hash_flow.rb:605:10:605:16 | ( ... ) | +| hash_flow.rb:607:5:607:5 | b [element] : | hash_flow.rb:612:11:612:11 | b [element] : | | hash_flow.rb:607:9:607:12 | hash [element :a] : | hash_flow.rb:607:28:607:32 | value : | | hash_flow.rb:607:9:607:12 | hash [element :c] : | hash_flow.rb:607:28:607:32 | value : | -| hash_flow.rb:607:9:611:7 | call to to_h [element] : | hash_flow.rb:612:11:612:11 | b [element] : | +| hash_flow.rb:607:9:611:7 | call to to_h [element] : | hash_flow.rb:607:5:607:5 | b [element] : | | hash_flow.rb:607:28:607:32 | value : | hash_flow.rb:609:14:609:18 | value | | hash_flow.rb:610:14:610:24 | call to taint : | hash_flow.rb:607:9:611:7 | call to to_h [element] : | | hash_flow.rb:612:11:612:11 | b [element] : | hash_flow.rb:612:11:612:15 | ...[...] : | | hash_flow.rb:612:11:612:15 | ...[...] : | hash_flow.rb:612:10:612:16 | ( ... ) | -| hash_flow.rb:619:15:619:25 | call to taint : | hash_flow.rb:623:9:623:12 | hash [element :a] : | -| hash_flow.rb:621:15:621:25 | call to taint : | hash_flow.rb:623:9:623:12 | hash [element :c] : | +| hash_flow.rb:618:5:618:8 | hash [element :a] : | hash_flow.rb:623:9:623:12 | hash [element :a] : | +| hash_flow.rb:618:5:618:8 | hash [element :c] : | hash_flow.rb:623:9:623:12 | hash [element :c] : | +| hash_flow.rb:619:15:619:25 | call to taint : | hash_flow.rb:618:5:618:8 | hash [element :a] : | +| hash_flow.rb:621:15:621:25 | call to taint : | hash_flow.rb:618:5:618:8 | hash [element :c] : | +| hash_flow.rb:623:5:623:5 | a [element] : | hash_flow.rb:624:11:624:11 | a [element] : | +| hash_flow.rb:623:5:623:5 | a [element] : | hash_flow.rb:625:11:625:11 | a [element] : | +| hash_flow.rb:623:5:623:5 | a [element] : | hash_flow.rb:626:11:626:11 | a [element] : | | hash_flow.rb:623:9:623:12 | hash [element :a] : | hash_flow.rb:623:9:623:45 | call to transform_keys [element] : | | hash_flow.rb:623:9:623:12 | hash [element :c] : | hash_flow.rb:623:9:623:45 | call to transform_keys [element] : | -| hash_flow.rb:623:9:623:45 | call to transform_keys [element] : | hash_flow.rb:624:11:624:11 | a [element] : | -| hash_flow.rb:623:9:623:45 | call to transform_keys [element] : | hash_flow.rb:625:11:625:11 | a [element] : | -| hash_flow.rb:623:9:623:45 | call to transform_keys [element] : | hash_flow.rb:626:11:626:11 | a [element] : | +| hash_flow.rb:623:9:623:45 | call to transform_keys [element] : | hash_flow.rb:623:5:623:5 | a [element] : | | hash_flow.rb:624:11:624:11 | a [element] : | hash_flow.rb:624:11:624:16 | ...[...] : | | hash_flow.rb:624:11:624:16 | ...[...] : | hash_flow.rb:624:10:624:17 | ( ... ) | | hash_flow.rb:625:11:625:11 | a [element] : | hash_flow.rb:625:11:625:16 | ...[...] : | | hash_flow.rb:625:11:625:16 | ...[...] : | hash_flow.rb:625:10:625:17 | ( ... ) | | hash_flow.rb:626:11:626:11 | a [element] : | hash_flow.rb:626:11:626:16 | ...[...] : | | hash_flow.rb:626:11:626:16 | ...[...] : | hash_flow.rb:626:10:626:17 | ( ... ) | -| hash_flow.rb:633:15:633:25 | call to taint : | hash_flow.rb:639:5:639:8 | hash [element :a] : | -| hash_flow.rb:635:15:635:25 | call to taint : | hash_flow.rb:639:5:639:8 | hash [element :c] : | +| hash_flow.rb:632:5:632:8 | hash [element :a] : | hash_flow.rb:639:5:639:8 | hash [element :a] : | +| hash_flow.rb:632:5:632:8 | hash [element :c] : | hash_flow.rb:639:5:639:8 | hash [element :c] : | +| hash_flow.rb:633:15:633:25 | call to taint : | hash_flow.rb:632:5:632:8 | hash [element :a] : | +| hash_flow.rb:635:15:635:25 | call to taint : | hash_flow.rb:632:5:632:8 | hash [element :c] : | | hash_flow.rb:637:5:637:8 | [post] hash [element] : | hash_flow.rb:639:5:639:8 | hash [element] : | | hash_flow.rb:637:5:637:8 | [post] hash [element] : | hash_flow.rb:640:11:640:14 | hash [element] : | | hash_flow.rb:637:5:637:8 | [post] hash [element] : | hash_flow.rb:641:11:641:14 | hash [element] : | @@ -427,20 +541,25 @@ edges | hash_flow.rb:641:11:641:19 | ...[...] : | hash_flow.rb:641:10:641:20 | ( ... ) | | hash_flow.rb:642:11:642:14 | hash [element] : | hash_flow.rb:642:11:642:19 | ...[...] : | | hash_flow.rb:642:11:642:19 | ...[...] : | hash_flow.rb:642:10:642:20 | ( ... ) | -| hash_flow.rb:649:15:649:25 | call to taint : | hash_flow.rb:653:9:653:12 | hash [element :a] : | -| hash_flow.rb:649:15:649:25 | call to taint : | hash_flow.rb:657:11:657:14 | hash [element :a] : | -| hash_flow.rb:651:15:651:25 | call to taint : | hash_flow.rb:653:9:653:12 | hash [element :c] : | +| hash_flow.rb:648:5:648:8 | hash [element :a] : | hash_flow.rb:653:9:653:12 | hash [element :a] : | +| hash_flow.rb:648:5:648:8 | hash [element :a] : | hash_flow.rb:657:11:657:14 | hash [element :a] : | +| hash_flow.rb:648:5:648:8 | hash [element :c] : | hash_flow.rb:653:9:653:12 | hash [element :c] : | +| hash_flow.rb:649:15:649:25 | call to taint : | hash_flow.rb:648:5:648:8 | hash [element :a] : | +| hash_flow.rb:651:15:651:25 | call to taint : | hash_flow.rb:648:5:648:8 | hash [element :c] : | +| hash_flow.rb:653:5:653:5 | b [element] : | hash_flow.rb:658:11:658:11 | b [element] : | | hash_flow.rb:653:9:653:12 | hash [element :a] : | hash_flow.rb:653:35:653:39 | value : | | hash_flow.rb:653:9:653:12 | hash [element :c] : | hash_flow.rb:653:35:653:39 | value : | -| hash_flow.rb:653:9:656:7 | call to transform_values [element] : | hash_flow.rb:658:11:658:11 | b [element] : | +| hash_flow.rb:653:9:656:7 | call to transform_values [element] : | hash_flow.rb:653:5:653:5 | b [element] : | | hash_flow.rb:653:35:653:39 | value : | hash_flow.rb:654:14:654:18 | value | | hash_flow.rb:655:9:655:19 | call to taint : | hash_flow.rb:653:9:656:7 | call to transform_values [element] : | | hash_flow.rb:657:11:657:14 | hash [element :a] : | hash_flow.rb:657:11:657:18 | ...[...] : | | hash_flow.rb:657:11:657:18 | ...[...] : | hash_flow.rb:657:10:657:19 | ( ... ) | | hash_flow.rb:658:11:658:11 | b [element] : | hash_flow.rb:658:11:658:15 | ...[...] : | | hash_flow.rb:658:11:658:15 | ...[...] : | hash_flow.rb:658:10:658:16 | ( ... ) | -| hash_flow.rb:665:15:665:25 | call to taint : | hash_flow.rb:669:5:669:8 | hash [element :a] : | -| hash_flow.rb:667:15:667:25 | call to taint : | hash_flow.rb:669:5:669:8 | hash [element :c] : | +| hash_flow.rb:664:5:664:8 | hash [element :a] : | hash_flow.rb:669:5:669:8 | hash [element :a] : | +| hash_flow.rb:664:5:664:8 | hash [element :c] : | hash_flow.rb:669:5:669:8 | hash [element :c] : | +| hash_flow.rb:665:15:665:25 | call to taint : | hash_flow.rb:664:5:664:8 | hash [element :a] : | +| hash_flow.rb:667:15:667:25 | call to taint : | hash_flow.rb:664:5:664:8 | hash [element :c] : | | hash_flow.rb:669:5:669:8 | [post] hash [element] : | hash_flow.rb:673:11:673:14 | hash [element] : | | hash_flow.rb:669:5:669:8 | hash [element :a] : | hash_flow.rb:669:32:669:36 | value : | | hash_flow.rb:669:5:669:8 | hash [element :c] : | hash_flow.rb:669:32:669:36 | value : | @@ -448,10 +567,18 @@ edges | hash_flow.rb:671:9:671:19 | call to taint : | hash_flow.rb:669:5:669:8 | [post] hash [element] : | | hash_flow.rb:673:11:673:14 | hash [element] : | hash_flow.rb:673:11:673:18 | ...[...] : | | hash_flow.rb:673:11:673:18 | ...[...] : | hash_flow.rb:673:10:673:19 | ( ... ) | -| hash_flow.rb:680:15:680:25 | call to taint : | hash_flow.rb:689:12:689:16 | hash1 [element :a] : | -| hash_flow.rb:682:15:682:25 | call to taint : | hash_flow.rb:689:12:689:16 | hash1 [element :c] : | -| hash_flow.rb:685:15:685:25 | call to taint : | hash_flow.rb:689:25:689:29 | hash2 [element :d] : | -| hash_flow.rb:687:15:687:25 | call to taint : | hash_flow.rb:689:25:689:29 | hash2 [element :f] : | +| hash_flow.rb:679:5:679:9 | hash1 [element :a] : | hash_flow.rb:689:12:689:16 | hash1 [element :a] : | +| hash_flow.rb:679:5:679:9 | hash1 [element :c] : | hash_flow.rb:689:12:689:16 | hash1 [element :c] : | +| hash_flow.rb:680:15:680:25 | call to taint : | hash_flow.rb:679:5:679:9 | hash1 [element :a] : | +| hash_flow.rb:682:15:682:25 | call to taint : | hash_flow.rb:679:5:679:9 | hash1 [element :c] : | +| hash_flow.rb:684:5:684:9 | hash2 [element :d] : | hash_flow.rb:689:25:689:29 | hash2 [element :d] : | +| hash_flow.rb:684:5:684:9 | hash2 [element :f] : | hash_flow.rb:689:25:689:29 | hash2 [element :f] : | +| hash_flow.rb:685:15:685:25 | call to taint : | hash_flow.rb:684:5:684:9 | hash2 [element :d] : | +| hash_flow.rb:687:15:687:25 | call to taint : | hash_flow.rb:684:5:684:9 | hash2 [element :f] : | +| hash_flow.rb:689:5:689:8 | hash [element :a] : | hash_flow.rb:694:11:694:14 | hash [element :a] : | +| hash_flow.rb:689:5:689:8 | hash [element :c] : | hash_flow.rb:696:11:696:14 | hash [element :c] : | +| hash_flow.rb:689:5:689:8 | hash [element :d] : | hash_flow.rb:697:11:697:14 | hash [element :d] : | +| hash_flow.rb:689:5:689:8 | hash [element :f] : | hash_flow.rb:699:11:699:14 | hash [element :f] : | | hash_flow.rb:689:12:689:16 | [post] hash1 [element :a] : | hash_flow.rb:701:11:701:15 | hash1 [element :a] : | | hash_flow.rb:689:12:689:16 | [post] hash1 [element :c] : | hash_flow.rb:703:11:703:15 | hash1 [element :c] : | | hash_flow.rb:689:12:689:16 | [post] hash1 [element :d] : | hash_flow.rb:704:11:704:15 | hash1 [element :d] : | @@ -464,10 +591,10 @@ edges | hash_flow.rb:689:12:689:16 | hash1 [element :c] : | hash_flow.rb:689:12:693:7 | call to update [element :c] : | | hash_flow.rb:689:12:689:16 | hash1 [element :c] : | hash_flow.rb:689:41:689:49 | old_value : | | hash_flow.rb:689:12:689:16 | hash1 [element :c] : | hash_flow.rb:689:52:689:60 | new_value : | -| hash_flow.rb:689:12:693:7 | call to update [element :a] : | hash_flow.rb:694:11:694:14 | hash [element :a] : | -| hash_flow.rb:689:12:693:7 | call to update [element :c] : | hash_flow.rb:696:11:696:14 | hash [element :c] : | -| hash_flow.rb:689:12:693:7 | call to update [element :d] : | hash_flow.rb:697:11:697:14 | hash [element :d] : | -| hash_flow.rb:689:12:693:7 | call to update [element :f] : | hash_flow.rb:699:11:699:14 | hash [element :f] : | +| hash_flow.rb:689:12:693:7 | call to update [element :a] : | hash_flow.rb:689:5:689:8 | hash [element :a] : | +| hash_flow.rb:689:12:693:7 | call to update [element :c] : | hash_flow.rb:689:5:689:8 | hash [element :c] : | +| hash_flow.rb:689:12:693:7 | call to update [element :d] : | hash_flow.rb:689:5:689:8 | hash [element :d] : | +| hash_flow.rb:689:12:693:7 | call to update [element :f] : | hash_flow.rb:689:5:689:8 | hash [element :f] : | | hash_flow.rb:689:25:689:29 | hash2 [element :d] : | hash_flow.rb:689:12:689:16 | [post] hash1 [element :d] : | | hash_flow.rb:689:25:689:29 | hash2 [element :d] : | hash_flow.rb:689:12:693:7 | call to update [element :d] : | | hash_flow.rb:689:25:689:29 | hash2 [element :d] : | hash_flow.rb:689:41:689:49 | old_value : | @@ -494,34 +621,50 @@ edges | hash_flow.rb:704:11:704:19 | ...[...] : | hash_flow.rb:704:10:704:20 | ( ... ) | | hash_flow.rb:706:11:706:15 | hash1 [element :f] : | hash_flow.rb:706:11:706:19 | ...[...] : | | hash_flow.rb:706:11:706:19 | ...[...] : | hash_flow.rb:706:10:706:20 | ( ... ) | -| hash_flow.rb:713:15:713:25 | call to taint : | hash_flow.rb:717:9:717:12 | hash [element :a] : | -| hash_flow.rb:715:15:715:25 | call to taint : | hash_flow.rb:717:9:717:12 | hash [element :c] : | +| hash_flow.rb:712:5:712:8 | hash [element :a] : | hash_flow.rb:717:9:717:12 | hash [element :a] : | +| hash_flow.rb:712:5:712:8 | hash [element :c] : | hash_flow.rb:717:9:717:12 | hash [element :c] : | +| hash_flow.rb:713:15:713:25 | call to taint : | hash_flow.rb:712:5:712:8 | hash [element :a] : | +| hash_flow.rb:715:15:715:25 | call to taint : | hash_flow.rb:712:5:712:8 | hash [element :c] : | +| hash_flow.rb:717:5:717:5 | a [element] : | hash_flow.rb:718:11:718:11 | a [element] : | | hash_flow.rb:717:9:717:12 | hash [element :a] : | hash_flow.rb:717:9:717:19 | call to values [element] : | | hash_flow.rb:717:9:717:12 | hash [element :c] : | hash_flow.rb:717:9:717:19 | call to values [element] : | -| hash_flow.rb:717:9:717:19 | call to values [element] : | hash_flow.rb:718:11:718:11 | a [element] : | +| hash_flow.rb:717:9:717:19 | call to values [element] : | hash_flow.rb:717:5:717:5 | a [element] : | | hash_flow.rb:718:11:718:11 | a [element] : | hash_flow.rb:718:11:718:14 | ...[...] : | | hash_flow.rb:718:11:718:14 | ...[...] : | hash_flow.rb:718:10:718:15 | ( ... ) | -| hash_flow.rb:725:15:725:25 | call to taint : | hash_flow.rb:729:9:729:12 | hash [element :a] : | -| hash_flow.rb:725:15:725:25 | call to taint : | hash_flow.rb:731:9:731:12 | hash [element :a] : | -| hash_flow.rb:727:15:727:25 | call to taint : | hash_flow.rb:731:9:731:12 | hash [element :c] : | +| hash_flow.rb:724:5:724:8 | hash [element :a] : | hash_flow.rb:729:9:729:12 | hash [element :a] : | +| hash_flow.rb:724:5:724:8 | hash [element :a] : | hash_flow.rb:731:9:731:12 | hash [element :a] : | +| hash_flow.rb:724:5:724:8 | hash [element :c] : | hash_flow.rb:731:9:731:12 | hash [element :c] : | +| hash_flow.rb:725:15:725:25 | call to taint : | hash_flow.rb:724:5:724:8 | hash [element :a] : | +| hash_flow.rb:727:15:727:25 | call to taint : | hash_flow.rb:724:5:724:8 | hash [element :c] : | +| hash_flow.rb:729:5:729:5 | b [element 0] : | hash_flow.rb:730:10:730:10 | b [element 0] : | | hash_flow.rb:729:9:729:12 | hash [element :a] : | hash_flow.rb:729:9:729:26 | call to values_at [element 0] : | -| hash_flow.rb:729:9:729:26 | call to values_at [element 0] : | hash_flow.rb:730:10:730:10 | b [element 0] : | +| hash_flow.rb:729:9:729:26 | call to values_at [element 0] : | hash_flow.rb:729:5:729:5 | b [element 0] : | | hash_flow.rb:730:10:730:10 | b [element 0] : | hash_flow.rb:730:10:730:13 | ...[...] | +| hash_flow.rb:731:5:731:5 | b [element] : | hash_flow.rb:732:10:732:10 | b [element] : | | hash_flow.rb:731:9:731:12 | hash [element :a] : | hash_flow.rb:731:9:731:31 | call to fetch_values [element] : | | hash_flow.rb:731:9:731:12 | hash [element :c] : | hash_flow.rb:731:9:731:31 | call to fetch_values [element] : | -| hash_flow.rb:731:9:731:31 | call to fetch_values [element] : | hash_flow.rb:732:10:732:10 | b [element] : | +| hash_flow.rb:731:9:731:31 | call to fetch_values [element] : | hash_flow.rb:731:5:731:5 | b [element] : | | hash_flow.rb:732:10:732:10 | b [element] : | hash_flow.rb:732:10:732:13 | ...[...] | -| hash_flow.rb:739:15:739:25 | call to taint : | hash_flow.rb:748:16:748:20 | hash1 [element :a] : | -| hash_flow.rb:741:15:741:25 | call to taint : | hash_flow.rb:748:16:748:20 | hash1 [element :c] : | -| hash_flow.rb:744:15:744:25 | call to taint : | hash_flow.rb:748:44:748:48 | hash2 [element :d] : | -| hash_flow.rb:746:15:746:25 | call to taint : | hash_flow.rb:748:44:748:48 | hash2 [element :f] : | -| hash_flow.rb:748:14:748:20 | ** ... [element :a] : | hash_flow.rb:749:10:749:13 | hash [element :a] : | -| hash_flow.rb:748:14:748:20 | ** ... [element :c] : | hash_flow.rb:751:10:751:13 | hash [element :c] : | +| hash_flow.rb:738:5:738:9 | hash1 [element :a] : | hash_flow.rb:748:16:748:20 | hash1 [element :a] : | +| hash_flow.rb:738:5:738:9 | hash1 [element :c] : | hash_flow.rb:748:16:748:20 | hash1 [element :c] : | +| hash_flow.rb:739:15:739:25 | call to taint : | hash_flow.rb:738:5:738:9 | hash1 [element :a] : | +| hash_flow.rb:741:15:741:25 | call to taint : | hash_flow.rb:738:5:738:9 | hash1 [element :c] : | +| hash_flow.rb:743:5:743:9 | hash2 [element :d] : | hash_flow.rb:748:44:748:48 | hash2 [element :d] : | +| hash_flow.rb:743:5:743:9 | hash2 [element :f] : | hash_flow.rb:748:44:748:48 | hash2 [element :f] : | +| hash_flow.rb:744:15:744:25 | call to taint : | hash_flow.rb:743:5:743:9 | hash2 [element :d] : | +| hash_flow.rb:746:15:746:25 | call to taint : | hash_flow.rb:743:5:743:9 | hash2 [element :f] : | +| hash_flow.rb:748:5:748:8 | hash [element :a] : | hash_flow.rb:749:10:749:13 | hash [element :a] : | +| hash_flow.rb:748:5:748:8 | hash [element :c] : | hash_flow.rb:751:10:751:13 | hash [element :c] : | +| hash_flow.rb:748:5:748:8 | hash [element :d] : | hash_flow.rb:752:10:752:13 | hash [element :d] : | +| hash_flow.rb:748:5:748:8 | hash [element :f] : | hash_flow.rb:754:10:754:13 | hash [element :f] : | +| hash_flow.rb:748:5:748:8 | hash [element :g] : | hash_flow.rb:755:10:755:13 | hash [element :g] : | +| hash_flow.rb:748:14:748:20 | ** ... [element :a] : | hash_flow.rb:748:5:748:8 | hash [element :a] : | +| hash_flow.rb:748:14:748:20 | ** ... [element :c] : | hash_flow.rb:748:5:748:8 | hash [element :c] : | | hash_flow.rb:748:16:748:20 | hash1 [element :a] : | hash_flow.rb:748:14:748:20 | ** ... [element :a] : | | hash_flow.rb:748:16:748:20 | hash1 [element :c] : | hash_flow.rb:748:14:748:20 | ** ... [element :c] : | -| hash_flow.rb:748:29:748:39 | call to taint : | hash_flow.rb:755:10:755:13 | hash [element :g] : | -| hash_flow.rb:748:42:748:48 | ** ... [element :d] : | hash_flow.rb:752:10:752:13 | hash [element :d] : | -| hash_flow.rb:748:42:748:48 | ** ... [element :f] : | hash_flow.rb:754:10:754:13 | hash [element :f] : | +| hash_flow.rb:748:29:748:39 | call to taint : | hash_flow.rb:748:5:748:8 | hash [element :g] : | +| hash_flow.rb:748:42:748:48 | ** ... [element :d] : | hash_flow.rb:748:5:748:8 | hash [element :d] : | +| hash_flow.rb:748:42:748:48 | ** ... [element :f] : | hash_flow.rb:748:5:748:8 | hash [element :f] : | | hash_flow.rb:748:44:748:48 | hash2 [element :d] : | hash_flow.rb:748:42:748:48 | ** ... [element :d] : | | hash_flow.rb:748:44:748:48 | hash2 [element :f] : | hash_flow.rb:748:42:748:48 | ** ... [element :f] : | | hash_flow.rb:749:10:749:13 | hash [element :a] : | hash_flow.rb:749:10:749:17 | ...[...] | @@ -529,33 +672,45 @@ edges | hash_flow.rb:752:10:752:13 | hash [element :d] : | hash_flow.rb:752:10:752:17 | ...[...] | | hash_flow.rb:754:10:754:13 | hash [element :f] : | hash_flow.rb:754:10:754:17 | ...[...] | | hash_flow.rb:755:10:755:13 | hash [element :g] : | hash_flow.rb:755:10:755:17 | ...[...] | -| hash_flow.rb:763:15:763:25 | call to taint : | hash_flow.rb:769:10:769:13 | hash [element :a] : | -| hash_flow.rb:765:15:765:25 | call to taint : | hash_flow.rb:771:10:771:13 | hash [element :c] : | -| hash_flow.rb:765:15:765:25 | call to taint : | hash_flow.rb:774:9:774:12 | hash [element :c] : | -| hash_flow.rb:766:15:766:25 | call to taint : | hash_flow.rb:772:10:772:13 | hash [element :d] : | +| hash_flow.rb:762:5:762:8 | hash [element :a] : | hash_flow.rb:769:10:769:13 | hash [element :a] : | +| hash_flow.rb:762:5:762:8 | hash [element :c] : | hash_flow.rb:771:10:771:13 | hash [element :c] : | +| hash_flow.rb:762:5:762:8 | hash [element :c] : | hash_flow.rb:774:9:774:12 | hash [element :c] : | +| hash_flow.rb:762:5:762:8 | hash [element :d] : | hash_flow.rb:772:10:772:13 | hash [element :d] : | +| hash_flow.rb:763:15:763:25 | call to taint : | hash_flow.rb:762:5:762:8 | hash [element :a] : | +| hash_flow.rb:765:15:765:25 | call to taint : | hash_flow.rb:762:5:762:8 | hash [element :c] : | +| hash_flow.rb:766:15:766:25 | call to taint : | hash_flow.rb:762:5:762:8 | hash [element :d] : | | hash_flow.rb:769:10:769:13 | hash [element :a] : | hash_flow.rb:769:10:769:17 | ...[...] | | hash_flow.rb:771:10:771:13 | hash [element :c] : | hash_flow.rb:771:10:771:17 | ...[...] | | hash_flow.rb:772:10:772:13 | hash [element :d] : | hash_flow.rb:772:10:772:17 | ...[...] | +| hash_flow.rb:774:5:774:5 | x [element :c] : | hash_flow.rb:778:10:778:10 | x [element :c] : | | hash_flow.rb:774:9:774:12 | [post] hash [element :c] : | hash_flow.rb:783:10:783:13 | hash [element :c] : | | hash_flow.rb:774:9:774:12 | hash [element :c] : | hash_flow.rb:774:9:774:12 | [post] hash [element :c] : | | hash_flow.rb:774:9:774:12 | hash [element :c] : | hash_flow.rb:774:9:774:31 | call to except! [element :c] : | -| hash_flow.rb:774:9:774:31 | call to except! [element :c] : | hash_flow.rb:778:10:778:10 | x [element :c] : | +| hash_flow.rb:774:9:774:31 | call to except! [element :c] : | hash_flow.rb:774:5:774:5 | x [element :c] : | | hash_flow.rb:778:10:778:10 | x [element :c] : | hash_flow.rb:778:10:778:14 | ...[...] | | hash_flow.rb:783:10:783:13 | hash [element :c] : | hash_flow.rb:783:10:783:17 | ...[...] | -| hash_flow.rb:791:15:791:25 | call to taint : | hash_flow.rb:800:12:800:16 | hash1 [element :a] : | -| hash_flow.rb:793:15:793:25 | call to taint : | hash_flow.rb:800:12:800:16 | hash1 [element :c] : | -| hash_flow.rb:796:15:796:25 | call to taint : | hash_flow.rb:800:29:800:33 | hash2 [element :d] : | -| hash_flow.rb:798:15:798:25 | call to taint : | hash_flow.rb:800:29:800:33 | hash2 [element :f] : | +| hash_flow.rb:790:5:790:9 | hash1 [element :a] : | hash_flow.rb:800:12:800:16 | hash1 [element :a] : | +| hash_flow.rb:790:5:790:9 | hash1 [element :c] : | hash_flow.rb:800:12:800:16 | hash1 [element :c] : | +| hash_flow.rb:791:15:791:25 | call to taint : | hash_flow.rb:790:5:790:9 | hash1 [element :a] : | +| hash_flow.rb:793:15:793:25 | call to taint : | hash_flow.rb:790:5:790:9 | hash1 [element :c] : | +| hash_flow.rb:795:5:795:9 | hash2 [element :d] : | hash_flow.rb:800:29:800:33 | hash2 [element :d] : | +| hash_flow.rb:795:5:795:9 | hash2 [element :f] : | hash_flow.rb:800:29:800:33 | hash2 [element :f] : | +| hash_flow.rb:796:15:796:25 | call to taint : | hash_flow.rb:795:5:795:9 | hash2 [element :d] : | +| hash_flow.rb:798:15:798:25 | call to taint : | hash_flow.rb:795:5:795:9 | hash2 [element :f] : | +| hash_flow.rb:800:5:800:8 | hash [element :a] : | hash_flow.rb:805:11:805:14 | hash [element :a] : | +| hash_flow.rb:800:5:800:8 | hash [element :c] : | hash_flow.rb:807:11:807:14 | hash [element :c] : | +| hash_flow.rb:800:5:800:8 | hash [element :d] : | hash_flow.rb:808:11:808:14 | hash [element :d] : | +| hash_flow.rb:800:5:800:8 | hash [element :f] : | hash_flow.rb:810:11:810:14 | hash [element :f] : | | hash_flow.rb:800:12:800:16 | hash1 [element :a] : | hash_flow.rb:800:12:804:7 | call to deep_merge [element :a] : | | hash_flow.rb:800:12:800:16 | hash1 [element :a] : | hash_flow.rb:800:45:800:53 | old_value : | | hash_flow.rb:800:12:800:16 | hash1 [element :a] : | hash_flow.rb:800:56:800:64 | new_value : | | hash_flow.rb:800:12:800:16 | hash1 [element :c] : | hash_flow.rb:800:12:804:7 | call to deep_merge [element :c] : | | hash_flow.rb:800:12:800:16 | hash1 [element :c] : | hash_flow.rb:800:45:800:53 | old_value : | | hash_flow.rb:800:12:800:16 | hash1 [element :c] : | hash_flow.rb:800:56:800:64 | new_value : | -| hash_flow.rb:800:12:804:7 | call to deep_merge [element :a] : | hash_flow.rb:805:11:805:14 | hash [element :a] : | -| hash_flow.rb:800:12:804:7 | call to deep_merge [element :c] : | hash_flow.rb:807:11:807:14 | hash [element :c] : | -| hash_flow.rb:800:12:804:7 | call to deep_merge [element :d] : | hash_flow.rb:808:11:808:14 | hash [element :d] : | -| hash_flow.rb:800:12:804:7 | call to deep_merge [element :f] : | hash_flow.rb:810:11:810:14 | hash [element :f] : | +| hash_flow.rb:800:12:804:7 | call to deep_merge [element :a] : | hash_flow.rb:800:5:800:8 | hash [element :a] : | +| hash_flow.rb:800:12:804:7 | call to deep_merge [element :c] : | hash_flow.rb:800:5:800:8 | hash [element :c] : | +| hash_flow.rb:800:12:804:7 | call to deep_merge [element :d] : | hash_flow.rb:800:5:800:8 | hash [element :d] : | +| hash_flow.rb:800:12:804:7 | call to deep_merge [element :f] : | hash_flow.rb:800:5:800:8 | hash [element :f] : | | hash_flow.rb:800:29:800:33 | hash2 [element :d] : | hash_flow.rb:800:12:804:7 | call to deep_merge [element :d] : | | hash_flow.rb:800:29:800:33 | hash2 [element :d] : | hash_flow.rb:800:45:800:53 | old_value : | | hash_flow.rb:800:29:800:33 | hash2 [element :d] : | hash_flow.rb:800:56:800:64 | new_value : | @@ -572,10 +727,18 @@ edges | hash_flow.rb:808:11:808:18 | ...[...] : | hash_flow.rb:808:10:808:19 | ( ... ) | | hash_flow.rb:810:11:810:14 | hash [element :f] : | hash_flow.rb:810:11:810:18 | ...[...] : | | hash_flow.rb:810:11:810:18 | ...[...] : | hash_flow.rb:810:10:810:19 | ( ... ) | -| hash_flow.rb:817:15:817:25 | call to taint : | hash_flow.rb:826:12:826:16 | hash1 [element :a] : | -| hash_flow.rb:819:15:819:25 | call to taint : | hash_flow.rb:826:12:826:16 | hash1 [element :c] : | -| hash_flow.rb:822:15:822:25 | call to taint : | hash_flow.rb:826:30:826:34 | hash2 [element :d] : | -| hash_flow.rb:824:15:824:25 | call to taint : | hash_flow.rb:826:30:826:34 | hash2 [element :f] : | +| hash_flow.rb:816:5:816:9 | hash1 [element :a] : | hash_flow.rb:826:12:826:16 | hash1 [element :a] : | +| hash_flow.rb:816:5:816:9 | hash1 [element :c] : | hash_flow.rb:826:12:826:16 | hash1 [element :c] : | +| hash_flow.rb:817:15:817:25 | call to taint : | hash_flow.rb:816:5:816:9 | hash1 [element :a] : | +| hash_flow.rb:819:15:819:25 | call to taint : | hash_flow.rb:816:5:816:9 | hash1 [element :c] : | +| hash_flow.rb:821:5:821:9 | hash2 [element :d] : | hash_flow.rb:826:30:826:34 | hash2 [element :d] : | +| hash_flow.rb:821:5:821:9 | hash2 [element :f] : | hash_flow.rb:826:30:826:34 | hash2 [element :f] : | +| hash_flow.rb:822:15:822:25 | call to taint : | hash_flow.rb:821:5:821:9 | hash2 [element :d] : | +| hash_flow.rb:824:15:824:25 | call to taint : | hash_flow.rb:821:5:821:9 | hash2 [element :f] : | +| hash_flow.rb:826:5:826:8 | hash [element :a] : | hash_flow.rb:831:11:831:14 | hash [element :a] : | +| hash_flow.rb:826:5:826:8 | hash [element :c] : | hash_flow.rb:833:11:833:14 | hash [element :c] : | +| hash_flow.rb:826:5:826:8 | hash [element :d] : | hash_flow.rb:834:11:834:14 | hash [element :d] : | +| hash_flow.rb:826:5:826:8 | hash [element :f] : | hash_flow.rb:836:11:836:14 | hash [element :f] : | | hash_flow.rb:826:12:826:16 | [post] hash1 [element :a] : | hash_flow.rb:838:11:838:15 | hash1 [element :a] : | | hash_flow.rb:826:12:826:16 | [post] hash1 [element :c] : | hash_flow.rb:840:11:840:15 | hash1 [element :c] : | | hash_flow.rb:826:12:826:16 | [post] hash1 [element :d] : | hash_flow.rb:841:11:841:15 | hash1 [element :d] : | @@ -588,10 +751,10 @@ edges | hash_flow.rb:826:12:826:16 | hash1 [element :c] : | hash_flow.rb:826:12:830:7 | call to deep_merge! [element :c] : | | hash_flow.rb:826:12:826:16 | hash1 [element :c] : | hash_flow.rb:826:46:826:54 | old_value : | | hash_flow.rb:826:12:826:16 | hash1 [element :c] : | hash_flow.rb:826:57:826:65 | new_value : | -| hash_flow.rb:826:12:830:7 | call to deep_merge! [element :a] : | hash_flow.rb:831:11:831:14 | hash [element :a] : | -| hash_flow.rb:826:12:830:7 | call to deep_merge! [element :c] : | hash_flow.rb:833:11:833:14 | hash [element :c] : | -| hash_flow.rb:826:12:830:7 | call to deep_merge! [element :d] : | hash_flow.rb:834:11:834:14 | hash [element :d] : | -| hash_flow.rb:826:12:830:7 | call to deep_merge! [element :f] : | hash_flow.rb:836:11:836:14 | hash [element :f] : | +| hash_flow.rb:826:12:830:7 | call to deep_merge! [element :a] : | hash_flow.rb:826:5:826:8 | hash [element :a] : | +| hash_flow.rb:826:12:830:7 | call to deep_merge! [element :c] : | hash_flow.rb:826:5:826:8 | hash [element :c] : | +| hash_flow.rb:826:12:830:7 | call to deep_merge! [element :d] : | hash_flow.rb:826:5:826:8 | hash [element :d] : | +| hash_flow.rb:826:12:830:7 | call to deep_merge! [element :f] : | hash_flow.rb:826:5:826:8 | hash [element :f] : | | hash_flow.rb:826:30:826:34 | hash2 [element :d] : | hash_flow.rb:826:12:826:16 | [post] hash1 [element :d] : | | hash_flow.rb:826:30:826:34 | hash2 [element :d] : | hash_flow.rb:826:12:830:7 | call to deep_merge! [element :d] : | | hash_flow.rb:826:30:826:34 | hash2 [element :d] : | hash_flow.rb:826:46:826:54 | old_value : | @@ -618,20 +781,28 @@ edges | hash_flow.rb:841:11:841:19 | ...[...] : | hash_flow.rb:841:10:841:20 | ( ... ) | | hash_flow.rb:843:11:843:15 | hash1 [element :f] : | hash_flow.rb:843:11:843:19 | ...[...] : | | hash_flow.rb:843:11:843:19 | ...[...] : | hash_flow.rb:843:10:843:20 | ( ... ) | -| hash_flow.rb:850:12:850:22 | call to taint : | hash_flow.rb:860:13:860:17 | hash1 [element :a] : | -| hash_flow.rb:850:12:850:22 | call to taint : | hash_flow.rb:869:13:869:17 | hash1 [element :a] : | -| hash_flow.rb:852:12:852:22 | call to taint : | hash_flow.rb:860:13:860:17 | hash1 [element :c] : | -| hash_flow.rb:852:12:852:22 | call to taint : | hash_flow.rb:869:13:869:17 | hash1 [element :c] : | -| hash_flow.rb:855:12:855:22 | call to taint : | hash_flow.rb:860:33:860:37 | hash2 [element :d] : | -| hash_flow.rb:855:12:855:22 | call to taint : | hash_flow.rb:869:33:869:37 | hash2 [element :d] : | -| hash_flow.rb:857:12:857:22 | call to taint : | hash_flow.rb:860:33:860:37 | hash2 [element :f] : | -| hash_flow.rb:857:12:857:22 | call to taint : | hash_flow.rb:869:33:869:37 | hash2 [element :f] : | +| hash_flow.rb:849:5:849:9 | hash1 [element :a] : | hash_flow.rb:860:13:860:17 | hash1 [element :a] : | +| hash_flow.rb:849:5:849:9 | hash1 [element :a] : | hash_flow.rb:869:13:869:17 | hash1 [element :a] : | +| hash_flow.rb:849:5:849:9 | hash1 [element :c] : | hash_flow.rb:860:13:860:17 | hash1 [element :c] : | +| hash_flow.rb:849:5:849:9 | hash1 [element :c] : | hash_flow.rb:869:13:869:17 | hash1 [element :c] : | +| hash_flow.rb:850:12:850:22 | call to taint : | hash_flow.rb:849:5:849:9 | hash1 [element :a] : | +| hash_flow.rb:852:12:852:22 | call to taint : | hash_flow.rb:849:5:849:9 | hash1 [element :c] : | +| hash_flow.rb:854:5:854:9 | hash2 [element :d] : | hash_flow.rb:860:33:860:37 | hash2 [element :d] : | +| hash_flow.rb:854:5:854:9 | hash2 [element :d] : | hash_flow.rb:869:33:869:37 | hash2 [element :d] : | +| hash_flow.rb:854:5:854:9 | hash2 [element :f] : | hash_flow.rb:860:33:860:37 | hash2 [element :f] : | +| hash_flow.rb:854:5:854:9 | hash2 [element :f] : | hash_flow.rb:869:33:869:37 | hash2 [element :f] : | +| hash_flow.rb:855:12:855:22 | call to taint : | hash_flow.rb:854:5:854:9 | hash2 [element :d] : | +| hash_flow.rb:857:12:857:22 | call to taint : | hash_flow.rb:854:5:854:9 | hash2 [element :f] : | +| hash_flow.rb:860:5:860:9 | hash3 [element :a] : | hash_flow.rb:861:11:861:15 | hash3 [element :a] : | +| hash_flow.rb:860:5:860:9 | hash3 [element :c] : | hash_flow.rb:863:11:863:15 | hash3 [element :c] : | +| hash_flow.rb:860:5:860:9 | hash3 [element :d] : | hash_flow.rb:864:11:864:15 | hash3 [element :d] : | +| hash_flow.rb:860:5:860:9 | hash3 [element :f] : | hash_flow.rb:866:11:866:15 | hash3 [element :f] : | | hash_flow.rb:860:13:860:17 | hash1 [element :a] : | hash_flow.rb:860:13:860:38 | call to reverse_merge [element :a] : | | hash_flow.rb:860:13:860:17 | hash1 [element :c] : | hash_flow.rb:860:13:860:38 | call to reverse_merge [element :c] : | -| hash_flow.rb:860:13:860:38 | call to reverse_merge [element :a] : | hash_flow.rb:861:11:861:15 | hash3 [element :a] : | -| hash_flow.rb:860:13:860:38 | call to reverse_merge [element :c] : | hash_flow.rb:863:11:863:15 | hash3 [element :c] : | -| hash_flow.rb:860:13:860:38 | call to reverse_merge [element :d] : | hash_flow.rb:864:11:864:15 | hash3 [element :d] : | -| hash_flow.rb:860:13:860:38 | call to reverse_merge [element :f] : | hash_flow.rb:866:11:866:15 | hash3 [element :f] : | +| hash_flow.rb:860:13:860:38 | call to reverse_merge [element :a] : | hash_flow.rb:860:5:860:9 | hash3 [element :a] : | +| hash_flow.rb:860:13:860:38 | call to reverse_merge [element :c] : | hash_flow.rb:860:5:860:9 | hash3 [element :c] : | +| hash_flow.rb:860:13:860:38 | call to reverse_merge [element :d] : | hash_flow.rb:860:5:860:9 | hash3 [element :d] : | +| hash_flow.rb:860:13:860:38 | call to reverse_merge [element :f] : | hash_flow.rb:860:5:860:9 | hash3 [element :f] : | | hash_flow.rb:860:33:860:37 | hash2 [element :d] : | hash_flow.rb:860:13:860:38 | call to reverse_merge [element :d] : | | hash_flow.rb:860:33:860:37 | hash2 [element :f] : | hash_flow.rb:860:13:860:38 | call to reverse_merge [element :f] : | | hash_flow.rb:861:11:861:15 | hash3 [element :a] : | hash_flow.rb:861:11:861:19 | ...[...] : | @@ -642,12 +813,16 @@ edges | hash_flow.rb:864:11:864:19 | ...[...] : | hash_flow.rb:864:10:864:20 | ( ... ) | | hash_flow.rb:866:11:866:15 | hash3 [element :f] : | hash_flow.rb:866:11:866:19 | ...[...] : | | hash_flow.rb:866:11:866:19 | ...[...] : | hash_flow.rb:866:10:866:20 | ( ... ) | +| hash_flow.rb:869:5:869:9 | hash4 [element :a] : | hash_flow.rb:870:11:870:15 | hash4 [element :a] : | +| hash_flow.rb:869:5:869:9 | hash4 [element :c] : | hash_flow.rb:872:11:872:15 | hash4 [element :c] : | +| hash_flow.rb:869:5:869:9 | hash4 [element :d] : | hash_flow.rb:873:11:873:15 | hash4 [element :d] : | +| hash_flow.rb:869:5:869:9 | hash4 [element :f] : | hash_flow.rb:875:11:875:15 | hash4 [element :f] : | | hash_flow.rb:869:13:869:17 | hash1 [element :a] : | hash_flow.rb:869:13:869:38 | call to with_defaults [element :a] : | | hash_flow.rb:869:13:869:17 | hash1 [element :c] : | hash_flow.rb:869:13:869:38 | call to with_defaults [element :c] : | -| hash_flow.rb:869:13:869:38 | call to with_defaults [element :a] : | hash_flow.rb:870:11:870:15 | hash4 [element :a] : | -| hash_flow.rb:869:13:869:38 | call to with_defaults [element :c] : | hash_flow.rb:872:11:872:15 | hash4 [element :c] : | -| hash_flow.rb:869:13:869:38 | call to with_defaults [element :d] : | hash_flow.rb:873:11:873:15 | hash4 [element :d] : | -| hash_flow.rb:869:13:869:38 | call to with_defaults [element :f] : | hash_flow.rb:875:11:875:15 | hash4 [element :f] : | +| hash_flow.rb:869:13:869:38 | call to with_defaults [element :a] : | hash_flow.rb:869:5:869:9 | hash4 [element :a] : | +| hash_flow.rb:869:13:869:38 | call to with_defaults [element :c] : | hash_flow.rb:869:5:869:9 | hash4 [element :c] : | +| hash_flow.rb:869:13:869:38 | call to with_defaults [element :d] : | hash_flow.rb:869:5:869:9 | hash4 [element :d] : | +| hash_flow.rb:869:13:869:38 | call to with_defaults [element :f] : | hash_flow.rb:869:5:869:9 | hash4 [element :f] : | | hash_flow.rb:869:33:869:37 | hash2 [element :d] : | hash_flow.rb:869:13:869:38 | call to with_defaults [element :d] : | | hash_flow.rb:869:33:869:37 | hash2 [element :f] : | hash_flow.rb:869:13:869:38 | call to with_defaults [element :f] : | | hash_flow.rb:870:11:870:15 | hash4 [element :a] : | hash_flow.rb:870:11:870:19 | ...[...] : | @@ -658,10 +833,18 @@ edges | hash_flow.rb:873:11:873:19 | ...[...] : | hash_flow.rb:873:10:873:20 | ( ... ) | | hash_flow.rb:875:11:875:15 | hash4 [element :f] : | hash_flow.rb:875:11:875:19 | ...[...] : | | hash_flow.rb:875:11:875:19 | ...[...] : | hash_flow.rb:875:10:875:20 | ( ... ) | -| hash_flow.rb:882:12:882:22 | call to taint : | hash_flow.rb:892:12:892:16 | hash1 [element :a] : | -| hash_flow.rb:884:12:884:22 | call to taint : | hash_flow.rb:892:12:892:16 | hash1 [element :c] : | -| hash_flow.rb:887:12:887:22 | call to taint : | hash_flow.rb:892:33:892:37 | hash2 [element :d] : | -| hash_flow.rb:889:12:889:22 | call to taint : | hash_flow.rb:892:33:892:37 | hash2 [element :f] : | +| hash_flow.rb:881:5:881:9 | hash1 [element :a] : | hash_flow.rb:892:12:892:16 | hash1 [element :a] : | +| hash_flow.rb:881:5:881:9 | hash1 [element :c] : | hash_flow.rb:892:12:892:16 | hash1 [element :c] : | +| hash_flow.rb:882:12:882:22 | call to taint : | hash_flow.rb:881:5:881:9 | hash1 [element :a] : | +| hash_flow.rb:884:12:884:22 | call to taint : | hash_flow.rb:881:5:881:9 | hash1 [element :c] : | +| hash_flow.rb:886:5:886:9 | hash2 [element :d] : | hash_flow.rb:892:33:892:37 | hash2 [element :d] : | +| hash_flow.rb:886:5:886:9 | hash2 [element :f] : | hash_flow.rb:892:33:892:37 | hash2 [element :f] : | +| hash_flow.rb:887:12:887:22 | call to taint : | hash_flow.rb:886:5:886:9 | hash2 [element :d] : | +| hash_flow.rb:889:12:889:22 | call to taint : | hash_flow.rb:886:5:886:9 | hash2 [element :f] : | +| hash_flow.rb:892:5:892:8 | hash [element :a] : | hash_flow.rb:893:11:893:14 | hash [element :a] : | +| hash_flow.rb:892:5:892:8 | hash [element :c] : | hash_flow.rb:895:11:895:14 | hash [element :c] : | +| hash_flow.rb:892:5:892:8 | hash [element :d] : | hash_flow.rb:896:11:896:14 | hash [element :d] : | +| hash_flow.rb:892:5:892:8 | hash [element :f] : | hash_flow.rb:898:11:898:14 | hash [element :f] : | | hash_flow.rb:892:12:892:16 | [post] hash1 [element :a] : | hash_flow.rb:900:11:900:15 | hash1 [element :a] : | | hash_flow.rb:892:12:892:16 | [post] hash1 [element :c] : | hash_flow.rb:902:11:902:15 | hash1 [element :c] : | | hash_flow.rb:892:12:892:16 | [post] hash1 [element :d] : | hash_flow.rb:903:11:903:15 | hash1 [element :d] : | @@ -670,10 +853,10 @@ edges | hash_flow.rb:892:12:892:16 | hash1 [element :a] : | hash_flow.rb:892:12:892:38 | call to reverse_merge! [element :a] : | | hash_flow.rb:892:12:892:16 | hash1 [element :c] : | hash_flow.rb:892:12:892:16 | [post] hash1 [element :c] : | | hash_flow.rb:892:12:892:16 | hash1 [element :c] : | hash_flow.rb:892:12:892:38 | call to reverse_merge! [element :c] : | -| hash_flow.rb:892:12:892:38 | call to reverse_merge! [element :a] : | hash_flow.rb:893:11:893:14 | hash [element :a] : | -| hash_flow.rb:892:12:892:38 | call to reverse_merge! [element :c] : | hash_flow.rb:895:11:895:14 | hash [element :c] : | -| hash_flow.rb:892:12:892:38 | call to reverse_merge! [element :d] : | hash_flow.rb:896:11:896:14 | hash [element :d] : | -| hash_flow.rb:892:12:892:38 | call to reverse_merge! [element :f] : | hash_flow.rb:898:11:898:14 | hash [element :f] : | +| hash_flow.rb:892:12:892:38 | call to reverse_merge! [element :a] : | hash_flow.rb:892:5:892:8 | hash [element :a] : | +| hash_flow.rb:892:12:892:38 | call to reverse_merge! [element :c] : | hash_flow.rb:892:5:892:8 | hash [element :c] : | +| hash_flow.rb:892:12:892:38 | call to reverse_merge! [element :d] : | hash_flow.rb:892:5:892:8 | hash [element :d] : | +| hash_flow.rb:892:12:892:38 | call to reverse_merge! [element :f] : | hash_flow.rb:892:5:892:8 | hash [element :f] : | | hash_flow.rb:892:33:892:37 | hash2 [element :d] : | hash_flow.rb:892:12:892:16 | [post] hash1 [element :d] : | | hash_flow.rb:892:33:892:37 | hash2 [element :d] : | hash_flow.rb:892:12:892:38 | call to reverse_merge! [element :d] : | | hash_flow.rb:892:33:892:37 | hash2 [element :f] : | hash_flow.rb:892:12:892:16 | [post] hash1 [element :f] : | @@ -694,10 +877,18 @@ edges | hash_flow.rb:903:11:903:19 | ...[...] : | hash_flow.rb:903:10:903:20 | ( ... ) | | hash_flow.rb:905:11:905:15 | hash1 [element :f] : | hash_flow.rb:905:11:905:19 | ...[...] : | | hash_flow.rb:905:11:905:19 | ...[...] : | hash_flow.rb:905:10:905:20 | ( ... ) | -| hash_flow.rb:912:12:912:22 | call to taint : | hash_flow.rb:922:12:922:16 | hash1 [element :a] : | -| hash_flow.rb:914:12:914:22 | call to taint : | hash_flow.rb:922:12:922:16 | hash1 [element :c] : | -| hash_flow.rb:917:12:917:22 | call to taint : | hash_flow.rb:922:33:922:37 | hash2 [element :d] : | -| hash_flow.rb:919:12:919:22 | call to taint : | hash_flow.rb:922:33:922:37 | hash2 [element :f] : | +| hash_flow.rb:911:5:911:9 | hash1 [element :a] : | hash_flow.rb:922:12:922:16 | hash1 [element :a] : | +| hash_flow.rb:911:5:911:9 | hash1 [element :c] : | hash_flow.rb:922:12:922:16 | hash1 [element :c] : | +| hash_flow.rb:912:12:912:22 | call to taint : | hash_flow.rb:911:5:911:9 | hash1 [element :a] : | +| hash_flow.rb:914:12:914:22 | call to taint : | hash_flow.rb:911:5:911:9 | hash1 [element :c] : | +| hash_flow.rb:916:5:916:9 | hash2 [element :d] : | hash_flow.rb:922:33:922:37 | hash2 [element :d] : | +| hash_flow.rb:916:5:916:9 | hash2 [element :f] : | hash_flow.rb:922:33:922:37 | hash2 [element :f] : | +| hash_flow.rb:917:12:917:22 | call to taint : | hash_flow.rb:916:5:916:9 | hash2 [element :d] : | +| hash_flow.rb:919:12:919:22 | call to taint : | hash_flow.rb:916:5:916:9 | hash2 [element :f] : | +| hash_flow.rb:922:5:922:8 | hash [element :a] : | hash_flow.rb:923:11:923:14 | hash [element :a] : | +| hash_flow.rb:922:5:922:8 | hash [element :c] : | hash_flow.rb:925:11:925:14 | hash [element :c] : | +| hash_flow.rb:922:5:922:8 | hash [element :d] : | hash_flow.rb:926:11:926:14 | hash [element :d] : | +| hash_flow.rb:922:5:922:8 | hash [element :f] : | hash_flow.rb:928:11:928:14 | hash [element :f] : | | hash_flow.rb:922:12:922:16 | [post] hash1 [element :a] : | hash_flow.rb:930:11:930:15 | hash1 [element :a] : | | hash_flow.rb:922:12:922:16 | [post] hash1 [element :c] : | hash_flow.rb:932:11:932:15 | hash1 [element :c] : | | hash_flow.rb:922:12:922:16 | [post] hash1 [element :d] : | hash_flow.rb:933:11:933:15 | hash1 [element :d] : | @@ -706,10 +897,10 @@ edges | hash_flow.rb:922:12:922:16 | hash1 [element :a] : | hash_flow.rb:922:12:922:38 | call to with_defaults! [element :a] : | | hash_flow.rb:922:12:922:16 | hash1 [element :c] : | hash_flow.rb:922:12:922:16 | [post] hash1 [element :c] : | | hash_flow.rb:922:12:922:16 | hash1 [element :c] : | hash_flow.rb:922:12:922:38 | call to with_defaults! [element :c] : | -| hash_flow.rb:922:12:922:38 | call to with_defaults! [element :a] : | hash_flow.rb:923:11:923:14 | hash [element :a] : | -| hash_flow.rb:922:12:922:38 | call to with_defaults! [element :c] : | hash_flow.rb:925:11:925:14 | hash [element :c] : | -| hash_flow.rb:922:12:922:38 | call to with_defaults! [element :d] : | hash_flow.rb:926:11:926:14 | hash [element :d] : | -| hash_flow.rb:922:12:922:38 | call to with_defaults! [element :f] : | hash_flow.rb:928:11:928:14 | hash [element :f] : | +| hash_flow.rb:922:12:922:38 | call to with_defaults! [element :a] : | hash_flow.rb:922:5:922:8 | hash [element :a] : | +| hash_flow.rb:922:12:922:38 | call to with_defaults! [element :c] : | hash_flow.rb:922:5:922:8 | hash [element :c] : | +| hash_flow.rb:922:12:922:38 | call to with_defaults! [element :d] : | hash_flow.rb:922:5:922:8 | hash [element :d] : | +| hash_flow.rb:922:12:922:38 | call to with_defaults! [element :f] : | hash_flow.rb:922:5:922:8 | hash [element :f] : | | hash_flow.rb:922:33:922:37 | hash2 [element :d] : | hash_flow.rb:922:12:922:16 | [post] hash1 [element :d] : | | hash_flow.rb:922:33:922:37 | hash2 [element :d] : | hash_flow.rb:922:12:922:38 | call to with_defaults! [element :d] : | | hash_flow.rb:922:33:922:37 | hash2 [element :f] : | hash_flow.rb:922:12:922:16 | [post] hash1 [element :f] : | @@ -730,10 +921,18 @@ edges | hash_flow.rb:933:11:933:19 | ...[...] : | hash_flow.rb:933:10:933:20 | ( ... ) | | hash_flow.rb:935:11:935:15 | hash1 [element :f] : | hash_flow.rb:935:11:935:19 | ...[...] : | | hash_flow.rb:935:11:935:19 | ...[...] : | hash_flow.rb:935:10:935:20 | ( ... ) | -| hash_flow.rb:942:12:942:22 | call to taint : | hash_flow.rb:952:12:952:16 | hash1 [element :a] : | -| hash_flow.rb:944:12:944:22 | call to taint : | hash_flow.rb:952:12:952:16 | hash1 [element :c] : | -| hash_flow.rb:947:12:947:22 | call to taint : | hash_flow.rb:952:33:952:37 | hash2 [element :d] : | -| hash_flow.rb:949:12:949:22 | call to taint : | hash_flow.rb:952:33:952:37 | hash2 [element :f] : | +| hash_flow.rb:941:5:941:9 | hash1 [element :a] : | hash_flow.rb:952:12:952:16 | hash1 [element :a] : | +| hash_flow.rb:941:5:941:9 | hash1 [element :c] : | hash_flow.rb:952:12:952:16 | hash1 [element :c] : | +| hash_flow.rb:942:12:942:22 | call to taint : | hash_flow.rb:941:5:941:9 | hash1 [element :a] : | +| hash_flow.rb:944:12:944:22 | call to taint : | hash_flow.rb:941:5:941:9 | hash1 [element :c] : | +| hash_flow.rb:946:5:946:9 | hash2 [element :d] : | hash_flow.rb:952:33:952:37 | hash2 [element :d] : | +| hash_flow.rb:946:5:946:9 | hash2 [element :f] : | hash_flow.rb:952:33:952:37 | hash2 [element :f] : | +| hash_flow.rb:947:12:947:22 | call to taint : | hash_flow.rb:946:5:946:9 | hash2 [element :d] : | +| hash_flow.rb:949:12:949:22 | call to taint : | hash_flow.rb:946:5:946:9 | hash2 [element :f] : | +| hash_flow.rb:952:5:952:8 | hash [element :a] : | hash_flow.rb:953:11:953:14 | hash [element :a] : | +| hash_flow.rb:952:5:952:8 | hash [element :c] : | hash_flow.rb:955:11:955:14 | hash [element :c] : | +| hash_flow.rb:952:5:952:8 | hash [element :d] : | hash_flow.rb:956:11:956:14 | hash [element :d] : | +| hash_flow.rb:952:5:952:8 | hash [element :f] : | hash_flow.rb:958:11:958:14 | hash [element :f] : | | hash_flow.rb:952:12:952:16 | [post] hash1 [element :a] : | hash_flow.rb:960:11:960:15 | hash1 [element :a] : | | hash_flow.rb:952:12:952:16 | [post] hash1 [element :c] : | hash_flow.rb:962:11:962:15 | hash1 [element :c] : | | hash_flow.rb:952:12:952:16 | [post] hash1 [element :d] : | hash_flow.rb:963:11:963:15 | hash1 [element :d] : | @@ -742,10 +941,10 @@ edges | hash_flow.rb:952:12:952:16 | hash1 [element :a] : | hash_flow.rb:952:12:952:38 | call to with_defaults! [element :a] : | | hash_flow.rb:952:12:952:16 | hash1 [element :c] : | hash_flow.rb:952:12:952:16 | [post] hash1 [element :c] : | | hash_flow.rb:952:12:952:16 | hash1 [element :c] : | hash_flow.rb:952:12:952:38 | call to with_defaults! [element :c] : | -| hash_flow.rb:952:12:952:38 | call to with_defaults! [element :a] : | hash_flow.rb:953:11:953:14 | hash [element :a] : | -| hash_flow.rb:952:12:952:38 | call to with_defaults! [element :c] : | hash_flow.rb:955:11:955:14 | hash [element :c] : | -| hash_flow.rb:952:12:952:38 | call to with_defaults! [element :d] : | hash_flow.rb:956:11:956:14 | hash [element :d] : | -| hash_flow.rb:952:12:952:38 | call to with_defaults! [element :f] : | hash_flow.rb:958:11:958:14 | hash [element :f] : | +| hash_flow.rb:952:12:952:38 | call to with_defaults! [element :a] : | hash_flow.rb:952:5:952:8 | hash [element :a] : | +| hash_flow.rb:952:12:952:38 | call to with_defaults! [element :c] : | hash_flow.rb:952:5:952:8 | hash [element :c] : | +| hash_flow.rb:952:12:952:38 | call to with_defaults! [element :d] : | hash_flow.rb:952:5:952:8 | hash [element :d] : | +| hash_flow.rb:952:12:952:38 | call to with_defaults! [element :f] : | hash_flow.rb:952:5:952:8 | hash [element :f] : | | hash_flow.rb:952:33:952:37 | hash2 [element :d] : | hash_flow.rb:952:12:952:16 | [post] hash1 [element :d] : | | hash_flow.rb:952:33:952:37 | hash2 [element :d] : | hash_flow.rb:952:12:952:38 | call to with_defaults! [element :d] : | | hash_flow.rb:952:33:952:37 | hash2 [element :f] : | hash_flow.rb:952:12:952:16 | [post] hash1 [element :f] : | @@ -767,6 +966,11 @@ edges | hash_flow.rb:965:11:965:15 | hash1 [element :f] : | hash_flow.rb:965:11:965:19 | ...[...] : | | hash_flow.rb:965:11:965:19 | ...[...] : | hash_flow.rb:965:10:965:20 | ( ... ) | nodes +| hash_flow.rb:10:5:10:8 | hash [element 0] : | semmle.label | hash [element 0] : | +| hash_flow.rb:10:5:10:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:10:5:10:8 | hash [element :c] : | semmle.label | hash [element :c] : | +| hash_flow.rb:10:5:10:8 | hash [element e] : | semmle.label | hash [element e] : | +| hash_flow.rb:10:5:10:8 | hash [element g] : | semmle.label | hash [element g] : | | hash_flow.rb:11:15:11:24 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:13:12:13:21 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:15:14:15:23 | call to taint : | semmle.label | call to taint : | @@ -812,50 +1016,64 @@ nodes | hash_flow.rb:46:10:46:17 | ...[...] | semmle.label | ...[...] | | hash_flow.rb:48:10:48:13 | hash [element a] : | semmle.label | hash [element a] : | | hash_flow.rb:48:10:48:18 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:55:5:55:9 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | | hash_flow.rb:55:13:55:37 | ...[...] [element :a] : | semmle.label | ...[...] [element :a] : | | hash_flow.rb:55:21:55:30 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:56:10:56:14 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | | hash_flow.rb:56:10:56:18 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:59:5:59:5 | x [element :a] : | semmle.label | x [element :a] : | | hash_flow.rb:59:13:59:22 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:60:5:60:9 | hash2 [element :a] : | semmle.label | hash2 [element :a] : | | hash_flow.rb:60:13:60:19 | ...[...] [element :a] : | semmle.label | ...[...] [element :a] : | | hash_flow.rb:60:18:60:18 | x [element :a] : | semmle.label | x [element :a] : | | hash_flow.rb:61:10:61:14 | hash2 [element :a] : | semmle.label | hash2 [element :a] : | | hash_flow.rb:61:10:61:18 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:64:5:64:9 | hash3 [element] : | semmle.label | hash3 [element] : | | hash_flow.rb:64:13:64:45 | ...[...] [element] : | semmle.label | ...[...] [element] : | | hash_flow.rb:64:24:64:33 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:65:10:65:14 | hash3 [element] : | semmle.label | hash3 [element] : | | hash_flow.rb:65:10:65:18 | ...[...] | semmle.label | ...[...] | | hash_flow.rb:66:10:66:14 | hash3 [element] : | semmle.label | hash3 [element] : | | hash_flow.rb:66:10:66:18 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:68:5:68:9 | hash4 [element :a] : | semmle.label | hash4 [element :a] : | | hash_flow.rb:68:13:68:39 | ...[...] [element :a] : | semmle.label | ...[...] [element :a] : | | hash_flow.rb:68:22:68:31 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:69:10:69:14 | hash4 [element :a] : | semmle.label | hash4 [element :a] : | | hash_flow.rb:69:10:69:18 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:72:5:72:9 | hash5 [element a] : | semmle.label | hash5 [element a] : | | hash_flow.rb:72:13:72:45 | ...[...] [element a] : | semmle.label | ...[...] [element a] : | | hash_flow.rb:72:25:72:34 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:73:10:73:14 | hash5 [element a] : | semmle.label | hash5 [element a] : | | hash_flow.rb:73:10:73:19 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:76:5:76:9 | hash6 [element a] : | semmle.label | hash6 [element a] : | | hash_flow.rb:76:13:76:47 | ...[...] [element a] : | semmle.label | ...[...] [element a] : | | hash_flow.rb:76:26:76:35 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:77:10:77:14 | hash6 [element a] : | semmle.label | hash6 [element a] : | | hash_flow.rb:77:10:77:19 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:84:5:84:9 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | | hash_flow.rb:84:13:84:42 | call to [] [element :a] : | semmle.label | call to [] [element :a] : | | hash_flow.rb:84:26:84:35 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:85:10:85:14 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | | hash_flow.rb:85:10:85:18 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:92:5:92:8 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:93:15:93:24 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:96:5:96:9 | hash2 [element :a] : | semmle.label | hash2 [element :a] : | | hash_flow.rb:96:13:96:34 | call to try_convert [element :a] : | semmle.label | call to try_convert [element :a] : | | hash_flow.rb:96:30:96:33 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:97:10:97:14 | hash2 [element :a] : | semmle.label | hash2 [element :a] : | | hash_flow.rb:97:10:97:18 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:105:5:105:5 | b : | semmle.label | b : | +| hash_flow.rb:105:21:105:30 | __synth__0 : | semmle.label | __synth__0 : | | hash_flow.rb:105:21:105:30 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:106:10:106:10 | b | semmle.label | b | +| hash_flow.rb:113:5:113:5 | b : | semmle.label | b : | | hash_flow.rb:113:9:113:12 | [post] hash [element :a] : | semmle.label | [post] hash [element :a] : | | hash_flow.rb:113:9:113:34 | call to store : | semmle.label | call to store : | | hash_flow.rb:113:24:113:33 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:114:10:114:13 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:114:10:114:17 | ...[...] | semmle.label | ...[...] | | hash_flow.rb:115:10:115:10 | b | semmle.label | b | +| hash_flow.rb:118:5:118:5 | c : | semmle.label | c : | | hash_flow.rb:118:9:118:12 | [post] hash [element] : | semmle.label | [post] hash [element] : | | hash_flow.rb:118:9:118:33 | call to store : | semmle.label | call to store : | | hash_flow.rb:118:23:118:32 | call to taint : | semmle.label | call to taint : | @@ -864,6 +1082,7 @@ nodes | hash_flow.rb:120:10:120:13 | hash [element] : | semmle.label | hash [element] : | | hash_flow.rb:120:10:120:17 | ...[...] | semmle.label | ...[...] | | hash_flow.rb:121:10:121:10 | c | semmle.label | c | +| hash_flow.rb:127:5:127:8 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:128:15:128:24 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:131:5:131:8 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:131:18:131:29 | key_or_value : | semmle.label | key_or_value : | @@ -871,27 +1090,36 @@ nodes | hash_flow.rb:134:5:134:8 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:134:22:134:26 | value : | semmle.label | value : | | hash_flow.rb:136:14:136:18 | value | semmle.label | value | +| hash_flow.rb:143:5:143:8 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:144:15:144:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:147:5:147:5 | b [element 1] : | semmle.label | b [element 1] : | | hash_flow.rb:147:9:147:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:147:9:147:22 | call to assoc [element 1] : | semmle.label | call to assoc [element 1] : | | hash_flow.rb:149:10:149:10 | b [element 1] : | semmle.label | b [element 1] : | | hash_flow.rb:149:10:149:13 | ...[...] | semmle.label | ...[...] | | hash_flow.rb:150:10:150:10 | b [element 1] : | semmle.label | b [element 1] : | | hash_flow.rb:150:10:150:13 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:151:5:151:5 | c [element 1] : | semmle.label | c [element 1] : | | hash_flow.rb:151:9:151:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:151:9:151:21 | call to assoc [element 1] : | semmle.label | call to assoc [element 1] : | | hash_flow.rb:152:10:152:10 | c [element 1] : | semmle.label | c [element 1] : | | hash_flow.rb:152:10:152:13 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:169:5:169:8 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:170:15:170:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:173:5:173:5 | a [element :a] : | semmle.label | a [element :a] : | | hash_flow.rb:173:9:173:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:173:9:173:20 | call to compact [element :a] : | semmle.label | call to compact [element :a] : | | hash_flow.rb:174:10:174:10 | a [element :a] : | semmle.label | a [element :a] : | | hash_flow.rb:174:10:174:14 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:181:5:181:8 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:182:15:182:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:185:5:185:5 | a : | semmle.label | a : | | hash_flow.rb:185:9:185:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:185:9:185:23 | call to delete : | semmle.label | call to delete : | | hash_flow.rb:186:10:186:10 | a | semmle.label | a | +| hash_flow.rb:193:5:193:8 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:194:15:194:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:197:5:197:5 | a [element :a] : | semmle.label | a [element :a] : | | hash_flow.rb:197:9:197:12 | [post] hash [element :a] : | semmle.label | [post] hash [element :a] : | | hash_flow.rb:197:9:197:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:197:9:200:7 | call to delete_if [element :a] : | semmle.label | call to delete_if [element :a] : | @@ -901,45 +1129,60 @@ nodes | hash_flow.rb:201:10:201:14 | ...[...] | semmle.label | ...[...] | | hash_flow.rb:202:10:202:13 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:202:10:202:17 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:209:5:209:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:209:5:209:8 | hash [element :c, element :d] : | semmle.label | hash [element :c, element :d] : | | hash_flow.rb:210:15:210:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:213:19:213:29 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:217:10:217:13 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:217:10:217:21 | call to dig | semmle.label | call to dig | | hash_flow.rb:219:10:219:13 | hash [element :c, element :d] : | semmle.label | hash [element :c, element :d] : | | hash_flow.rb:219:10:219:24 | call to dig | semmle.label | call to dig | +| hash_flow.rb:226:5:226:8 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:227:15:227:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:230:5:230:5 | x [element :a] : | semmle.label | x [element :a] : | | hash_flow.rb:230:9:230:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:230:9:233:7 | call to each [element :a] : | semmle.label | call to each [element :a] : | | hash_flow.rb:230:28:230:32 | value : | semmle.label | value : | | hash_flow.rb:232:14:232:18 | value | semmle.label | value | | hash_flow.rb:234:10:234:10 | x [element :a] : | semmle.label | x [element :a] : | | hash_flow.rb:234:10:234:14 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:241:5:241:8 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:242:15:242:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:245:5:245:5 | x [element :a] : | semmle.label | x [element :a] : | | hash_flow.rb:245:9:245:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:245:9:247:7 | call to each_key [element :a] : | semmle.label | call to each_key [element :a] : | | hash_flow.rb:248:10:248:10 | x [element :a] : | semmle.label | x [element :a] : | | hash_flow.rb:248:10:248:14 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:255:5:255:8 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:256:15:256:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:259:5:259:5 | x [element :a] : | semmle.label | x [element :a] : | | hash_flow.rb:259:9:259:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:259:9:262:7 | call to each_pair [element :a] : | semmle.label | call to each_pair [element :a] : | | hash_flow.rb:259:33:259:37 | value : | semmle.label | value : | | hash_flow.rb:261:14:261:18 | value | semmle.label | value | | hash_flow.rb:263:10:263:10 | x [element :a] : | semmle.label | x [element :a] : | | hash_flow.rb:263:10:263:14 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:270:5:270:8 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:271:15:271:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:274:5:274:5 | x [element :a] : | semmle.label | x [element :a] : | | hash_flow.rb:274:9:274:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:274:9:276:7 | call to each_value [element :a] : | semmle.label | call to each_value [element :a] : | | hash_flow.rb:274:29:274:33 | value : | semmle.label | value : | | hash_flow.rb:275:14:275:18 | value | semmle.label | value | | hash_flow.rb:277:10:277:10 | x [element :a] : | semmle.label | x [element :a] : | | hash_flow.rb:277:10:277:14 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:284:5:284:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:287:15:287:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:290:5:290:5 | x [element :c] : | semmle.label | x [element :c] : | | hash_flow.rb:290:9:290:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:290:9:290:28 | call to except [element :c] : | semmle.label | call to except [element :c] : | | hash_flow.rb:293:10:293:10 | x [element :c] : | semmle.label | x [element :c] : | | hash_flow.rb:293:10:293:14 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:300:5:300:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:300:5:300:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:301:15:301:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:303:15:303:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:305:5:305:5 | b : | semmle.label | b : | | hash_flow.rb:305:9:305:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:305:9:305:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:305:9:307:7 | call to fetch : | semmle.label | call to fetch : | @@ -947,23 +1190,30 @@ nodes | hash_flow.rb:305:37:305:37 | x : | semmle.label | x : | | hash_flow.rb:306:14:306:14 | x | semmle.label | x | | hash_flow.rb:308:10:308:10 | b | semmle.label | b | +| hash_flow.rb:309:5:309:5 | b : | semmle.label | b : | | hash_flow.rb:309:9:309:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:309:9:309:22 | call to fetch : | semmle.label | call to fetch : | | hash_flow.rb:310:10:310:10 | b | semmle.label | b | +| hash_flow.rb:311:5:311:5 | b : | semmle.label | b : | | hash_flow.rb:311:9:311:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:311:9:311:35 | call to fetch : | semmle.label | call to fetch : | | hash_flow.rb:311:24:311:34 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:312:10:312:10 | b | semmle.label | b | +| hash_flow.rb:313:5:313:5 | b : | semmle.label | b : | | hash_flow.rb:313:9:313:35 | call to fetch : | semmle.label | call to fetch : | | hash_flow.rb:313:24:313:34 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:314:10:314:10 | b | semmle.label | b | +| hash_flow.rb:315:5:315:5 | b : | semmle.label | b : | | hash_flow.rb:315:9:315:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:315:9:315:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:315:9:315:34 | call to fetch : | semmle.label | call to fetch : | | hash_flow.rb:315:23:315:33 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:316:10:316:10 | b | semmle.label | b | +| hash_flow.rb:322:5:322:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:322:5:322:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:323:15:323:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:325:15:325:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:327:5:327:5 | b [element] : | semmle.label | b [element] : | | hash_flow.rb:327:9:327:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:327:9:327:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:327:9:330:7 | call to fetch_values [element] : | semmle.label | call to fetch_values [element] : | @@ -973,17 +1223,22 @@ nodes | hash_flow.rb:329:9:329:19 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:331:10:331:10 | b [element] : | semmle.label | b [element] : | | hash_flow.rb:331:10:331:13 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:332:5:332:5 | b [element] : | semmle.label | b [element] : | | hash_flow.rb:332:9:332:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:332:9:332:29 | call to fetch_values [element] : | semmle.label | call to fetch_values [element] : | | hash_flow.rb:333:10:333:10 | b [element] : | semmle.label | b [element] : | | hash_flow.rb:333:10:333:13 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:334:5:334:5 | b [element] : | semmle.label | b [element] : | | hash_flow.rb:334:9:334:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:334:9:334:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:334:9:334:31 | call to fetch_values [element] : | semmle.label | call to fetch_values [element] : | | hash_flow.rb:335:10:335:10 | b [element] : | semmle.label | b [element] : | | hash_flow.rb:335:10:335:13 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:341:5:341:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:341:5:341:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:342:15:342:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:344:15:344:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:346:5:346:5 | b [element :a] : | semmle.label | b [element :a] : | | hash_flow.rb:346:9:346:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:346:9:346:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:346:9:350:7 | call to filter [element :a] : | semmle.label | call to filter [element :a] : | @@ -992,6 +1247,8 @@ nodes | hash_flow.rb:351:10:351:16 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:351:11:351:11 | b [element :a] : | semmle.label | b [element :a] : | | hash_flow.rb:351:11:351:15 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:357:5:357:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:357:5:357:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:358:15:358:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:360:15:360:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:362:5:362:8 | [post] hash [element :a] : | semmle.label | [post] hash [element :a] : | @@ -1002,16 +1259,22 @@ nodes | hash_flow.rb:367:10:367:19 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:367:11:367:14 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:367:11:367:18 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:373:5:373:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:373:5:373:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:374:15:374:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:376:15:376:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:378:5:378:5 | b [element] : | semmle.label | b [element] : | | hash_flow.rb:378:9:378:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:378:9:378:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:378:9:378:20 | call to flatten [element] : | semmle.label | call to flatten [element] : | | hash_flow.rb:379:10:379:15 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:379:11:379:11 | b [element] : | semmle.label | b [element] : | | hash_flow.rb:379:11:379:14 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:385:5:385:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:385:5:385:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:386:15:386:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:388:15:388:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:390:5:390:5 | b [element :a] : | semmle.label | b [element :a] : | | hash_flow.rb:390:9:390:12 | [post] hash [element :a] : | semmle.label | [post] hash [element :a] : | | hash_flow.rb:390:9:390:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:390:9:390:12 | hash [element :c] : | semmle.label | hash [element :c] : | @@ -1024,10 +1287,18 @@ nodes | hash_flow.rb:396:10:396:16 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:396:11:396:11 | b [element :a] : | semmle.label | b [element :a] : | | hash_flow.rb:396:11:396:15 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:402:5:402:9 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | +| hash_flow.rb:402:5:402:9 | hash1 [element :c] : | semmle.label | hash1 [element :c] : | | hash_flow.rb:403:15:403:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:405:15:405:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:407:5:407:9 | hash2 [element :d] : | semmle.label | hash2 [element :d] : | +| hash_flow.rb:407:5:407:9 | hash2 [element :f] : | semmle.label | hash2 [element :f] : | | hash_flow.rb:408:15:408:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:410:15:410:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:412:5:412:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:412:5:412:8 | hash [element :c] : | semmle.label | hash [element :c] : | +| hash_flow.rb:412:5:412:8 | hash [element :d] : | semmle.label | hash [element :d] : | +| hash_flow.rb:412:5:412:8 | hash [element :f] : | semmle.label | hash [element :f] : | | hash_flow.rb:412:12:412:16 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | | hash_flow.rb:412:12:412:16 | hash1 [element :c] : | semmle.label | hash1 [element :c] : | | hash_flow.rb:412:12:416:7 | call to merge [element :a] : | semmle.label | call to merge [element :a] : | @@ -1052,10 +1323,18 @@ nodes | hash_flow.rb:422:10:422:19 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:422:11:422:14 | hash [element :f] : | semmle.label | hash [element :f] : | | hash_flow.rb:422:11:422:18 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:428:5:428:9 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | +| hash_flow.rb:428:5:428:9 | hash1 [element :c] : | semmle.label | hash1 [element :c] : | | hash_flow.rb:429:15:429:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:431:15:431:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:433:5:433:9 | hash2 [element :d] : | semmle.label | hash2 [element :d] : | +| hash_flow.rb:433:5:433:9 | hash2 [element :f] : | semmle.label | hash2 [element :f] : | | hash_flow.rb:434:15:434:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:436:15:436:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:438:5:438:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:438:5:438:8 | hash [element :c] : | semmle.label | hash [element :c] : | +| hash_flow.rb:438:5:438:8 | hash [element :d] : | semmle.label | hash [element :d] : | +| hash_flow.rb:438:5:438:8 | hash [element :f] : | semmle.label | hash [element :f] : | | hash_flow.rb:438:12:438:16 | [post] hash1 [element :a] : | semmle.label | [post] hash1 [element :a] : | | hash_flow.rb:438:12:438:16 | [post] hash1 [element :c] : | semmle.label | [post] hash1 [element :c] : | | hash_flow.rb:438:12:438:16 | [post] hash1 [element :d] : | semmle.label | [post] hash1 [element :d] : | @@ -1096,19 +1375,25 @@ nodes | hash_flow.rb:455:10:455:20 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:455:11:455:15 | hash1 [element :f] : | semmle.label | hash1 [element :f] : | | hash_flow.rb:455:11:455:19 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:461:5:461:8 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:462:15:462:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:465:5:465:5 | b [element 1] : | semmle.label | b [element 1] : | | hash_flow.rb:465:9:465:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:465:9:465:22 | call to rassoc [element 1] : | semmle.label | call to rassoc [element 1] : | | hash_flow.rb:467:10:467:10 | b [element 1] : | semmle.label | b [element 1] : | | hash_flow.rb:467:10:467:13 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:473:5:473:8 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:474:15:474:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:477:5:477:5 | b [element :a] : | semmle.label | b [element :a] : | | hash_flow.rb:477:9:477:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:477:9:481:7 | call to reject [element :a] : | semmle.label | call to reject [element :a] : | | hash_flow.rb:477:29:477:33 | value : | semmle.label | value : | | hash_flow.rb:479:14:479:18 | value | semmle.label | value | | hash_flow.rb:482:10:482:10 | b [element :a] : | semmle.label | b [element :a] : | | hash_flow.rb:482:10:482:14 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:488:5:488:8 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:489:15:489:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:492:5:492:5 | b [element :a] : | semmle.label | b [element :a] : | | hash_flow.rb:492:9:492:12 | [post] hash [element :a] : | semmle.label | [post] hash [element :a] : | | hash_flow.rb:492:9:492:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:492:9:496:7 | call to reject! [element :a] : | semmle.label | call to reject! [element :a] : | @@ -1118,6 +1403,8 @@ nodes | hash_flow.rb:497:10:497:14 | ...[...] | semmle.label | ...[...] | | hash_flow.rb:498:10:498:13 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:498:10:498:17 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:504:5:504:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:504:5:504:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:505:15:505:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:507:15:507:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:512:5:512:9 | [post] hash2 [element :a] : | semmle.label | [post] hash2 [element :a] : | @@ -1130,8 +1417,11 @@ nodes | hash_flow.rb:515:10:515:20 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:515:11:515:15 | hash2 [element :c] : | semmle.label | hash2 [element :c] : | | hash_flow.rb:515:11:515:19 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:519:5:519:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:519:5:519:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:520:15:520:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:522:15:522:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:524:5:524:5 | b [element :a] : | semmle.label | b [element :a] : | | hash_flow.rb:524:9:524:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:524:9:524:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:524:9:528:7 | call to select [element :a] : | semmle.label | call to select [element :a] : | @@ -1140,6 +1430,8 @@ nodes | hash_flow.rb:529:10:529:16 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:529:11:529:11 | b [element :a] : | semmle.label | b [element :a] : | | hash_flow.rb:529:11:529:15 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:535:5:535:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:535:5:535:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:536:15:536:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:538:15:538:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:540:5:540:8 | [post] hash [element :a] : | semmle.label | [post] hash [element :a] : | @@ -1150,8 +1442,11 @@ nodes | hash_flow.rb:545:10:545:19 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:545:11:545:14 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:545:11:545:18 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:551:5:551:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:551:5:551:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:552:15:552:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:554:15:554:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:556:5:556:5 | b [element 1] : | semmle.label | b [element 1] : | | hash_flow.rb:556:9:556:12 | [post] hash [element :a] : | semmle.label | [post] hash [element :a] : | | hash_flow.rb:556:9:556:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:556:9:556:12 | hash [element :c] : | semmle.label | hash [element :c] : | @@ -1162,13 +1457,18 @@ nodes | hash_flow.rb:559:10:559:15 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:559:11:559:11 | b [element 1] : | semmle.label | b [element 1] : | | hash_flow.rb:559:11:559:14 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:565:5:565:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:565:5:565:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:566:15:566:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:568:15:568:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:570:5:570:5 | b [element :a] : | semmle.label | b [element :a] : | | hash_flow.rb:570:9:570:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:570:9:570:26 | call to slice [element :a] : | semmle.label | call to slice [element :a] : | | hash_flow.rb:571:10:571:16 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:571:11:571:11 | b [element :a] : | semmle.label | b [element :a] : | | hash_flow.rb:571:11:571:15 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:575:5:575:5 | c [element :a] : | semmle.label | c [element :a] : | +| hash_flow.rb:575:5:575:5 | c [element :c] : | semmle.label | c [element :c] : | | hash_flow.rb:575:9:575:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:575:9:575:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:575:9:575:25 | call to slice [element :a] : | semmle.label | call to slice [element :a] : | @@ -1179,8 +1479,11 @@ nodes | hash_flow.rb:578:10:578:16 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:578:11:578:11 | c [element :c] : | semmle.label | c [element :c] : | | hash_flow.rb:578:11:578:15 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:584:5:584:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:584:5:584:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:585:15:585:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:587:15:587:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:589:5:589:5 | a [element, element 1] : | semmle.label | a [element, element 1] : | | hash_flow.rb:589:9:589:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:589:9:589:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:589:9:589:17 | call to to_a [element, element 1] : | semmle.label | call to to_a [element, element 1] : | @@ -1188,8 +1491,12 @@ nodes | hash_flow.rb:591:11:591:11 | a [element, element 1] : | semmle.label | a [element, element 1] : | | hash_flow.rb:591:11:591:14 | ...[...] [element 1] : | semmle.label | ...[...] [element 1] : | | hash_flow.rb:591:11:591:17 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:597:5:597:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:597:5:597:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:598:15:598:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:600:15:600:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:602:5:602:5 | a [element :a] : | semmle.label | a [element :a] : | +| hash_flow.rb:602:5:602:5 | a [element :c] : | semmle.label | a [element :c] : | | hash_flow.rb:602:9:602:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:602:9:602:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:602:9:602:17 | call to to_h [element :a] : | semmle.label | call to to_h [element :a] : | @@ -1200,6 +1507,7 @@ nodes | hash_flow.rb:605:10:605:16 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:605:11:605:11 | a [element :c] : | semmle.label | a [element :c] : | | hash_flow.rb:605:11:605:15 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:607:5:607:5 | b [element] : | semmle.label | b [element] : | | hash_flow.rb:607:9:607:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:607:9:607:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:607:9:611:7 | call to to_h [element] : | semmle.label | call to to_h [element] : | @@ -1209,8 +1517,11 @@ nodes | hash_flow.rb:612:10:612:16 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:612:11:612:11 | b [element] : | semmle.label | b [element] : | | hash_flow.rb:612:11:612:15 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:618:5:618:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:618:5:618:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:619:15:619:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:621:15:621:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:623:5:623:5 | a [element] : | semmle.label | a [element] : | | hash_flow.rb:623:9:623:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:623:9:623:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:623:9:623:45 | call to transform_keys [element] : | semmle.label | call to transform_keys [element] : | @@ -1223,6 +1534,8 @@ nodes | hash_flow.rb:626:10:626:17 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:626:11:626:11 | a [element] : | semmle.label | a [element] : | | hash_flow.rb:626:11:626:16 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:632:5:632:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:632:5:632:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:633:15:633:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:635:15:635:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:637:5:637:8 | [post] hash [element] : | semmle.label | [post] hash [element] : | @@ -1240,8 +1553,11 @@ nodes | hash_flow.rb:642:10:642:20 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:642:11:642:14 | hash [element] : | semmle.label | hash [element] : | | hash_flow.rb:642:11:642:19 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:648:5:648:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:648:5:648:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:649:15:649:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:651:15:651:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:653:5:653:5 | b [element] : | semmle.label | b [element] : | | hash_flow.rb:653:9:653:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:653:9:653:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:653:9:656:7 | call to transform_values [element] : | semmle.label | call to transform_values [element] : | @@ -1254,6 +1570,8 @@ nodes | hash_flow.rb:658:10:658:16 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:658:11:658:11 | b [element] : | semmle.label | b [element] : | | hash_flow.rb:658:11:658:15 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:664:5:664:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:664:5:664:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:665:15:665:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:667:15:667:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:669:5:669:8 | [post] hash [element] : | semmle.label | [post] hash [element] : | @@ -1265,10 +1583,18 @@ nodes | hash_flow.rb:673:10:673:19 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:673:11:673:14 | hash [element] : | semmle.label | hash [element] : | | hash_flow.rb:673:11:673:18 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:679:5:679:9 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | +| hash_flow.rb:679:5:679:9 | hash1 [element :c] : | semmle.label | hash1 [element :c] : | | hash_flow.rb:680:15:680:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:682:15:682:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:684:5:684:9 | hash2 [element :d] : | semmle.label | hash2 [element :d] : | +| hash_flow.rb:684:5:684:9 | hash2 [element :f] : | semmle.label | hash2 [element :f] : | | hash_flow.rb:685:15:685:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:687:15:687:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:689:5:689:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:689:5:689:8 | hash [element :c] : | semmle.label | hash [element :c] : | +| hash_flow.rb:689:5:689:8 | hash [element :d] : | semmle.label | hash [element :d] : | +| hash_flow.rb:689:5:689:8 | hash [element :f] : | semmle.label | hash [element :f] : | | hash_flow.rb:689:12:689:16 | [post] hash1 [element :a] : | semmle.label | [post] hash1 [element :a] : | | hash_flow.rb:689:12:689:16 | [post] hash1 [element :c] : | semmle.label | [post] hash1 [element :c] : | | hash_flow.rb:689:12:689:16 | [post] hash1 [element :d] : | semmle.label | [post] hash1 [element :d] : | @@ -1309,29 +1635,45 @@ nodes | hash_flow.rb:706:10:706:20 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:706:11:706:15 | hash1 [element :f] : | semmle.label | hash1 [element :f] : | | hash_flow.rb:706:11:706:19 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:712:5:712:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:712:5:712:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:713:15:713:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:715:15:715:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:717:5:717:5 | a [element] : | semmle.label | a [element] : | | hash_flow.rb:717:9:717:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:717:9:717:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:717:9:717:19 | call to values [element] : | semmle.label | call to values [element] : | | hash_flow.rb:718:10:718:15 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:718:11:718:11 | a [element] : | semmle.label | a [element] : | | hash_flow.rb:718:11:718:14 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:724:5:724:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:724:5:724:8 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:725:15:725:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:727:15:727:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:729:5:729:5 | b [element 0] : | semmle.label | b [element 0] : | | hash_flow.rb:729:9:729:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:729:9:729:26 | call to values_at [element 0] : | semmle.label | call to values_at [element 0] : | | hash_flow.rb:730:10:730:10 | b [element 0] : | semmle.label | b [element 0] : | | hash_flow.rb:730:10:730:13 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:731:5:731:5 | b [element] : | semmle.label | b [element] : | | hash_flow.rb:731:9:731:12 | hash [element :a] : | semmle.label | hash [element :a] : | | hash_flow.rb:731:9:731:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:731:9:731:31 | call to fetch_values [element] : | semmle.label | call to fetch_values [element] : | | hash_flow.rb:732:10:732:10 | b [element] : | semmle.label | b [element] : | | hash_flow.rb:732:10:732:13 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:738:5:738:9 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | +| hash_flow.rb:738:5:738:9 | hash1 [element :c] : | semmle.label | hash1 [element :c] : | | hash_flow.rb:739:15:739:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:741:15:741:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:743:5:743:9 | hash2 [element :d] : | semmle.label | hash2 [element :d] : | +| hash_flow.rb:743:5:743:9 | hash2 [element :f] : | semmle.label | hash2 [element :f] : | | hash_flow.rb:744:15:744:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:746:15:746:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:748:5:748:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:748:5:748:8 | hash [element :c] : | semmle.label | hash [element :c] : | +| hash_flow.rb:748:5:748:8 | hash [element :d] : | semmle.label | hash [element :d] : | +| hash_flow.rb:748:5:748:8 | hash [element :f] : | semmle.label | hash [element :f] : | +| hash_flow.rb:748:5:748:8 | hash [element :g] : | semmle.label | hash [element :g] : | | hash_flow.rb:748:14:748:20 | ** ... [element :a] : | semmle.label | ** ... [element :a] : | | hash_flow.rb:748:14:748:20 | ** ... [element :c] : | semmle.label | ** ... [element :c] : | | hash_flow.rb:748:16:748:20 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | @@ -1351,6 +1693,9 @@ nodes | hash_flow.rb:754:10:754:17 | ...[...] | semmle.label | ...[...] | | hash_flow.rb:755:10:755:13 | hash [element :g] : | semmle.label | hash [element :g] : | | hash_flow.rb:755:10:755:17 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:762:5:762:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:762:5:762:8 | hash [element :c] : | semmle.label | hash [element :c] : | +| hash_flow.rb:762:5:762:8 | hash [element :d] : | semmle.label | hash [element :d] : | | hash_flow.rb:763:15:763:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:765:15:765:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:766:15:766:25 | call to taint : | semmle.label | call to taint : | @@ -1360,6 +1705,7 @@ nodes | hash_flow.rb:771:10:771:17 | ...[...] | semmle.label | ...[...] | | hash_flow.rb:772:10:772:13 | hash [element :d] : | semmle.label | hash [element :d] : | | hash_flow.rb:772:10:772:17 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:774:5:774:5 | x [element :c] : | semmle.label | x [element :c] : | | hash_flow.rb:774:9:774:12 | [post] hash [element :c] : | semmle.label | [post] hash [element :c] : | | hash_flow.rb:774:9:774:12 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:774:9:774:31 | call to except! [element :c] : | semmle.label | call to except! [element :c] : | @@ -1367,10 +1713,18 @@ nodes | hash_flow.rb:778:10:778:14 | ...[...] | semmle.label | ...[...] | | hash_flow.rb:783:10:783:13 | hash [element :c] : | semmle.label | hash [element :c] : | | hash_flow.rb:783:10:783:17 | ...[...] | semmle.label | ...[...] | +| hash_flow.rb:790:5:790:9 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | +| hash_flow.rb:790:5:790:9 | hash1 [element :c] : | semmle.label | hash1 [element :c] : | | hash_flow.rb:791:15:791:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:793:15:793:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:795:5:795:9 | hash2 [element :d] : | semmle.label | hash2 [element :d] : | +| hash_flow.rb:795:5:795:9 | hash2 [element :f] : | semmle.label | hash2 [element :f] : | | hash_flow.rb:796:15:796:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:798:15:798:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:800:5:800:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:800:5:800:8 | hash [element :c] : | semmle.label | hash [element :c] : | +| hash_flow.rb:800:5:800:8 | hash [element :d] : | semmle.label | hash [element :d] : | +| hash_flow.rb:800:5:800:8 | hash [element :f] : | semmle.label | hash [element :f] : | | hash_flow.rb:800:12:800:16 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | | hash_flow.rb:800:12:800:16 | hash1 [element :c] : | semmle.label | hash1 [element :c] : | | hash_flow.rb:800:12:804:7 | call to deep_merge [element :a] : | semmle.label | call to deep_merge [element :a] : | @@ -1395,10 +1749,18 @@ nodes | hash_flow.rb:810:10:810:19 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:810:11:810:14 | hash [element :f] : | semmle.label | hash [element :f] : | | hash_flow.rb:810:11:810:18 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:816:5:816:9 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | +| hash_flow.rb:816:5:816:9 | hash1 [element :c] : | semmle.label | hash1 [element :c] : | | hash_flow.rb:817:15:817:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:819:15:819:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:821:5:821:9 | hash2 [element :d] : | semmle.label | hash2 [element :d] : | +| hash_flow.rb:821:5:821:9 | hash2 [element :f] : | semmle.label | hash2 [element :f] : | | hash_flow.rb:822:15:822:25 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:824:15:824:25 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:826:5:826:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:826:5:826:8 | hash [element :c] : | semmle.label | hash [element :c] : | +| hash_flow.rb:826:5:826:8 | hash [element :d] : | semmle.label | hash [element :d] : | +| hash_flow.rb:826:5:826:8 | hash [element :f] : | semmle.label | hash [element :f] : | | hash_flow.rb:826:12:826:16 | [post] hash1 [element :a] : | semmle.label | [post] hash1 [element :a] : | | hash_flow.rb:826:12:826:16 | [post] hash1 [element :c] : | semmle.label | [post] hash1 [element :c] : | | hash_flow.rb:826:12:826:16 | [post] hash1 [element :d] : | semmle.label | [post] hash1 [element :d] : | @@ -1439,10 +1801,18 @@ nodes | hash_flow.rb:843:10:843:20 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:843:11:843:15 | hash1 [element :f] : | semmle.label | hash1 [element :f] : | | hash_flow.rb:843:11:843:19 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:849:5:849:9 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | +| hash_flow.rb:849:5:849:9 | hash1 [element :c] : | semmle.label | hash1 [element :c] : | | hash_flow.rb:850:12:850:22 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:852:12:852:22 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:854:5:854:9 | hash2 [element :d] : | semmle.label | hash2 [element :d] : | +| hash_flow.rb:854:5:854:9 | hash2 [element :f] : | semmle.label | hash2 [element :f] : | | hash_flow.rb:855:12:855:22 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:857:12:857:22 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:860:5:860:9 | hash3 [element :a] : | semmle.label | hash3 [element :a] : | +| hash_flow.rb:860:5:860:9 | hash3 [element :c] : | semmle.label | hash3 [element :c] : | +| hash_flow.rb:860:5:860:9 | hash3 [element :d] : | semmle.label | hash3 [element :d] : | +| hash_flow.rb:860:5:860:9 | hash3 [element :f] : | semmle.label | hash3 [element :f] : | | hash_flow.rb:860:13:860:17 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | | hash_flow.rb:860:13:860:17 | hash1 [element :c] : | semmle.label | hash1 [element :c] : | | hash_flow.rb:860:13:860:38 | call to reverse_merge [element :a] : | semmle.label | call to reverse_merge [element :a] : | @@ -1463,6 +1833,10 @@ nodes | hash_flow.rb:866:10:866:20 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:866:11:866:15 | hash3 [element :f] : | semmle.label | hash3 [element :f] : | | hash_flow.rb:866:11:866:19 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:869:5:869:9 | hash4 [element :a] : | semmle.label | hash4 [element :a] : | +| hash_flow.rb:869:5:869:9 | hash4 [element :c] : | semmle.label | hash4 [element :c] : | +| hash_flow.rb:869:5:869:9 | hash4 [element :d] : | semmle.label | hash4 [element :d] : | +| hash_flow.rb:869:5:869:9 | hash4 [element :f] : | semmle.label | hash4 [element :f] : | | hash_flow.rb:869:13:869:17 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | | hash_flow.rb:869:13:869:17 | hash1 [element :c] : | semmle.label | hash1 [element :c] : | | hash_flow.rb:869:13:869:38 | call to with_defaults [element :a] : | semmle.label | call to with_defaults [element :a] : | @@ -1483,10 +1857,18 @@ nodes | hash_flow.rb:875:10:875:20 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:875:11:875:15 | hash4 [element :f] : | semmle.label | hash4 [element :f] : | | hash_flow.rb:875:11:875:19 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:881:5:881:9 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | +| hash_flow.rb:881:5:881:9 | hash1 [element :c] : | semmle.label | hash1 [element :c] : | | hash_flow.rb:882:12:882:22 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:884:12:884:22 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:886:5:886:9 | hash2 [element :d] : | semmle.label | hash2 [element :d] : | +| hash_flow.rb:886:5:886:9 | hash2 [element :f] : | semmle.label | hash2 [element :f] : | | hash_flow.rb:887:12:887:22 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:889:12:889:22 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:892:5:892:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:892:5:892:8 | hash [element :c] : | semmle.label | hash [element :c] : | +| hash_flow.rb:892:5:892:8 | hash [element :d] : | semmle.label | hash [element :d] : | +| hash_flow.rb:892:5:892:8 | hash [element :f] : | semmle.label | hash [element :f] : | | hash_flow.rb:892:12:892:16 | [post] hash1 [element :a] : | semmle.label | [post] hash1 [element :a] : | | hash_flow.rb:892:12:892:16 | [post] hash1 [element :c] : | semmle.label | [post] hash1 [element :c] : | | hash_flow.rb:892:12:892:16 | [post] hash1 [element :d] : | semmle.label | [post] hash1 [element :d] : | @@ -1523,10 +1905,18 @@ nodes | hash_flow.rb:905:10:905:20 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:905:11:905:15 | hash1 [element :f] : | semmle.label | hash1 [element :f] : | | hash_flow.rb:905:11:905:19 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:911:5:911:9 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | +| hash_flow.rb:911:5:911:9 | hash1 [element :c] : | semmle.label | hash1 [element :c] : | | hash_flow.rb:912:12:912:22 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:914:12:914:22 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:916:5:916:9 | hash2 [element :d] : | semmle.label | hash2 [element :d] : | +| hash_flow.rb:916:5:916:9 | hash2 [element :f] : | semmle.label | hash2 [element :f] : | | hash_flow.rb:917:12:917:22 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:919:12:919:22 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:922:5:922:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:922:5:922:8 | hash [element :c] : | semmle.label | hash [element :c] : | +| hash_flow.rb:922:5:922:8 | hash [element :d] : | semmle.label | hash [element :d] : | +| hash_flow.rb:922:5:922:8 | hash [element :f] : | semmle.label | hash [element :f] : | | hash_flow.rb:922:12:922:16 | [post] hash1 [element :a] : | semmle.label | [post] hash1 [element :a] : | | hash_flow.rb:922:12:922:16 | [post] hash1 [element :c] : | semmle.label | [post] hash1 [element :c] : | | hash_flow.rb:922:12:922:16 | [post] hash1 [element :d] : | semmle.label | [post] hash1 [element :d] : | @@ -1563,10 +1953,18 @@ nodes | hash_flow.rb:935:10:935:20 | ( ... ) | semmle.label | ( ... ) | | hash_flow.rb:935:11:935:15 | hash1 [element :f] : | semmle.label | hash1 [element :f] : | | hash_flow.rb:935:11:935:19 | ...[...] : | semmle.label | ...[...] : | +| hash_flow.rb:941:5:941:9 | hash1 [element :a] : | semmle.label | hash1 [element :a] : | +| hash_flow.rb:941:5:941:9 | hash1 [element :c] : | semmle.label | hash1 [element :c] : | | hash_flow.rb:942:12:942:22 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:944:12:944:22 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:946:5:946:9 | hash2 [element :d] : | semmle.label | hash2 [element :d] : | +| hash_flow.rb:946:5:946:9 | hash2 [element :f] : | semmle.label | hash2 [element :f] : | | hash_flow.rb:947:12:947:22 | call to taint : | semmle.label | call to taint : | | hash_flow.rb:949:12:949:22 | call to taint : | semmle.label | call to taint : | +| hash_flow.rb:952:5:952:8 | hash [element :a] : | semmle.label | hash [element :a] : | +| hash_flow.rb:952:5:952:8 | hash [element :c] : | semmle.label | hash [element :c] : | +| hash_flow.rb:952:5:952:8 | hash [element :d] : | semmle.label | hash [element :d] : | +| hash_flow.rb:952:5:952:8 | hash [element :f] : | semmle.label | hash [element :f] : | | hash_flow.rb:952:12:952:16 | [post] hash1 [element :a] : | semmle.label | [post] hash1 [element :a] : | | hash_flow.rb:952:12:952:16 | [post] hash1 [element :c] : | semmle.label | [post] hash1 [element :c] : | | hash_flow.rb:952:12:952:16 | [post] hash1 [element :d] : | semmle.label | [post] hash1 [element :d] : | diff --git a/ruby/ql/test/library-tests/dataflow/local/DataflowStep.expected b/ruby/ql/test/library-tests/dataflow/local/DataflowStep.expected index 2e1948ff2d7..60f62362f75 100644 --- a/ruby/ql/test/library-tests/dataflow/local/DataflowStep.expected +++ b/ruby/ql/test/library-tests/dataflow/local/DataflowStep.expected @@ -1,107 +1,107 @@ | UseUseExplosion.rb:18:5:22:7 | self (m) | UseUseExplosion.rb:20:13:20:17 | self | | UseUseExplosion.rb:18:5:22:7 | self in m | UseUseExplosion.rb:18:5:22:7 | self (m) | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2081:20:2116 | SSA phi read(x) | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2111:20:2111 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2127:20:2127 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2143:20:2143 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2159:20:2159 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2175:20:2175 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2191:20:2191 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2207:20:2207 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2223:20:2223 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2239:20:2239 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2255:20:2255 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2271:20:2271 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2287:20:2287 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2303:20:2303 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2319:20:2319 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2335:20:2335 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2351:20:2351 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2367:20:2367 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2383:20:2383 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2399:20:2399 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2415:20:2415 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2431:20:2431 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2447:20:2447 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2463:20:2463 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2479:20:2479 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2495:20:2495 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2511:20:2511 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2527:20:2527 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2543:20:2543 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2559:20:2559 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2575:20:2575 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2591:20:2591 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2607:20:2607 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2623:20:2623 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2639:20:2639 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2655:20:2655 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2671:20:2671 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2687:20:2687 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2703:20:2703 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2719:20:2719 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2735:20:2735 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2751:20:2751 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2767:20:2767 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2783:20:2783 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2799:20:2799 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2815:20:2815 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2831:20:2831 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2847:20:2847 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2863:20:2863 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2879:20:2879 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2895:20:2895 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2911:20:2911 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2927:20:2927 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2943:20:2943 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2959:20:2959 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2975:20:2975 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2991:20:2991 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3007:20:3007 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3023:20:3023 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3039:20:3039 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3055:20:3055 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3071:20:3071 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3087:20:3087 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3103:20:3103 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3119:20:3119 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3135:20:3135 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3151:20:3151 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3167:20:3167 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3183:20:3183 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3199:20:3199 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3215:20:3215 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3231:20:3231 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3247:20:3247 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3263:20:3263 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3279:20:3279 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3295:20:3295 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3311:20:3311 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3327:20:3327 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3343:20:3343 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3359:20:3359 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3375:20:3375 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3391:20:3391 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3407:20:3407 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3423:20:3423 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3439:20:3439 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3455:20:3455 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3471:20:3471 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3487:20:3487 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3503:20:3503 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3519:20:3519 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3535:20:3535 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3551:20:3551 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3567:20:3567 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3583:20:3583 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3599:20:3599 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3615:20:3615 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3631:20:3631 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3647:20:3647 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3663:20:3663 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3679:20:3679 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3695:20:3695 | x | -| UseUseExplosion.rb:19:13:19:13 | 0 | UseUseExplosion.rb:19:9:19:13 | ... = ... | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2081:20:2116 | SSA phi read(x) | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2111:20:2111 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2127:20:2127 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2143:20:2143 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2159:20:2159 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2175:20:2175 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2191:20:2191 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2207:20:2207 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2223:20:2223 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2239:20:2239 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2255:20:2255 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2271:20:2271 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2287:20:2287 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2303:20:2303 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2319:20:2319 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2335:20:2335 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2351:20:2351 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2367:20:2367 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2383:20:2383 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2399:20:2399 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2415:20:2415 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2431:20:2431 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2447:20:2447 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2463:20:2463 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2479:20:2479 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2495:20:2495 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2511:20:2511 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2527:20:2527 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2543:20:2543 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2559:20:2559 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2575:20:2575 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2591:20:2591 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2607:20:2607 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2623:20:2623 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2639:20:2639 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2655:20:2655 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2671:20:2671 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2687:20:2687 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2703:20:2703 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2719:20:2719 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2735:20:2735 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2751:20:2751 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2767:20:2767 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2783:20:2783 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2799:20:2799 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2815:20:2815 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2831:20:2831 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2847:20:2847 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2863:20:2863 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2879:20:2879 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2895:20:2895 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2911:20:2911 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2927:20:2927 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2943:20:2943 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2959:20:2959 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2975:20:2975 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2991:20:2991 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3007:20:3007 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3023:20:3023 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3039:20:3039 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3055:20:3055 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3071:20:3071 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3087:20:3087 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3103:20:3103 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3119:20:3119 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3135:20:3135 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3151:20:3151 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3167:20:3167 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3183:20:3183 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3199:20:3199 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3215:20:3215 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3231:20:3231 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3247:20:3247 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3263:20:3263 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3279:20:3279 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3295:20:3295 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3311:20:3311 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3327:20:3327 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3343:20:3343 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3359:20:3359 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3375:20:3375 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3391:20:3391 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3407:20:3407 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3423:20:3423 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3439:20:3439 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3455:20:3455 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3471:20:3471 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3487:20:3487 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3503:20:3503 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3519:20:3519 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3535:20:3535 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3551:20:3551 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3567:20:3567 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3583:20:3583 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3599:20:3599 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3615:20:3615 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3631:20:3631 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3647:20:3647 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3663:20:3663 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3679:20:3679 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3695:20:3695 | x | +| UseUseExplosion.rb:19:13:19:13 | 0 | UseUseExplosion.rb:19:9:19:9 | x | | UseUseExplosion.rb:19:13:19:13 | 0 | UseUseExplosion.rb:19:9:19:13 | ... = ... | | UseUseExplosion.rb:20:9:20:3700 | SSA phi read(self) | UseUseExplosion.rb:21:13:21:17 | self | | UseUseExplosion.rb:20:9:20:3700 | SSA phi read(x) | UseUseExplosion.rb:21:2111:21:2111 | x | @@ -2402,8 +2402,8 @@ | local_dataflow.rb:1:1:150:3 | self (local_dataflow.rb) | local_dataflow.rb:49:1:53:3 | self | | local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:1:9:1:9 | a | | local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:2:7:2:7 | a | -| local_dataflow.rb:2:3:2:7 | ... = ... | local_dataflow.rb:3:13:3:13 | b | -| local_dataflow.rb:2:7:2:7 | a | local_dataflow.rb:2:3:2:7 | ... = ... | +| local_dataflow.rb:2:3:2:3 | b | local_dataflow.rb:3:13:3:13 | b | +| local_dataflow.rb:2:7:2:7 | a | local_dataflow.rb:2:3:2:3 | b | | local_dataflow.rb:2:7:2:7 | a | local_dataflow.rb:2:3:2:7 | ... = ... | | local_dataflow.rb:2:7:2:7 | a | local_dataflow.rb:3:10:3:10 | a | | local_dataflow.rb:3:7:3:14 | ( ... ) | local_dataflow.rb:3:3:3:14 | ... = ... | @@ -2421,39 +2421,39 @@ | local_dataflow.rb:6:7:6:14 | ( ... ) | local_dataflow.rb:6:3:6:14 | ... = ... | | local_dataflow.rb:6:8:6:13 | ... = ... | local_dataflow.rb:6:7:6:14 | ( ... ) | | local_dataflow.rb:6:10:6:11 | ... + ... | local_dataflow.rb:6:8:6:13 | ... = ... | -| local_dataflow.rb:9:1:9:15 | ... = ... | local_dataflow.rb:10:14:10:18 | array | +| local_dataflow.rb:9:1:9:5 | array | local_dataflow.rb:10:14:10:18 | array | +| local_dataflow.rb:9:9:9:15 | call to [] | local_dataflow.rb:9:1:9:5 | array | | local_dataflow.rb:9:9:9:15 | call to [] | local_dataflow.rb:9:1:9:15 | ... = ... | -| local_dataflow.rb:9:9:9:15 | call to [] | local_dataflow.rb:9:1:9:15 | ... = ... | -| local_dataflow.rb:10:5:13:3 | ... = ... | local_dataflow.rb:12:5:12:5 | x | | local_dataflow.rb:10:5:13:3 | <captured entry> self | local_dataflow.rb:11:1:11:2 | self | | local_dataflow.rb:10:5:13:3 | __synth__0__1 | local_dataflow.rb:10:5:13:3 | ... = ... | -| local_dataflow.rb:10:5:13:3 | __synth__0__1 | local_dataflow.rb:10:5:13:3 | ... = ... | | local_dataflow.rb:10:5:13:3 | __synth__0__1 | local_dataflow.rb:10:5:13:3 | __synth__0__1 | | local_dataflow.rb:10:5:13:3 | __synth__0__1 | local_dataflow.rb:10:5:13:3 | __synth__0__1 | +| local_dataflow.rb:10:5:13:3 | __synth__0__1 | local_dataflow.rb:10:9:10:9 | x | | local_dataflow.rb:10:5:13:3 | call to each | local_dataflow.rb:10:1:13:3 | ... = ... | +| local_dataflow.rb:10:9:10:9 | x | local_dataflow.rb:12:5:12:5 | x | | local_dataflow.rb:10:14:10:18 | [post] array | local_dataflow.rb:15:10:15:14 | array | | local_dataflow.rb:10:14:10:18 | array | local_dataflow.rb:15:10:15:14 | array | | local_dataflow.rb:11:1:11:2 | [post] self | local_dataflow.rb:12:3:12:5 | self | | local_dataflow.rb:11:1:11:2 | self | local_dataflow.rb:12:3:12:5 | self | | local_dataflow.rb:15:1:17:3 | __synth__0__1 | local_dataflow.rb:15:1:17:3 | ... = ... | -| local_dataflow.rb:15:1:17:3 | __synth__0__1 | local_dataflow.rb:15:1:17:3 | ... = ... | | local_dataflow.rb:15:1:17:3 | __synth__0__1 | local_dataflow.rb:15:1:17:3 | __synth__0__1 | | local_dataflow.rb:15:1:17:3 | __synth__0__1 | local_dataflow.rb:15:1:17:3 | __synth__0__1 | +| local_dataflow.rb:15:1:17:3 | __synth__0__1 | local_dataflow.rb:15:5:15:5 | x | | local_dataflow.rb:15:10:15:14 | [post] array | local_dataflow.rb:19:10:19:14 | array | | local_dataflow.rb:15:10:15:14 | array | local_dataflow.rb:19:10:19:14 | array | | local_dataflow.rb:16:9:16:10 | 10 | local_dataflow.rb:16:3:16:10 | break | -| local_dataflow.rb:19:1:21:3 | ... = ... | local_dataflow.rb:20:6:20:6 | x | -| local_dataflow.rb:19:1:21:3 | __synth__0__1 | local_dataflow.rb:19:1:21:3 | ... = ... | | local_dataflow.rb:19:1:21:3 | __synth__0__1 | local_dataflow.rb:19:1:21:3 | ... = ... | | local_dataflow.rb:19:1:21:3 | __synth__0__1 | local_dataflow.rb:19:1:21:3 | __synth__0__1 | | local_dataflow.rb:19:1:21:3 | __synth__0__1 | local_dataflow.rb:19:1:21:3 | __synth__0__1 | +| local_dataflow.rb:19:1:21:3 | __synth__0__1 | local_dataflow.rb:19:5:19:5 | x | +| local_dataflow.rb:19:5:19:5 | x | local_dataflow.rb:20:6:20:6 | x | | local_dataflow.rb:24:2:24:8 | break | local_dataflow.rb:23:1:25:3 | while ... | | local_dataflow.rb:24:8:24:8 | 5 | local_dataflow.rb:24:2:24:8 | break | | local_dataflow.rb:28:5:28:26 | M | local_dataflow.rb:28:1:28:26 | ... = ... | | local_dataflow.rb:28:15:28:22 | "module" | local_dataflow.rb:28:5:28:26 | M | | local_dataflow.rb:30:5:30:24 | C | local_dataflow.rb:30:1:30:24 | ... = ... | | local_dataflow.rb:30:14:30:20 | "class" | local_dataflow.rb:30:5:30:24 | C | -| local_dataflow.rb:32:5:32:25 | bar | local_dataflow.rb:32:1:32:25 | ... = ... | +| local_dataflow.rb:32:5:32:25 | bar | local_dataflow.rb:32:1:32:1 | x | | local_dataflow.rb:32:5:32:25 | bar | local_dataflow.rb:32:1:32:25 | ... = ... | | local_dataflow.rb:34:7:34:7 | x | local_dataflow.rb:34:7:34:7 | x | | local_dataflow.rb:34:7:34:7 | x | local_dataflow.rb:35:6:35:6 | x | @@ -2498,9 +2498,9 @@ | local_dataflow.rb:73:7:73:7 | x | local_dataflow.rb:72:7:73:7 | then ... | | local_dataflow.rb:74:3:75:6 | else ... | local_dataflow.rb:69:7:76:5 | case ... | | local_dataflow.rb:75:6:75:6 | x | local_dataflow.rb:74:3:75:6 | else ... | -| local_dataflow.rb:78:3:88:5 | ... = ... | local_dataflow.rb:89:8:89:8 | z | +| local_dataflow.rb:78:3:78:3 | z | local_dataflow.rb:89:8:89:8 | z | | local_dataflow.rb:78:7:88:5 | SSA phi read(self) | local_dataflow.rb:89:3:89:9 | self | -| local_dataflow.rb:78:7:88:5 | case ... | local_dataflow.rb:78:3:88:5 | ... = ... | +| local_dataflow.rb:78:7:88:5 | case ... | local_dataflow.rb:78:3:78:3 | z | | local_dataflow.rb:78:7:88:5 | case ... | local_dataflow.rb:78:3:88:5 | ... = ... | | local_dataflow.rb:78:12:78:20 | [post] self | local_dataflow.rb:79:20:79:26 | self | | local_dataflow.rb:78:12:78:20 | [post] self | local_dataflow.rb:80:24:80:30 | self | @@ -2544,18 +2544,18 @@ | local_dataflow.rb:87:29:87:29 | x | local_dataflow.rb:87:15:87:48 | then ... | | local_dataflow.rb:92:1:109:3 | self (and_or) | local_dataflow.rb:93:7:93:15 | self | | local_dataflow.rb:92:1:109:3 | self in and_or | local_dataflow.rb:92:1:109:3 | self (and_or) | -| local_dataflow.rb:93:3:93:28 | ... = ... | local_dataflow.rb:94:8:94:8 | a | +| local_dataflow.rb:93:3:93:3 | a | local_dataflow.rb:94:8:94:8 | a | | local_dataflow.rb:93:7:93:15 | [post] self | local_dataflow.rb:93:20:93:28 | self | | local_dataflow.rb:93:7:93:15 | call to source | local_dataflow.rb:93:7:93:28 | ... \|\| ... | | local_dataflow.rb:93:7:93:15 | self | local_dataflow.rb:93:20:93:28 | self | -| local_dataflow.rb:93:7:93:28 | ... \|\| ... | local_dataflow.rb:93:3:93:28 | ... = ... | +| local_dataflow.rb:93:7:93:28 | ... \|\| ... | local_dataflow.rb:93:3:93:3 | a | | local_dataflow.rb:93:7:93:28 | ... \|\| ... | local_dataflow.rb:93:3:93:28 | ... = ... | | local_dataflow.rb:93:7:93:28 | SSA phi read(self) | local_dataflow.rb:94:3:94:9 | self | | local_dataflow.rb:93:20:93:28 | call to source | local_dataflow.rb:93:7:93:28 | ... \|\| ... | | local_dataflow.rb:94:3:94:9 | [post] self | local_dataflow.rb:95:8:95:16 | self | | local_dataflow.rb:94:3:94:9 | self | local_dataflow.rb:95:8:95:16 | self | -| local_dataflow.rb:95:3:95:30 | ... = ... | local_dataflow.rb:96:8:96:8 | b | -| local_dataflow.rb:95:7:95:30 | ( ... ) | local_dataflow.rb:95:3:95:30 | ... = ... | +| local_dataflow.rb:95:3:95:3 | b | local_dataflow.rb:96:8:96:8 | b | +| local_dataflow.rb:95:7:95:30 | ( ... ) | local_dataflow.rb:95:3:95:3 | b | | local_dataflow.rb:95:7:95:30 | ( ... ) | local_dataflow.rb:95:3:95:30 | ... = ... | | local_dataflow.rb:95:8:95:16 | [post] self | local_dataflow.rb:95:21:95:29 | self | | local_dataflow.rb:95:8:95:16 | call to source | local_dataflow.rb:95:8:95:29 | ... or ... | @@ -2565,18 +2565,18 @@ | local_dataflow.rb:95:21:95:29 | call to source | local_dataflow.rb:95:8:95:29 | ... or ... | | local_dataflow.rb:96:3:96:9 | [post] self | local_dataflow.rb:98:7:98:15 | self | | local_dataflow.rb:96:3:96:9 | self | local_dataflow.rb:98:7:98:15 | self | -| local_dataflow.rb:98:3:98:28 | ... = ... | local_dataflow.rb:99:8:99:8 | a | +| local_dataflow.rb:98:3:98:3 | a | local_dataflow.rb:99:8:99:8 | a | | local_dataflow.rb:98:7:98:15 | [post] self | local_dataflow.rb:98:20:98:28 | self | | local_dataflow.rb:98:7:98:15 | call to source | local_dataflow.rb:98:7:98:28 | ... && ... | | local_dataflow.rb:98:7:98:15 | self | local_dataflow.rb:98:20:98:28 | self | -| local_dataflow.rb:98:7:98:28 | ... && ... | local_dataflow.rb:98:3:98:28 | ... = ... | +| local_dataflow.rb:98:7:98:28 | ... && ... | local_dataflow.rb:98:3:98:3 | a | | local_dataflow.rb:98:7:98:28 | ... && ... | local_dataflow.rb:98:3:98:28 | ... = ... | | local_dataflow.rb:98:7:98:28 | SSA phi read(self) | local_dataflow.rb:99:3:99:9 | self | | local_dataflow.rb:98:20:98:28 | call to source | local_dataflow.rb:98:7:98:28 | ... && ... | | local_dataflow.rb:99:3:99:9 | [post] self | local_dataflow.rb:100:8:100:16 | self | | local_dataflow.rb:99:3:99:9 | self | local_dataflow.rb:100:8:100:16 | self | -| local_dataflow.rb:100:3:100:31 | ... = ... | local_dataflow.rb:101:8:101:8 | b | -| local_dataflow.rb:100:7:100:31 | ( ... ) | local_dataflow.rb:100:3:100:31 | ... = ... | +| local_dataflow.rb:100:3:100:3 | b | local_dataflow.rb:101:8:101:8 | b | +| local_dataflow.rb:100:7:100:31 | ( ... ) | local_dataflow.rb:100:3:100:3 | b | | local_dataflow.rb:100:7:100:31 | ( ... ) | local_dataflow.rb:100:3:100:31 | ... = ... | | local_dataflow.rb:100:8:100:16 | [post] self | local_dataflow.rb:100:22:100:30 | self | | local_dataflow.rb:100:8:100:16 | call to source | local_dataflow.rb:100:8:100:30 | ... and ... | @@ -2586,27 +2586,27 @@ | local_dataflow.rb:100:22:100:30 | call to source | local_dataflow.rb:100:8:100:30 | ... and ... | | local_dataflow.rb:101:3:101:9 | [post] self | local_dataflow.rb:103:7:103:15 | self | | local_dataflow.rb:101:3:101:9 | self | local_dataflow.rb:103:7:103:15 | self | -| local_dataflow.rb:103:3:103:15 | ... = ... | local_dataflow.rb:104:3:104:3 | a | +| local_dataflow.rb:103:3:103:3 | a | local_dataflow.rb:104:3:104:3 | a | | local_dataflow.rb:103:7:103:15 | [post] self | local_dataflow.rb:104:9:104:17 | self | -| local_dataflow.rb:103:7:103:15 | call to source | local_dataflow.rb:103:3:103:15 | ... = ... | +| local_dataflow.rb:103:7:103:15 | call to source | local_dataflow.rb:103:3:103:3 | a | | local_dataflow.rb:103:7:103:15 | call to source | local_dataflow.rb:103:3:103:15 | ... = ... | | local_dataflow.rb:103:7:103:15 | self | local_dataflow.rb:104:9:104:17 | self | | local_dataflow.rb:104:3:104:3 | a | local_dataflow.rb:104:5:104:7 | ... \|\| ... | -| local_dataflow.rb:104:3:104:17 | ... = ... | local_dataflow.rb:105:8:105:8 | a | -| local_dataflow.rb:104:5:104:7 | ... \|\| ... | local_dataflow.rb:104:3:104:17 | ... = ... | +| local_dataflow.rb:104:3:104:3 | a | local_dataflow.rb:105:8:105:8 | a | +| local_dataflow.rb:104:5:104:7 | ... \|\| ... | local_dataflow.rb:104:3:104:3 | a | | local_dataflow.rb:104:5:104:7 | ... \|\| ... | local_dataflow.rb:104:3:104:17 | ... = ... | | local_dataflow.rb:104:5:104:7 | SSA phi read(self) | local_dataflow.rb:105:3:105:9 | self | | local_dataflow.rb:104:9:104:17 | call to source | local_dataflow.rb:104:5:104:7 | ... \|\| ... | | local_dataflow.rb:105:3:105:9 | [post] self | local_dataflow.rb:106:7:106:15 | self | | local_dataflow.rb:105:3:105:9 | self | local_dataflow.rb:106:7:106:15 | self | -| local_dataflow.rb:106:3:106:15 | ... = ... | local_dataflow.rb:107:3:107:3 | b | +| local_dataflow.rb:106:3:106:3 | b | local_dataflow.rb:107:3:107:3 | b | | local_dataflow.rb:106:7:106:15 | [post] self | local_dataflow.rb:107:9:107:17 | self | -| local_dataflow.rb:106:7:106:15 | call to source | local_dataflow.rb:106:3:106:15 | ... = ... | +| local_dataflow.rb:106:7:106:15 | call to source | local_dataflow.rb:106:3:106:3 | b | | local_dataflow.rb:106:7:106:15 | call to source | local_dataflow.rb:106:3:106:15 | ... = ... | | local_dataflow.rb:106:7:106:15 | self | local_dataflow.rb:107:9:107:17 | self | | local_dataflow.rb:107:3:107:3 | b | local_dataflow.rb:107:5:107:7 | ... && ... | -| local_dataflow.rb:107:3:107:17 | ... = ... | local_dataflow.rb:108:8:108:8 | b | -| local_dataflow.rb:107:5:107:7 | ... && ... | local_dataflow.rb:107:3:107:17 | ... = ... | +| local_dataflow.rb:107:3:107:3 | b | local_dataflow.rb:108:8:108:8 | b | +| local_dataflow.rb:107:5:107:7 | ... && ... | local_dataflow.rb:107:3:107:3 | b | | local_dataflow.rb:107:5:107:7 | ... && ... | local_dataflow.rb:107:3:107:17 | ... = ... | | local_dataflow.rb:107:5:107:7 | SSA phi read(self) | local_dataflow.rb:108:3:108:9 | self | | local_dataflow.rb:107:9:107:17 | call to source | local_dataflow.rb:107:5:107:7 | ... && ... | @@ -2650,8 +2650,8 @@ | local_dataflow.rb:126:1:128:3 | self in use | local_dataflow.rb:126:1:128:3 | self (use) | | local_dataflow.rb:130:1:150:3 | self (use_use_madness) | local_dataflow.rb:132:6:132:11 | self | | local_dataflow.rb:130:1:150:3 | self in use_use_madness | local_dataflow.rb:130:1:150:3 | self (use_use_madness) | -| local_dataflow.rb:131:3:131:8 | ... = ... | local_dataflow.rb:132:10:132:10 | x | -| local_dataflow.rb:131:7:131:8 | "" | local_dataflow.rb:131:3:131:8 | ... = ... | +| local_dataflow.rb:131:3:131:3 | x | local_dataflow.rb:132:10:132:10 | x | +| local_dataflow.rb:131:7:131:8 | "" | local_dataflow.rb:131:3:131:3 | x | | local_dataflow.rb:131:7:131:8 | "" | local_dataflow.rb:131:3:131:8 | ... = ... | | local_dataflow.rb:132:6:132:11 | [post] self | local_dataflow.rb:133:8:133:13 | self | | local_dataflow.rb:132:6:132:11 | self | local_dataflow.rb:133:8:133:13 | self | diff --git a/ruby/ql/test/library-tests/dataflow/local/InlineFlowTest.expected b/ruby/ql/test/library-tests/dataflow/local/InlineFlowTest.expected index 762fc9a70f1..b824d6d37a1 100644 --- a/ruby/ql/test/library-tests/dataflow/local/InlineFlowTest.expected +++ b/ruby/ql/test/library-tests/dataflow/local/InlineFlowTest.expected @@ -1,38 +1,63 @@ failures edges -| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:79:25:79:25 | b | -| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:80:29:80:29 | a | -| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:82:12:82:12 | c | -| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:83:12:83:12 | d | -| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:84:12:84:12 | e | -| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:85:27:85:27 | f | -| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:86:33:86:33 | g | -| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:87:25:87:25 | x | -| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:89:8:89:8 | z | -| local_dataflow.rb:93:7:93:15 | call to source : | local_dataflow.rb:94:8:94:8 | a | -| local_dataflow.rb:93:7:93:15 | call to source : | local_dataflow.rb:94:8:94:8 | a | -| local_dataflow.rb:93:20:93:28 | call to source : | local_dataflow.rb:94:8:94:8 | a | -| local_dataflow.rb:93:20:93:28 | call to source : | local_dataflow.rb:94:8:94:8 | a | -| local_dataflow.rb:95:8:95:16 | call to source : | local_dataflow.rb:96:8:96:8 | b | -| local_dataflow.rb:95:8:95:16 | call to source : | local_dataflow.rb:96:8:96:8 | b | -| local_dataflow.rb:95:21:95:29 | call to source : | local_dataflow.rb:96:8:96:8 | b | -| local_dataflow.rb:95:21:95:29 | call to source : | local_dataflow.rb:96:8:96:8 | b | -| local_dataflow.rb:98:7:98:15 | call to source : | local_dataflow.rb:99:8:99:8 | a | -| local_dataflow.rb:98:7:98:15 | call to source : | local_dataflow.rb:99:8:99:8 | a | -| local_dataflow.rb:98:20:98:28 | call to source : | local_dataflow.rb:99:8:99:8 | a | -| local_dataflow.rb:98:20:98:28 | call to source : | local_dataflow.rb:99:8:99:8 | a | -| local_dataflow.rb:100:8:100:16 | call to source : | local_dataflow.rb:101:8:101:8 | b | -| local_dataflow.rb:100:8:100:16 | call to source : | local_dataflow.rb:101:8:101:8 | b | -| local_dataflow.rb:100:22:100:30 | call to source : | local_dataflow.rb:101:8:101:8 | b | -| local_dataflow.rb:100:22:100:30 | call to source : | local_dataflow.rb:101:8:101:8 | b | -| local_dataflow.rb:103:7:103:15 | call to source : | local_dataflow.rb:105:8:105:8 | a | -| local_dataflow.rb:103:7:103:15 | call to source : | local_dataflow.rb:105:8:105:8 | a | -| local_dataflow.rb:104:9:104:17 | call to source : | local_dataflow.rb:105:8:105:8 | a | -| local_dataflow.rb:104:9:104:17 | call to source : | local_dataflow.rb:105:8:105:8 | a | -| local_dataflow.rb:106:7:106:15 | call to source : | local_dataflow.rb:108:8:108:8 | b | -| local_dataflow.rb:106:7:106:15 | call to source : | local_dataflow.rb:108:8:108:8 | b | -| local_dataflow.rb:107:9:107:17 | call to source : | local_dataflow.rb:108:8:108:8 | b | -| local_dataflow.rb:107:9:107:17 | call to source : | local_dataflow.rb:108:8:108:8 | b | +| local_dataflow.rb:78:3:78:3 | z : | local_dataflow.rb:89:8:89:8 | z | +| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:79:13:79:13 | b : | +| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:80:8:80:8 | a : | +| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:81:9:81:9 | c : | +| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:81:13:81:13 | d : | +| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:81:16:81:16 | e : | +| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:85:13:85:13 | f : | +| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:86:18:86:18 | g : | +| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:87:10:87:10 | x : | +| local_dataflow.rb:79:13:79:13 | b : | local_dataflow.rb:79:25:79:25 | b | +| local_dataflow.rb:80:8:80:8 | a : | local_dataflow.rb:80:29:80:29 | a | +| local_dataflow.rb:81:9:81:9 | c : | local_dataflow.rb:82:12:82:12 | c | +| local_dataflow.rb:81:13:81:13 | d : | local_dataflow.rb:83:12:83:12 | d | +| local_dataflow.rb:81:16:81:16 | e : | local_dataflow.rb:84:12:84:12 | e | +| local_dataflow.rb:85:13:85:13 | f : | local_dataflow.rb:85:27:85:27 | f | +| local_dataflow.rb:86:18:86:18 | g : | local_dataflow.rb:86:33:86:33 | g | +| local_dataflow.rb:87:10:87:10 | x : | local_dataflow.rb:78:3:78:3 | z : | +| local_dataflow.rb:87:10:87:10 | x : | local_dataflow.rb:87:25:87:25 | x | +| local_dataflow.rb:93:3:93:3 | a : | local_dataflow.rb:94:8:94:8 | a | +| local_dataflow.rb:93:3:93:3 | a : | local_dataflow.rb:94:8:94:8 | a | +| local_dataflow.rb:93:7:93:15 | call to source : | local_dataflow.rb:93:3:93:3 | a : | +| local_dataflow.rb:93:7:93:15 | call to source : | local_dataflow.rb:93:3:93:3 | a : | +| local_dataflow.rb:93:20:93:28 | call to source : | local_dataflow.rb:93:3:93:3 | a : | +| local_dataflow.rb:93:20:93:28 | call to source : | local_dataflow.rb:93:3:93:3 | a : | +| local_dataflow.rb:95:3:95:3 | b : | local_dataflow.rb:96:8:96:8 | b | +| local_dataflow.rb:95:3:95:3 | b : | local_dataflow.rb:96:8:96:8 | b | +| local_dataflow.rb:95:8:95:16 | call to source : | local_dataflow.rb:95:3:95:3 | b : | +| local_dataflow.rb:95:8:95:16 | call to source : | local_dataflow.rb:95:3:95:3 | b : | +| local_dataflow.rb:95:21:95:29 | call to source : | local_dataflow.rb:95:3:95:3 | b : | +| local_dataflow.rb:95:21:95:29 | call to source : | local_dataflow.rb:95:3:95:3 | b : | +| local_dataflow.rb:98:3:98:3 | a : | local_dataflow.rb:99:8:99:8 | a | +| local_dataflow.rb:98:3:98:3 | a : | local_dataflow.rb:99:8:99:8 | a | +| local_dataflow.rb:98:7:98:15 | call to source : | local_dataflow.rb:98:3:98:3 | a : | +| local_dataflow.rb:98:7:98:15 | call to source : | local_dataflow.rb:98:3:98:3 | a : | +| local_dataflow.rb:98:20:98:28 | call to source : | local_dataflow.rb:98:3:98:3 | a : | +| local_dataflow.rb:98:20:98:28 | call to source : | local_dataflow.rb:98:3:98:3 | a : | +| local_dataflow.rb:100:3:100:3 | b : | local_dataflow.rb:101:8:101:8 | b | +| local_dataflow.rb:100:3:100:3 | b : | local_dataflow.rb:101:8:101:8 | b | +| local_dataflow.rb:100:8:100:16 | call to source : | local_dataflow.rb:100:3:100:3 | b : | +| local_dataflow.rb:100:8:100:16 | call to source : | local_dataflow.rb:100:3:100:3 | b : | +| local_dataflow.rb:100:22:100:30 | call to source : | local_dataflow.rb:100:3:100:3 | b : | +| local_dataflow.rb:100:22:100:30 | call to source : | local_dataflow.rb:100:3:100:3 | b : | +| local_dataflow.rb:103:3:103:3 | a : | local_dataflow.rb:104:3:104:3 | a : | +| local_dataflow.rb:103:3:103:3 | a : | local_dataflow.rb:104:3:104:3 | a : | +| local_dataflow.rb:103:7:103:15 | call to source : | local_dataflow.rb:103:3:103:3 | a : | +| local_dataflow.rb:103:7:103:15 | call to source : | local_dataflow.rb:103:3:103:3 | a : | +| local_dataflow.rb:104:3:104:3 | a : | local_dataflow.rb:105:8:105:8 | a | +| local_dataflow.rb:104:3:104:3 | a : | local_dataflow.rb:105:8:105:8 | a | +| local_dataflow.rb:104:9:104:17 | call to source : | local_dataflow.rb:104:3:104:3 | a : | +| local_dataflow.rb:104:9:104:17 | call to source : | local_dataflow.rb:104:3:104:3 | a : | +| local_dataflow.rb:106:3:106:3 | b : | local_dataflow.rb:107:3:107:3 | b : | +| local_dataflow.rb:106:3:106:3 | b : | local_dataflow.rb:107:3:107:3 | b : | +| local_dataflow.rb:106:7:106:15 | call to source : | local_dataflow.rb:106:3:106:3 | b : | +| local_dataflow.rb:106:7:106:15 | call to source : | local_dataflow.rb:106:3:106:3 | b : | +| local_dataflow.rb:107:3:107:3 | b : | local_dataflow.rb:108:8:108:8 | b | +| local_dataflow.rb:107:3:107:3 | b : | local_dataflow.rb:108:8:108:8 | b | +| local_dataflow.rb:107:9:107:17 | call to source : | local_dataflow.rb:107:3:107:3 | b : | +| local_dataflow.rb:107:9:107:17 | call to source : | local_dataflow.rb:107:3:107:3 | b : | | local_dataflow.rb:112:8:112:16 | call to source : | local_dataflow.rb:112:8:112:20 | call to dup | | local_dataflow.rb:112:8:112:16 | call to source : | local_dataflow.rb:112:8:112:20 | call to dup | | local_dataflow.rb:113:8:113:16 | call to source : | local_dataflow.rb:113:8:113:20 | call to dup : | @@ -56,48 +81,73 @@ edges | local_dataflow.rb:123:8:123:45 | call to tap : | local_dataflow.rb:123:8:123:49 | call to dup | | local_dataflow.rb:123:8:123:45 | call to tap : | local_dataflow.rb:123:8:123:49 | call to dup | nodes +| local_dataflow.rb:78:3:78:3 | z : | semmle.label | z : | | local_dataflow.rb:78:12:78:20 | call to source : | semmle.label | call to source : | +| local_dataflow.rb:79:13:79:13 | b : | semmle.label | b : | | local_dataflow.rb:79:25:79:25 | b | semmle.label | b | +| local_dataflow.rb:80:8:80:8 | a : | semmle.label | a : | | local_dataflow.rb:80:29:80:29 | a | semmle.label | a | +| local_dataflow.rb:81:9:81:9 | c : | semmle.label | c : | +| local_dataflow.rb:81:13:81:13 | d : | semmle.label | d : | +| local_dataflow.rb:81:16:81:16 | e : | semmle.label | e : | | local_dataflow.rb:82:12:82:12 | c | semmle.label | c | | local_dataflow.rb:83:12:83:12 | d | semmle.label | d | | local_dataflow.rb:84:12:84:12 | e | semmle.label | e | +| local_dataflow.rb:85:13:85:13 | f : | semmle.label | f : | | local_dataflow.rb:85:27:85:27 | f | semmle.label | f | +| local_dataflow.rb:86:18:86:18 | g : | semmle.label | g : | | local_dataflow.rb:86:33:86:33 | g | semmle.label | g | +| local_dataflow.rb:87:10:87:10 | x : | semmle.label | x : | | local_dataflow.rb:87:25:87:25 | x | semmle.label | x | | local_dataflow.rb:89:8:89:8 | z | semmle.label | z | +| local_dataflow.rb:93:3:93:3 | a : | semmle.label | a : | +| local_dataflow.rb:93:3:93:3 | a : | semmle.label | a : | | local_dataflow.rb:93:7:93:15 | call to source : | semmle.label | call to source : | | local_dataflow.rb:93:7:93:15 | call to source : | semmle.label | call to source : | | local_dataflow.rb:93:20:93:28 | call to source : | semmle.label | call to source : | | local_dataflow.rb:93:20:93:28 | call to source : | semmle.label | call to source : | | local_dataflow.rb:94:8:94:8 | a | semmle.label | a | | local_dataflow.rb:94:8:94:8 | a | semmle.label | a | +| local_dataflow.rb:95:3:95:3 | b : | semmle.label | b : | +| local_dataflow.rb:95:3:95:3 | b : | semmle.label | b : | | local_dataflow.rb:95:8:95:16 | call to source : | semmle.label | call to source : | | local_dataflow.rb:95:8:95:16 | call to source : | semmle.label | call to source : | | local_dataflow.rb:95:21:95:29 | call to source : | semmle.label | call to source : | | local_dataflow.rb:95:21:95:29 | call to source : | semmle.label | call to source : | | local_dataflow.rb:96:8:96:8 | b | semmle.label | b | | local_dataflow.rb:96:8:96:8 | b | semmle.label | b | +| local_dataflow.rb:98:3:98:3 | a : | semmle.label | a : | +| local_dataflow.rb:98:3:98:3 | a : | semmle.label | a : | | local_dataflow.rb:98:7:98:15 | call to source : | semmle.label | call to source : | | local_dataflow.rb:98:7:98:15 | call to source : | semmle.label | call to source : | | local_dataflow.rb:98:20:98:28 | call to source : | semmle.label | call to source : | | local_dataflow.rb:98:20:98:28 | call to source : | semmle.label | call to source : | | local_dataflow.rb:99:8:99:8 | a | semmle.label | a | | local_dataflow.rb:99:8:99:8 | a | semmle.label | a | +| local_dataflow.rb:100:3:100:3 | b : | semmle.label | b : | +| local_dataflow.rb:100:3:100:3 | b : | semmle.label | b : | | local_dataflow.rb:100:8:100:16 | call to source : | semmle.label | call to source : | | local_dataflow.rb:100:8:100:16 | call to source : | semmle.label | call to source : | | local_dataflow.rb:100:22:100:30 | call to source : | semmle.label | call to source : | | local_dataflow.rb:100:22:100:30 | call to source : | semmle.label | call to source : | | local_dataflow.rb:101:8:101:8 | b | semmle.label | b | | local_dataflow.rb:101:8:101:8 | b | semmle.label | b | +| local_dataflow.rb:103:3:103:3 | a : | semmle.label | a : | +| local_dataflow.rb:103:3:103:3 | a : | semmle.label | a : | | local_dataflow.rb:103:7:103:15 | call to source : | semmle.label | call to source : | | local_dataflow.rb:103:7:103:15 | call to source : | semmle.label | call to source : | +| local_dataflow.rb:104:3:104:3 | a : | semmle.label | a : | +| local_dataflow.rb:104:3:104:3 | a : | semmle.label | a : | | local_dataflow.rb:104:9:104:17 | call to source : | semmle.label | call to source : | | local_dataflow.rb:104:9:104:17 | call to source : | semmle.label | call to source : | | local_dataflow.rb:105:8:105:8 | a | semmle.label | a | | local_dataflow.rb:105:8:105:8 | a | semmle.label | a | +| local_dataflow.rb:106:3:106:3 | b : | semmle.label | b : | +| local_dataflow.rb:106:3:106:3 | b : | semmle.label | b : | | local_dataflow.rb:106:7:106:15 | call to source : | semmle.label | call to source : | | local_dataflow.rb:106:7:106:15 | call to source : | semmle.label | call to source : | +| local_dataflow.rb:107:3:107:3 | b : | semmle.label | b : | +| local_dataflow.rb:107:3:107:3 | b : | semmle.label | b : | | local_dataflow.rb:107:9:107:17 | call to source : | semmle.label | call to source : | | local_dataflow.rb:107:9:107:17 | call to source : | semmle.label | call to source : | | local_dataflow.rb:108:8:108:8 | b | semmle.label | b | diff --git a/ruby/ql/test/library-tests/dataflow/local/TaintStep.expected b/ruby/ql/test/library-tests/dataflow/local/TaintStep.expected index da8b1b82747..890bef5720e 100644 --- a/ruby/ql/test/library-tests/dataflow/local/TaintStep.expected +++ b/ruby/ql/test/library-tests/dataflow/local/TaintStep.expected @@ -1,107 +1,107 @@ | UseUseExplosion.rb:18:5:22:7 | self (m) | UseUseExplosion.rb:20:13:20:17 | self | | UseUseExplosion.rb:18:5:22:7 | self in m | UseUseExplosion.rb:18:5:22:7 | self (m) | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2081:20:2116 | SSA phi read(x) | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2111:20:2111 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2127:20:2127 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2143:20:2143 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2159:20:2159 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2175:20:2175 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2191:20:2191 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2207:20:2207 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2223:20:2223 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2239:20:2239 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2255:20:2255 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2271:20:2271 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2287:20:2287 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2303:20:2303 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2319:20:2319 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2335:20:2335 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2351:20:2351 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2367:20:2367 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2383:20:2383 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2399:20:2399 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2415:20:2415 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2431:20:2431 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2447:20:2447 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2463:20:2463 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2479:20:2479 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2495:20:2495 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2511:20:2511 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2527:20:2527 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2543:20:2543 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2559:20:2559 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2575:20:2575 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2591:20:2591 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2607:20:2607 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2623:20:2623 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2639:20:2639 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2655:20:2655 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2671:20:2671 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2687:20:2687 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2703:20:2703 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2719:20:2719 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2735:20:2735 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2751:20:2751 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2767:20:2767 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2783:20:2783 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2799:20:2799 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2815:20:2815 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2831:20:2831 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2847:20:2847 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2863:20:2863 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2879:20:2879 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2895:20:2895 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2911:20:2911 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2927:20:2927 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2943:20:2943 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2959:20:2959 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2975:20:2975 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:2991:20:2991 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3007:20:3007 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3023:20:3023 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3039:20:3039 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3055:20:3055 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3071:20:3071 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3087:20:3087 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3103:20:3103 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3119:20:3119 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3135:20:3135 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3151:20:3151 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3167:20:3167 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3183:20:3183 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3199:20:3199 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3215:20:3215 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3231:20:3231 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3247:20:3247 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3263:20:3263 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3279:20:3279 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3295:20:3295 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3311:20:3311 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3327:20:3327 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3343:20:3343 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3359:20:3359 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3375:20:3375 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3391:20:3391 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3407:20:3407 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3423:20:3423 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3439:20:3439 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3455:20:3455 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3471:20:3471 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3487:20:3487 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3503:20:3503 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3519:20:3519 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3535:20:3535 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3551:20:3551 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3567:20:3567 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3583:20:3583 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3599:20:3599 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3615:20:3615 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3631:20:3631 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3647:20:3647 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3663:20:3663 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3679:20:3679 | x | -| UseUseExplosion.rb:19:9:19:13 | ... = ... | UseUseExplosion.rb:20:3695:20:3695 | x | -| UseUseExplosion.rb:19:13:19:13 | 0 | UseUseExplosion.rb:19:9:19:13 | ... = ... | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2081:20:2116 | SSA phi read(x) | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2111:20:2111 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2127:20:2127 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2143:20:2143 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2159:20:2159 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2175:20:2175 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2191:20:2191 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2207:20:2207 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2223:20:2223 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2239:20:2239 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2255:20:2255 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2271:20:2271 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2287:20:2287 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2303:20:2303 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2319:20:2319 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2335:20:2335 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2351:20:2351 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2367:20:2367 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2383:20:2383 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2399:20:2399 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2415:20:2415 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2431:20:2431 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2447:20:2447 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2463:20:2463 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2479:20:2479 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2495:20:2495 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2511:20:2511 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2527:20:2527 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2543:20:2543 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2559:20:2559 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2575:20:2575 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2591:20:2591 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2607:20:2607 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2623:20:2623 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2639:20:2639 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2655:20:2655 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2671:20:2671 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2687:20:2687 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2703:20:2703 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2719:20:2719 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2735:20:2735 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2751:20:2751 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2767:20:2767 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2783:20:2783 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2799:20:2799 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2815:20:2815 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2831:20:2831 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2847:20:2847 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2863:20:2863 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2879:20:2879 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2895:20:2895 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2911:20:2911 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2927:20:2927 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2943:20:2943 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2959:20:2959 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2975:20:2975 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:2991:20:2991 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3007:20:3007 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3023:20:3023 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3039:20:3039 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3055:20:3055 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3071:20:3071 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3087:20:3087 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3103:20:3103 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3119:20:3119 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3135:20:3135 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3151:20:3151 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3167:20:3167 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3183:20:3183 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3199:20:3199 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3215:20:3215 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3231:20:3231 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3247:20:3247 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3263:20:3263 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3279:20:3279 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3295:20:3295 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3311:20:3311 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3327:20:3327 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3343:20:3343 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3359:20:3359 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3375:20:3375 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3391:20:3391 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3407:20:3407 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3423:20:3423 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3439:20:3439 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3455:20:3455 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3471:20:3471 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3487:20:3487 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3503:20:3503 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3519:20:3519 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3535:20:3535 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3551:20:3551 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3567:20:3567 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3583:20:3583 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3599:20:3599 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3615:20:3615 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3631:20:3631 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3647:20:3647 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3663:20:3663 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3679:20:3679 | x | +| UseUseExplosion.rb:19:9:19:9 | x | UseUseExplosion.rb:20:3695:20:3695 | x | +| UseUseExplosion.rb:19:13:19:13 | 0 | UseUseExplosion.rb:19:9:19:9 | x | | UseUseExplosion.rb:19:13:19:13 | 0 | UseUseExplosion.rb:19:9:19:13 | ... = ... | | UseUseExplosion.rb:20:9:20:3700 | SSA phi read(self) | UseUseExplosion.rb:21:13:21:17 | self | | UseUseExplosion.rb:20:9:20:3700 | SSA phi read(x) | UseUseExplosion.rb:21:2111:21:2111 | x | @@ -2833,8 +2833,8 @@ | local_dataflow.rb:1:1:150:3 | self (local_dataflow.rb) | local_dataflow.rb:49:1:53:3 | self | | local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:1:9:1:9 | a | | local_dataflow.rb:1:9:1:9 | a | local_dataflow.rb:2:7:2:7 | a | -| local_dataflow.rb:2:3:2:7 | ... = ... | local_dataflow.rb:3:13:3:13 | b | -| local_dataflow.rb:2:7:2:7 | a | local_dataflow.rb:2:3:2:7 | ... = ... | +| local_dataflow.rb:2:3:2:3 | b | local_dataflow.rb:3:13:3:13 | b | +| local_dataflow.rb:2:7:2:7 | a | local_dataflow.rb:2:3:2:3 | b | | local_dataflow.rb:2:7:2:7 | a | local_dataflow.rb:2:3:2:7 | ... = ... | | local_dataflow.rb:2:7:2:7 | a | local_dataflow.rb:3:10:3:10 | a | | local_dataflow.rb:3:7:3:14 | ( ... ) | local_dataflow.rb:3:3:3:14 | ... = ... | @@ -2854,33 +2854,33 @@ | local_dataflow.rb:6:8:6:13 | ... = ... | local_dataflow.rb:6:7:6:14 | ( ... ) | | local_dataflow.rb:6:10:6:11 | ... + ... | local_dataflow.rb:6:8:6:13 | ... = ... | | local_dataflow.rb:6:13:6:13 | b | local_dataflow.rb:6:10:6:11 | ... + ... | -| local_dataflow.rb:9:1:9:15 | ... = ... | local_dataflow.rb:10:14:10:18 | array | +| local_dataflow.rb:9:1:9:5 | array | local_dataflow.rb:10:14:10:18 | array | | local_dataflow.rb:9:9:9:15 | Array | local_dataflow.rb:9:9:9:15 | call to [] | +| local_dataflow.rb:9:9:9:15 | call to [] | local_dataflow.rb:9:1:9:5 | array | | local_dataflow.rb:9:9:9:15 | call to [] | local_dataflow.rb:9:1:9:15 | ... = ... | -| local_dataflow.rb:9:9:9:15 | call to [] | local_dataflow.rb:9:1:9:15 | ... = ... | -| local_dataflow.rb:10:5:13:3 | ... = ... | local_dataflow.rb:12:5:12:5 | x | | local_dataflow.rb:10:5:13:3 | <captured entry> self | local_dataflow.rb:11:1:11:2 | self | | local_dataflow.rb:10:5:13:3 | __synth__0__1 | local_dataflow.rb:10:5:13:3 | ... = ... | -| local_dataflow.rb:10:5:13:3 | __synth__0__1 | local_dataflow.rb:10:5:13:3 | ... = ... | | local_dataflow.rb:10:5:13:3 | __synth__0__1 | local_dataflow.rb:10:5:13:3 | __synth__0__1 | | local_dataflow.rb:10:5:13:3 | __synth__0__1 | local_dataflow.rb:10:5:13:3 | __synth__0__1 | +| local_dataflow.rb:10:5:13:3 | __synth__0__1 | local_dataflow.rb:10:9:10:9 | x | | local_dataflow.rb:10:5:13:3 | call to each | local_dataflow.rb:10:1:13:3 | ... = ... | +| local_dataflow.rb:10:9:10:9 | x | local_dataflow.rb:12:5:12:5 | x | | local_dataflow.rb:10:14:10:18 | [post] array | local_dataflow.rb:15:10:15:14 | array | | local_dataflow.rb:10:14:10:18 | array | local_dataflow.rb:15:10:15:14 | array | | local_dataflow.rb:11:1:11:2 | [post] self | local_dataflow.rb:12:3:12:5 | self | | local_dataflow.rb:11:1:11:2 | self | local_dataflow.rb:12:3:12:5 | self | | local_dataflow.rb:15:1:17:3 | __synth__0__1 | local_dataflow.rb:15:1:17:3 | ... = ... | -| local_dataflow.rb:15:1:17:3 | __synth__0__1 | local_dataflow.rb:15:1:17:3 | ... = ... | | local_dataflow.rb:15:1:17:3 | __synth__0__1 | local_dataflow.rb:15:1:17:3 | __synth__0__1 | | local_dataflow.rb:15:1:17:3 | __synth__0__1 | local_dataflow.rb:15:1:17:3 | __synth__0__1 | +| local_dataflow.rb:15:1:17:3 | __synth__0__1 | local_dataflow.rb:15:5:15:5 | x | | local_dataflow.rb:15:10:15:14 | [post] array | local_dataflow.rb:19:10:19:14 | array | | local_dataflow.rb:15:10:15:14 | array | local_dataflow.rb:19:10:19:14 | array | | local_dataflow.rb:16:9:16:10 | 10 | local_dataflow.rb:16:3:16:10 | break | -| local_dataflow.rb:19:1:21:3 | ... = ... | local_dataflow.rb:20:6:20:6 | x | -| local_dataflow.rb:19:1:21:3 | __synth__0__1 | local_dataflow.rb:19:1:21:3 | ... = ... | | local_dataflow.rb:19:1:21:3 | __synth__0__1 | local_dataflow.rb:19:1:21:3 | ... = ... | | local_dataflow.rb:19:1:21:3 | __synth__0__1 | local_dataflow.rb:19:1:21:3 | __synth__0__1 | | local_dataflow.rb:19:1:21:3 | __synth__0__1 | local_dataflow.rb:19:1:21:3 | __synth__0__1 | +| local_dataflow.rb:19:1:21:3 | __synth__0__1 | local_dataflow.rb:19:5:19:5 | x | +| local_dataflow.rb:19:5:19:5 | x | local_dataflow.rb:20:6:20:6 | x | | local_dataflow.rb:20:6:20:6 | x | local_dataflow.rb:20:6:20:10 | ... > ... | | local_dataflow.rb:20:10:20:10 | 1 | local_dataflow.rb:20:6:20:10 | ... > ... | | local_dataflow.rb:24:2:24:8 | break | local_dataflow.rb:23:1:25:3 | while ... | @@ -2889,7 +2889,7 @@ | local_dataflow.rb:28:15:28:22 | "module" | local_dataflow.rb:28:5:28:26 | M | | local_dataflow.rb:30:5:30:24 | C | local_dataflow.rb:30:1:30:24 | ... = ... | | local_dataflow.rb:30:14:30:20 | "class" | local_dataflow.rb:30:5:30:24 | C | -| local_dataflow.rb:32:5:32:25 | bar | local_dataflow.rb:32:1:32:25 | ... = ... | +| local_dataflow.rb:32:5:32:25 | bar | local_dataflow.rb:32:1:32:1 | x | | local_dataflow.rb:32:5:32:25 | bar | local_dataflow.rb:32:1:32:25 | ... = ... | | local_dataflow.rb:34:7:34:7 | x | local_dataflow.rb:34:7:34:7 | x | | local_dataflow.rb:34:7:34:7 | x | local_dataflow.rb:35:6:35:6 | x | @@ -2943,9 +2943,9 @@ | local_dataflow.rb:73:7:73:7 | x | local_dataflow.rb:72:7:73:7 | then ... | | local_dataflow.rb:74:3:75:6 | else ... | local_dataflow.rb:69:7:76:5 | case ... | | local_dataflow.rb:75:6:75:6 | x | local_dataflow.rb:74:3:75:6 | else ... | -| local_dataflow.rb:78:3:88:5 | ... = ... | local_dataflow.rb:89:8:89:8 | z | +| local_dataflow.rb:78:3:78:3 | z | local_dataflow.rb:89:8:89:8 | z | | local_dataflow.rb:78:7:88:5 | SSA phi read(self) | local_dataflow.rb:89:3:89:9 | self | -| local_dataflow.rb:78:7:88:5 | case ... | local_dataflow.rb:78:3:88:5 | ... = ... | +| local_dataflow.rb:78:7:88:5 | case ... | local_dataflow.rb:78:3:78:3 | z | | local_dataflow.rb:78:7:88:5 | case ... | local_dataflow.rb:78:3:88:5 | ... = ... | | local_dataflow.rb:78:12:78:20 | [post] self | local_dataflow.rb:79:20:79:26 | self | | local_dataflow.rb:78:12:78:20 | [post] self | local_dataflow.rb:80:24:80:30 | self | @@ -3000,18 +3000,18 @@ | local_dataflow.rb:87:29:87:29 | x | local_dataflow.rb:87:15:87:48 | then ... | | local_dataflow.rb:92:1:109:3 | self (and_or) | local_dataflow.rb:93:7:93:15 | self | | local_dataflow.rb:92:1:109:3 | self in and_or | local_dataflow.rb:92:1:109:3 | self (and_or) | -| local_dataflow.rb:93:3:93:28 | ... = ... | local_dataflow.rb:94:8:94:8 | a | +| local_dataflow.rb:93:3:93:3 | a | local_dataflow.rb:94:8:94:8 | a | | local_dataflow.rb:93:7:93:15 | [post] self | local_dataflow.rb:93:20:93:28 | self | | local_dataflow.rb:93:7:93:15 | call to source | local_dataflow.rb:93:7:93:28 | ... \|\| ... | | local_dataflow.rb:93:7:93:15 | self | local_dataflow.rb:93:20:93:28 | self | -| local_dataflow.rb:93:7:93:28 | ... \|\| ... | local_dataflow.rb:93:3:93:28 | ... = ... | +| local_dataflow.rb:93:7:93:28 | ... \|\| ... | local_dataflow.rb:93:3:93:3 | a | | local_dataflow.rb:93:7:93:28 | ... \|\| ... | local_dataflow.rb:93:3:93:28 | ... = ... | | local_dataflow.rb:93:7:93:28 | SSA phi read(self) | local_dataflow.rb:94:3:94:9 | self | | local_dataflow.rb:93:20:93:28 | call to source | local_dataflow.rb:93:7:93:28 | ... \|\| ... | | local_dataflow.rb:94:3:94:9 | [post] self | local_dataflow.rb:95:8:95:16 | self | | local_dataflow.rb:94:3:94:9 | self | local_dataflow.rb:95:8:95:16 | self | -| local_dataflow.rb:95:3:95:30 | ... = ... | local_dataflow.rb:96:8:96:8 | b | -| local_dataflow.rb:95:7:95:30 | ( ... ) | local_dataflow.rb:95:3:95:30 | ... = ... | +| local_dataflow.rb:95:3:95:3 | b | local_dataflow.rb:96:8:96:8 | b | +| local_dataflow.rb:95:7:95:30 | ( ... ) | local_dataflow.rb:95:3:95:3 | b | | local_dataflow.rb:95:7:95:30 | ( ... ) | local_dataflow.rb:95:3:95:30 | ... = ... | | local_dataflow.rb:95:8:95:16 | [post] self | local_dataflow.rb:95:21:95:29 | self | | local_dataflow.rb:95:8:95:16 | call to source | local_dataflow.rb:95:8:95:29 | ... or ... | @@ -3021,18 +3021,18 @@ | local_dataflow.rb:95:21:95:29 | call to source | local_dataflow.rb:95:8:95:29 | ... or ... | | local_dataflow.rb:96:3:96:9 | [post] self | local_dataflow.rb:98:7:98:15 | self | | local_dataflow.rb:96:3:96:9 | self | local_dataflow.rb:98:7:98:15 | self | -| local_dataflow.rb:98:3:98:28 | ... = ... | local_dataflow.rb:99:8:99:8 | a | +| local_dataflow.rb:98:3:98:3 | a | local_dataflow.rb:99:8:99:8 | a | | local_dataflow.rb:98:7:98:15 | [post] self | local_dataflow.rb:98:20:98:28 | self | | local_dataflow.rb:98:7:98:15 | call to source | local_dataflow.rb:98:7:98:28 | ... && ... | | local_dataflow.rb:98:7:98:15 | self | local_dataflow.rb:98:20:98:28 | self | -| local_dataflow.rb:98:7:98:28 | ... && ... | local_dataflow.rb:98:3:98:28 | ... = ... | +| local_dataflow.rb:98:7:98:28 | ... && ... | local_dataflow.rb:98:3:98:3 | a | | local_dataflow.rb:98:7:98:28 | ... && ... | local_dataflow.rb:98:3:98:28 | ... = ... | | local_dataflow.rb:98:7:98:28 | SSA phi read(self) | local_dataflow.rb:99:3:99:9 | self | | local_dataflow.rb:98:20:98:28 | call to source | local_dataflow.rb:98:7:98:28 | ... && ... | | local_dataflow.rb:99:3:99:9 | [post] self | local_dataflow.rb:100:8:100:16 | self | | local_dataflow.rb:99:3:99:9 | self | local_dataflow.rb:100:8:100:16 | self | -| local_dataflow.rb:100:3:100:31 | ... = ... | local_dataflow.rb:101:8:101:8 | b | -| local_dataflow.rb:100:7:100:31 | ( ... ) | local_dataflow.rb:100:3:100:31 | ... = ... | +| local_dataflow.rb:100:3:100:3 | b | local_dataflow.rb:101:8:101:8 | b | +| local_dataflow.rb:100:7:100:31 | ( ... ) | local_dataflow.rb:100:3:100:3 | b | | local_dataflow.rb:100:7:100:31 | ( ... ) | local_dataflow.rb:100:3:100:31 | ... = ... | | local_dataflow.rb:100:8:100:16 | [post] self | local_dataflow.rb:100:22:100:30 | self | | local_dataflow.rb:100:8:100:16 | call to source | local_dataflow.rb:100:8:100:30 | ... and ... | @@ -3042,27 +3042,27 @@ | local_dataflow.rb:100:22:100:30 | call to source | local_dataflow.rb:100:8:100:30 | ... and ... | | local_dataflow.rb:101:3:101:9 | [post] self | local_dataflow.rb:103:7:103:15 | self | | local_dataflow.rb:101:3:101:9 | self | local_dataflow.rb:103:7:103:15 | self | -| local_dataflow.rb:103:3:103:15 | ... = ... | local_dataflow.rb:104:3:104:3 | a | +| local_dataflow.rb:103:3:103:3 | a | local_dataflow.rb:104:3:104:3 | a | | local_dataflow.rb:103:7:103:15 | [post] self | local_dataflow.rb:104:9:104:17 | self | -| local_dataflow.rb:103:7:103:15 | call to source | local_dataflow.rb:103:3:103:15 | ... = ... | +| local_dataflow.rb:103:7:103:15 | call to source | local_dataflow.rb:103:3:103:3 | a | | local_dataflow.rb:103:7:103:15 | call to source | local_dataflow.rb:103:3:103:15 | ... = ... | | local_dataflow.rb:103:7:103:15 | self | local_dataflow.rb:104:9:104:17 | self | | local_dataflow.rb:104:3:104:3 | a | local_dataflow.rb:104:5:104:7 | ... \|\| ... | -| local_dataflow.rb:104:3:104:17 | ... = ... | local_dataflow.rb:105:8:105:8 | a | -| local_dataflow.rb:104:5:104:7 | ... \|\| ... | local_dataflow.rb:104:3:104:17 | ... = ... | +| local_dataflow.rb:104:3:104:3 | a | local_dataflow.rb:105:8:105:8 | a | +| local_dataflow.rb:104:5:104:7 | ... \|\| ... | local_dataflow.rb:104:3:104:3 | a | | local_dataflow.rb:104:5:104:7 | ... \|\| ... | local_dataflow.rb:104:3:104:17 | ... = ... | | local_dataflow.rb:104:5:104:7 | SSA phi read(self) | local_dataflow.rb:105:3:105:9 | self | | local_dataflow.rb:104:9:104:17 | call to source | local_dataflow.rb:104:5:104:7 | ... \|\| ... | | local_dataflow.rb:105:3:105:9 | [post] self | local_dataflow.rb:106:7:106:15 | self | | local_dataflow.rb:105:3:105:9 | self | local_dataflow.rb:106:7:106:15 | self | -| local_dataflow.rb:106:3:106:15 | ... = ... | local_dataflow.rb:107:3:107:3 | b | +| local_dataflow.rb:106:3:106:3 | b | local_dataflow.rb:107:3:107:3 | b | | local_dataflow.rb:106:7:106:15 | [post] self | local_dataflow.rb:107:9:107:17 | self | -| local_dataflow.rb:106:7:106:15 | call to source | local_dataflow.rb:106:3:106:15 | ... = ... | +| local_dataflow.rb:106:7:106:15 | call to source | local_dataflow.rb:106:3:106:3 | b | | local_dataflow.rb:106:7:106:15 | call to source | local_dataflow.rb:106:3:106:15 | ... = ... | | local_dataflow.rb:106:7:106:15 | self | local_dataflow.rb:107:9:107:17 | self | | local_dataflow.rb:107:3:107:3 | b | local_dataflow.rb:107:5:107:7 | ... && ... | -| local_dataflow.rb:107:3:107:17 | ... = ... | local_dataflow.rb:108:8:108:8 | b | -| local_dataflow.rb:107:5:107:7 | ... && ... | local_dataflow.rb:107:3:107:17 | ... = ... | +| local_dataflow.rb:107:3:107:3 | b | local_dataflow.rb:108:8:108:8 | b | +| local_dataflow.rb:107:5:107:7 | ... && ... | local_dataflow.rb:107:3:107:3 | b | | local_dataflow.rb:107:5:107:7 | ... && ... | local_dataflow.rb:107:3:107:17 | ... = ... | | local_dataflow.rb:107:5:107:7 | SSA phi read(self) | local_dataflow.rb:108:3:108:9 | self | | local_dataflow.rb:107:9:107:17 | call to source | local_dataflow.rb:107:5:107:7 | ... && ... | @@ -3106,8 +3106,8 @@ | local_dataflow.rb:126:1:128:3 | self in use | local_dataflow.rb:126:1:128:3 | self (use) | | local_dataflow.rb:130:1:150:3 | self (use_use_madness) | local_dataflow.rb:132:6:132:11 | self | | local_dataflow.rb:130:1:150:3 | self in use_use_madness | local_dataflow.rb:130:1:150:3 | self (use_use_madness) | -| local_dataflow.rb:131:3:131:8 | ... = ... | local_dataflow.rb:132:10:132:10 | x | -| local_dataflow.rb:131:7:131:8 | "" | local_dataflow.rb:131:3:131:8 | ... = ... | +| local_dataflow.rb:131:3:131:3 | x | local_dataflow.rb:132:10:132:10 | x | +| local_dataflow.rb:131:7:131:8 | "" | local_dataflow.rb:131:3:131:3 | x | | local_dataflow.rb:131:7:131:8 | "" | local_dataflow.rb:131:3:131:8 | ... = ... | | local_dataflow.rb:132:6:132:11 | [post] self | local_dataflow.rb:133:8:133:13 | self | | local_dataflow.rb:132:6:132:11 | self | local_dataflow.rb:133:8:133:13 | self | diff --git a/ruby/ql/test/library-tests/dataflow/params/params-flow.expected b/ruby/ql/test/library-tests/dataflow/params/params-flow.expected index 12db100a968..3b459c4a3e6 100644 --- a/ruby/ql/test/library-tests/dataflow/params/params-flow.expected +++ b/ruby/ql/test/library-tests/dataflow/params/params-flow.expected @@ -22,17 +22,21 @@ edges | params_flow.rb:33:12:33:19 | call to taint : | params_flow.rb:25:12:25:13 | p1 : | | params_flow.rb:33:26:33:34 | call to taint : | params_flow.rb:25:17:25:24 | **kwargs [element :p2] : | | params_flow.rb:33:41:33:49 | call to taint : | params_flow.rb:25:17:25:24 | **kwargs [element :p3] : | -| params_flow.rb:34:14:34:22 | call to taint : | params_flow.rb:35:25:35:28 | args [element :p3] : | +| params_flow.rb:34:1:34:4 | args [element :p3] : | params_flow.rb:35:25:35:28 | args [element :p3] : | +| params_flow.rb:34:14:34:22 | call to taint : | params_flow.rb:34:1:34:4 | args [element :p3] : | | params_flow.rb:35:12:35:20 | call to taint : | params_flow.rb:25:12:25:13 | p1 : | | params_flow.rb:35:23:35:28 | ** ... [element :p3] : | params_flow.rb:25:17:25:24 | **kwargs [element :p3] : | | params_flow.rb:35:25:35:28 | args [element :p3] : | params_flow.rb:35:23:35:28 | ** ... [element :p3] : | -| params_flow.rb:37:16:37:24 | call to taint : | params_flow.rb:38:10:38:13 | args [element :p1] : | -| params_flow.rb:37:34:37:42 | call to taint : | params_flow.rb:38:10:38:13 | args [element :p2] : | +| params_flow.rb:37:1:37:4 | args [element :p1] : | params_flow.rb:38:10:38:13 | args [element :p1] : | +| params_flow.rb:37:1:37:4 | args [element :p2] : | params_flow.rb:38:10:38:13 | args [element :p2] : | +| params_flow.rb:37:16:37:24 | call to taint : | params_flow.rb:37:1:37:4 | args [element :p1] : | +| params_flow.rb:37:34:37:42 | call to taint : | params_flow.rb:37:1:37:4 | args [element :p2] : | | params_flow.rb:38:8:38:13 | ** ... [element :p1] : | params_flow.rb:25:12:25:13 | p1 : | | params_flow.rb:38:8:38:13 | ** ... [element :p2] : | params_flow.rb:25:17:25:24 | **kwargs [element :p2] : | | params_flow.rb:38:10:38:13 | args [element :p1] : | params_flow.rb:38:8:38:13 | ** ... [element :p1] : | | params_flow.rb:38:10:38:13 | args [element :p2] : | params_flow.rb:38:8:38:13 | ** ... [element :p2] : | -| params_flow.rb:40:16:40:24 | call to taint : | params_flow.rb:41:26:41:29 | args [element :p1] : | +| params_flow.rb:40:1:40:4 | args [element :p1] : | params_flow.rb:41:26:41:29 | args [element :p1] : | +| params_flow.rb:40:16:40:24 | call to taint : | params_flow.rb:40:1:40:4 | args [element :p1] : | | params_flow.rb:41:13:41:21 | call to taint : | params_flow.rb:16:18:16:19 | p2 : | | params_flow.rb:41:24:41:29 | ** ... [element :p1] : | params_flow.rb:16:13:16:14 | p1 : | | params_flow.rb:41:26:41:29 | args [element :p1] : | params_flow.rb:41:24:41:29 | ** ... [element :p1] : | @@ -40,7 +44,8 @@ edges | params_flow.rb:49:13:49:14 | p1 : | params_flow.rb:50:10:50:11 | p1 | | params_flow.rb:54:9:54:17 | call to taint : | params_flow.rb:49:13:49:14 | p1 : | | params_flow.rb:57:9:57:17 | call to taint : | params_flow.rb:49:13:49:14 | p1 : | -| params_flow.rb:62:8:62:16 | call to taint : | params_flow.rb:66:13:66:16 | args : | +| params_flow.rb:62:1:62:4 | args : | params_flow.rb:66:13:66:16 | args : | +| params_flow.rb:62:8:62:16 | call to taint : | params_flow.rb:62:1:62:4 | args : | | params_flow.rb:63:16:63:17 | *x [element 0] : | params_flow.rb:64:10:64:10 | x [element 0] : | | params_flow.rb:64:10:64:10 | x [element 0] : | params_flow.rb:64:10:64:13 | ...[...] | | params_flow.rb:66:12:66:16 | * ... [element 0] : | params_flow.rb:63:16:63:17 | *x [element 0] : | @@ -75,16 +80,20 @@ nodes | params_flow.rb:33:12:33:19 | call to taint : | semmle.label | call to taint : | | params_flow.rb:33:26:33:34 | call to taint : | semmle.label | call to taint : | | params_flow.rb:33:41:33:49 | call to taint : | semmle.label | call to taint : | +| params_flow.rb:34:1:34:4 | args [element :p3] : | semmle.label | args [element :p3] : | | params_flow.rb:34:14:34:22 | call to taint : | semmle.label | call to taint : | | params_flow.rb:35:12:35:20 | call to taint : | semmle.label | call to taint : | | params_flow.rb:35:23:35:28 | ** ... [element :p3] : | semmle.label | ** ... [element :p3] : | | params_flow.rb:35:25:35:28 | args [element :p3] : | semmle.label | args [element :p3] : | +| params_flow.rb:37:1:37:4 | args [element :p1] : | semmle.label | args [element :p1] : | +| params_flow.rb:37:1:37:4 | args [element :p2] : | semmle.label | args [element :p2] : | | params_flow.rb:37:16:37:24 | call to taint : | semmle.label | call to taint : | | params_flow.rb:37:34:37:42 | call to taint : | semmle.label | call to taint : | | params_flow.rb:38:8:38:13 | ** ... [element :p1] : | semmle.label | ** ... [element :p1] : | | params_flow.rb:38:8:38:13 | ** ... [element :p2] : | semmle.label | ** ... [element :p2] : | | params_flow.rb:38:10:38:13 | args [element :p1] : | semmle.label | args [element :p1] : | | params_flow.rb:38:10:38:13 | args [element :p2] : | semmle.label | args [element :p2] : | +| params_flow.rb:40:1:40:4 | args [element :p1] : | semmle.label | args [element :p1] : | | params_flow.rb:40:16:40:24 | call to taint : | semmle.label | call to taint : | | params_flow.rb:41:13:41:21 | call to taint : | semmle.label | call to taint : | | params_flow.rb:41:24:41:29 | ** ... [element :p1] : | semmle.label | ** ... [element :p1] : | @@ -94,6 +103,7 @@ nodes | params_flow.rb:50:10:50:11 | p1 | semmle.label | p1 | | params_flow.rb:54:9:54:17 | call to taint : | semmle.label | call to taint : | | params_flow.rb:57:9:57:17 | call to taint : | semmle.label | call to taint : | +| params_flow.rb:62:1:62:4 | args : | semmle.label | args : | | params_flow.rb:62:8:62:16 | call to taint : | semmle.label | call to taint : | | params_flow.rb:63:16:63:17 | *x [element 0] : | semmle.label | *x [element 0] : | | params_flow.rb:64:10:64:10 | x [element 0] : | semmle.label | x [element 0] : | diff --git a/ruby/ql/test/library-tests/dataflow/pathname-flow/pathame-flow.expected b/ruby/ql/test/library-tests/dataflow/pathname-flow/pathame-flow.expected index a13e860bd04..b248ef21157 100644 --- a/ruby/ql/test/library-tests/dataflow/pathname-flow/pathame-flow.expected +++ b/ruby/ql/test/library-tests/dataflow/pathname-flow/pathame-flow.expected @@ -1,216 +1,290 @@ failures edges -| pathname_flow.rb:4:10:4:33 | call to new : | pathname_flow.rb:5:10:5:11 | pn | +| pathname_flow.rb:4:5:4:6 | pn : | pathname_flow.rb:5:10:5:11 | pn | +| pathname_flow.rb:4:10:4:33 | call to new : | pathname_flow.rb:4:5:4:6 | pn : | | pathname_flow.rb:4:23:4:32 | call to source : | pathname_flow.rb:4:10:4:33 | call to new : | -| pathname_flow.rb:9:7:9:30 | call to new : | pathname_flow.rb:11:8:11:12 | ... + ... | +| pathname_flow.rb:9:3:9:3 | a : | pathname_flow.rb:11:8:11:12 | ... + ... | +| pathname_flow.rb:9:7:9:30 | call to new : | pathname_flow.rb:9:3:9:3 | a : | | pathname_flow.rb:9:20:9:29 | call to source : | pathname_flow.rb:9:7:9:30 | call to new : | -| pathname_flow.rb:10:7:10:30 | call to new : | pathname_flow.rb:11:8:11:12 | ... + ... | +| pathname_flow.rb:10:3:10:3 | b : | pathname_flow.rb:11:8:11:12 | ... + ... | +| pathname_flow.rb:10:7:10:30 | call to new : | pathname_flow.rb:10:3:10:3 | b : | | pathname_flow.rb:10:20:10:29 | call to source : | pathname_flow.rb:10:7:10:30 | call to new : | -| pathname_flow.rb:15:8:15:31 | call to new : | pathname_flow.rb:16:8:16:9 | pn : | +| pathname_flow.rb:15:3:15:4 | pn : | pathname_flow.rb:16:8:16:9 | pn : | +| pathname_flow.rb:15:8:15:31 | call to new : | pathname_flow.rb:15:3:15:4 | pn : | | pathname_flow.rb:15:21:15:30 | call to source : | pathname_flow.rb:15:8:15:31 | call to new : | | pathname_flow.rb:16:8:16:9 | pn : | pathname_flow.rb:16:8:16:17 | call to dirname | -| pathname_flow.rb:20:7:20:30 | call to new : | pathname_flow.rb:21:3:21:3 | a : | +| pathname_flow.rb:20:3:20:3 | a : | pathname_flow.rb:21:3:21:3 | a : | +| pathname_flow.rb:20:7:20:30 | call to new : | pathname_flow.rb:20:3:20:3 | a : | | pathname_flow.rb:20:20:20:29 | call to source : | pathname_flow.rb:20:7:20:30 | call to new : | | pathname_flow.rb:21:3:21:3 | a : | pathname_flow.rb:21:23:21:23 | x : | | pathname_flow.rb:21:23:21:23 | x : | pathname_flow.rb:22:10:22:10 | x | -| pathname_flow.rb:27:7:27:30 | call to new : | pathname_flow.rb:28:8:28:8 | a : | +| pathname_flow.rb:27:3:27:3 | a : | pathname_flow.rb:28:8:28:8 | a : | +| pathname_flow.rb:27:7:27:30 | call to new : | pathname_flow.rb:27:3:27:3 | a : | | pathname_flow.rb:27:20:27:29 | call to source : | pathname_flow.rb:27:7:27:30 | call to new : | | pathname_flow.rb:28:8:28:8 | a : | pathname_flow.rb:28:8:28:22 | call to expand_path | -| pathname_flow.rb:32:7:32:30 | call to new : | pathname_flow.rb:35:8:35:8 | a : | +| pathname_flow.rb:32:3:32:3 | a : | pathname_flow.rb:35:8:35:8 | a : | +| pathname_flow.rb:32:7:32:30 | call to new : | pathname_flow.rb:32:3:32:3 | a : | | pathname_flow.rb:32:20:32:29 | call to source : | pathname_flow.rb:32:7:32:30 | call to new : | -| pathname_flow.rb:34:7:34:30 | call to new : | pathname_flow.rb:35:18:35:18 | c : | +| pathname_flow.rb:34:3:34:3 | c : | pathname_flow.rb:35:18:35:18 | c : | +| pathname_flow.rb:34:7:34:30 | call to new : | pathname_flow.rb:34:3:34:3 | c : | | pathname_flow.rb:34:20:34:29 | call to source : | pathname_flow.rb:34:7:34:30 | call to new : | | pathname_flow.rb:35:8:35:8 | a : | pathname_flow.rb:35:8:35:19 | call to join | | pathname_flow.rb:35:18:35:18 | c : | pathname_flow.rb:35:8:35:19 | call to join | -| pathname_flow.rb:39:7:39:30 | call to new : | pathname_flow.rb:40:8:40:8 | a : | +| pathname_flow.rb:39:3:39:3 | a : | pathname_flow.rb:40:8:40:8 | a : | +| pathname_flow.rb:39:7:39:30 | call to new : | pathname_flow.rb:39:3:39:3 | a : | | pathname_flow.rb:39:20:39:29 | call to source : | pathname_flow.rb:39:7:39:30 | call to new : | | pathname_flow.rb:40:8:40:8 | a : | pathname_flow.rb:40:8:40:17 | call to parent | -| pathname_flow.rb:44:7:44:30 | call to new : | pathname_flow.rb:45:8:45:8 | a : | +| pathname_flow.rb:44:3:44:3 | a : | pathname_flow.rb:45:8:45:8 | a : | +| pathname_flow.rb:44:7:44:30 | call to new : | pathname_flow.rb:44:3:44:3 | a : | | pathname_flow.rb:44:20:44:29 | call to source : | pathname_flow.rb:44:7:44:30 | call to new : | | pathname_flow.rb:45:8:45:8 | a : | pathname_flow.rb:45:8:45:19 | call to realpath | -| pathname_flow.rb:49:7:49:30 | call to new : | pathname_flow.rb:50:8:50:8 | a : | +| pathname_flow.rb:49:3:49:3 | a : | pathname_flow.rb:50:8:50:8 | a : | +| pathname_flow.rb:49:7:49:30 | call to new : | pathname_flow.rb:49:3:49:3 | a : | | pathname_flow.rb:49:20:49:29 | call to source : | pathname_flow.rb:49:7:49:30 | call to new : | | pathname_flow.rb:50:8:50:8 | a : | pathname_flow.rb:50:8:50:39 | call to relative_path_from | -| pathname_flow.rb:54:7:54:30 | call to new : | pathname_flow.rb:55:8:55:8 | a : | +| pathname_flow.rb:54:3:54:3 | a : | pathname_flow.rb:55:8:55:8 | a : | +| pathname_flow.rb:54:7:54:30 | call to new : | pathname_flow.rb:54:3:54:3 | a : | | pathname_flow.rb:54:20:54:29 | call to source : | pathname_flow.rb:54:7:54:30 | call to new : | | pathname_flow.rb:55:8:55:8 | a : | pathname_flow.rb:55:8:55:16 | call to to_path | -| pathname_flow.rb:59:7:59:30 | call to new : | pathname_flow.rb:60:8:60:8 | a : | +| pathname_flow.rb:59:3:59:3 | a : | pathname_flow.rb:60:8:60:8 | a : | +| pathname_flow.rb:59:7:59:30 | call to new : | pathname_flow.rb:59:3:59:3 | a : | | pathname_flow.rb:59:20:59:29 | call to source : | pathname_flow.rb:59:7:59:30 | call to new : | | pathname_flow.rb:60:8:60:8 | a : | pathname_flow.rb:60:8:60:13 | call to to_s | -| pathname_flow.rb:64:7:64:30 | call to new : | pathname_flow.rb:66:8:66:8 | b | +| pathname_flow.rb:64:3:64:3 | a : | pathname_flow.rb:65:3:65:3 | b : | +| pathname_flow.rb:64:7:64:30 | call to new : | pathname_flow.rb:64:3:64:3 | a : | | pathname_flow.rb:64:20:64:29 | call to source : | pathname_flow.rb:64:7:64:30 | call to new : | -| pathname_flow.rb:70:7:70:30 | call to new : | pathname_flow.rb:72:8:72:8 | b | +| pathname_flow.rb:65:3:65:3 | b : | pathname_flow.rb:66:8:66:8 | b | +| pathname_flow.rb:70:3:70:3 | a : | pathname_flow.rb:71:3:71:3 | b : | +| pathname_flow.rb:70:7:70:30 | call to new : | pathname_flow.rb:70:3:70:3 | a : | | pathname_flow.rb:70:20:70:29 | call to source : | pathname_flow.rb:70:7:70:30 | call to new : | -| pathname_flow.rb:76:7:76:30 | call to new : | pathname_flow.rb:77:7:77:7 | a : | +| pathname_flow.rb:71:3:71:3 | b : | pathname_flow.rb:72:8:72:8 | b | +| pathname_flow.rb:76:3:76:3 | a : | pathname_flow.rb:77:7:77:7 | a : | +| pathname_flow.rb:76:7:76:30 | call to new : | pathname_flow.rb:76:3:76:3 | a : | | pathname_flow.rb:76:20:76:29 | call to source : | pathname_flow.rb:76:7:76:30 | call to new : | +| pathname_flow.rb:77:3:77:3 | b : | pathname_flow.rb:78:8:78:8 | b | | pathname_flow.rb:77:7:77:7 | a : | pathname_flow.rb:77:7:77:16 | call to basename : | -| pathname_flow.rb:77:7:77:16 | call to basename : | pathname_flow.rb:78:8:78:8 | b | -| pathname_flow.rb:82:7:82:30 | call to new : | pathname_flow.rb:83:7:83:7 | a : | +| pathname_flow.rb:77:7:77:16 | call to basename : | pathname_flow.rb:77:3:77:3 | b : | +| pathname_flow.rb:82:3:82:3 | a : | pathname_flow.rb:83:7:83:7 | a : | +| pathname_flow.rb:82:7:82:30 | call to new : | pathname_flow.rb:82:3:82:3 | a : | | pathname_flow.rb:82:20:82:29 | call to source : | pathname_flow.rb:82:7:82:30 | call to new : | +| pathname_flow.rb:83:3:83:3 | b : | pathname_flow.rb:84:8:84:8 | b | | pathname_flow.rb:83:7:83:7 | a : | pathname_flow.rb:83:7:83:17 | call to cleanpath : | -| pathname_flow.rb:83:7:83:17 | call to cleanpath : | pathname_flow.rb:84:8:84:8 | b | -| pathname_flow.rb:88:7:88:30 | call to new : | pathname_flow.rb:89:7:89:7 | a : | +| pathname_flow.rb:83:7:83:17 | call to cleanpath : | pathname_flow.rb:83:3:83:3 | b : | +| pathname_flow.rb:88:3:88:3 | a : | pathname_flow.rb:89:7:89:7 | a : | +| pathname_flow.rb:88:7:88:30 | call to new : | pathname_flow.rb:88:3:88:3 | a : | | pathname_flow.rb:88:20:88:29 | call to source : | pathname_flow.rb:88:7:88:30 | call to new : | +| pathname_flow.rb:89:3:89:3 | b : | pathname_flow.rb:90:8:90:8 | b | | pathname_flow.rb:89:7:89:7 | a : | pathname_flow.rb:89:7:89:25 | call to sub : | -| pathname_flow.rb:89:7:89:25 | call to sub : | pathname_flow.rb:90:8:90:8 | b | -| pathname_flow.rb:94:7:94:30 | call to new : | pathname_flow.rb:95:7:95:7 | a : | +| pathname_flow.rb:89:7:89:25 | call to sub : | pathname_flow.rb:89:3:89:3 | b : | +| pathname_flow.rb:94:3:94:3 | a : | pathname_flow.rb:95:7:95:7 | a : | +| pathname_flow.rb:94:7:94:30 | call to new : | pathname_flow.rb:94:3:94:3 | a : | | pathname_flow.rb:94:20:94:29 | call to source : | pathname_flow.rb:94:7:94:30 | call to new : | +| pathname_flow.rb:95:3:95:3 | b : | pathname_flow.rb:96:8:96:8 | b | | pathname_flow.rb:95:7:95:7 | a : | pathname_flow.rb:95:7:95:23 | call to sub_ext : | -| pathname_flow.rb:95:7:95:23 | call to sub_ext : | pathname_flow.rb:96:8:96:8 | b | -| pathname_flow.rb:101:7:101:30 | call to new : | pathname_flow.rb:104:8:104:8 | b : | -| pathname_flow.rb:101:7:101:30 | call to new : | pathname_flow.rb:107:8:107:8 | c : | -| pathname_flow.rb:101:7:101:30 | call to new : | pathname_flow.rb:109:7:109:7 | a : | -| pathname_flow.rb:101:7:101:30 | call to new : | pathname_flow.rb:112:7:112:7 | a : | -| pathname_flow.rb:101:7:101:30 | call to new : | pathname_flow.rb:115:7:115:7 | a : | -| pathname_flow.rb:101:7:101:30 | call to new : | pathname_flow.rb:118:7:118:7 | a : | -| pathname_flow.rb:101:7:101:30 | call to new : | pathname_flow.rb:121:7:121:7 | a : | -| pathname_flow.rb:101:7:101:30 | call to new : | pathname_flow.rb:124:7:124:7 | a : | -| pathname_flow.rb:101:7:101:30 | call to new : | pathname_flow.rb:127:7:127:7 | a : | -| pathname_flow.rb:101:7:101:30 | call to new : | pathname_flow.rb:130:7:130:7 | a : | -| pathname_flow.rb:101:7:101:30 | call to new : | pathname_flow.rb:133:7:133:7 | a : | +| pathname_flow.rb:95:7:95:23 | call to sub_ext : | pathname_flow.rb:95:3:95:3 | b : | +| pathname_flow.rb:101:3:101:3 | a : | pathname_flow.rb:103:3:103:3 | b : | +| pathname_flow.rb:101:3:101:3 | a : | pathname_flow.rb:106:3:106:3 | c : | +| pathname_flow.rb:101:3:101:3 | a : | pathname_flow.rb:109:7:109:7 | a : | +| pathname_flow.rb:101:3:101:3 | a : | pathname_flow.rb:112:7:112:7 | a : | +| pathname_flow.rb:101:3:101:3 | a : | pathname_flow.rb:115:7:115:7 | a : | +| pathname_flow.rb:101:3:101:3 | a : | pathname_flow.rb:118:7:118:7 | a : | +| pathname_flow.rb:101:3:101:3 | a : | pathname_flow.rb:121:7:121:7 | a : | +| pathname_flow.rb:101:3:101:3 | a : | pathname_flow.rb:124:7:124:7 | a : | +| pathname_flow.rb:101:3:101:3 | a : | pathname_flow.rb:127:7:127:7 | a : | +| pathname_flow.rb:101:3:101:3 | a : | pathname_flow.rb:130:7:130:7 | a : | +| pathname_flow.rb:101:3:101:3 | a : | pathname_flow.rb:133:7:133:7 | a : | +| pathname_flow.rb:101:7:101:30 | call to new : | pathname_flow.rb:101:3:101:3 | a : | | pathname_flow.rb:101:20:101:29 | call to source : | pathname_flow.rb:101:7:101:30 | call to new : | +| pathname_flow.rb:103:3:103:3 | b : | pathname_flow.rb:104:8:104:8 | b : | | pathname_flow.rb:104:8:104:8 | b : | pathname_flow.rb:104:8:104:17 | call to realpath | +| pathname_flow.rb:106:3:106:3 | c : | pathname_flow.rb:107:8:107:8 | c : | | pathname_flow.rb:107:8:107:8 | c : | pathname_flow.rb:107:8:107:17 | call to realpath | +| pathname_flow.rb:109:3:109:3 | d : | pathname_flow.rb:110:8:110:8 | d : | | pathname_flow.rb:109:7:109:7 | a : | pathname_flow.rb:109:7:109:16 | call to basename : | -| pathname_flow.rb:109:7:109:16 | call to basename : | pathname_flow.rb:110:8:110:8 | d : | +| pathname_flow.rb:109:7:109:16 | call to basename : | pathname_flow.rb:109:3:109:3 | d : | | pathname_flow.rb:110:8:110:8 | d : | pathname_flow.rb:110:8:110:17 | call to realpath | +| pathname_flow.rb:112:3:112:3 | e : | pathname_flow.rb:113:8:113:8 | e : | | pathname_flow.rb:112:7:112:7 | a : | pathname_flow.rb:112:7:112:17 | call to cleanpath : | -| pathname_flow.rb:112:7:112:17 | call to cleanpath : | pathname_flow.rb:113:8:113:8 | e : | +| pathname_flow.rb:112:7:112:17 | call to cleanpath : | pathname_flow.rb:112:3:112:3 | e : | | pathname_flow.rb:113:8:113:8 | e : | pathname_flow.rb:113:8:113:17 | call to realpath | +| pathname_flow.rb:115:3:115:3 | f : | pathname_flow.rb:116:8:116:8 | f : | | pathname_flow.rb:115:7:115:7 | a : | pathname_flow.rb:115:7:115:19 | call to expand_path : | -| pathname_flow.rb:115:7:115:19 | call to expand_path : | pathname_flow.rb:116:8:116:8 | f : | +| pathname_flow.rb:115:7:115:19 | call to expand_path : | pathname_flow.rb:115:3:115:3 | f : | | pathname_flow.rb:116:8:116:8 | f : | pathname_flow.rb:116:8:116:17 | call to realpath | +| pathname_flow.rb:118:3:118:3 | g : | pathname_flow.rb:119:8:119:8 | g : | | pathname_flow.rb:118:7:118:7 | a : | pathname_flow.rb:118:7:118:19 | call to join : | -| pathname_flow.rb:118:7:118:19 | call to join : | pathname_flow.rb:119:8:119:8 | g : | +| pathname_flow.rb:118:7:118:19 | call to join : | pathname_flow.rb:118:3:118:3 | g : | | pathname_flow.rb:119:8:119:8 | g : | pathname_flow.rb:119:8:119:17 | call to realpath | +| pathname_flow.rb:121:3:121:3 | h : | pathname_flow.rb:122:8:122:8 | h : | | pathname_flow.rb:121:7:121:7 | a : | pathname_flow.rb:121:7:121:16 | call to realpath : | -| pathname_flow.rb:121:7:121:16 | call to realpath : | pathname_flow.rb:122:8:122:8 | h : | +| pathname_flow.rb:121:7:121:16 | call to realpath : | pathname_flow.rb:121:3:121:3 | h : | | pathname_flow.rb:122:8:122:8 | h : | pathname_flow.rb:122:8:122:17 | call to realpath | +| pathname_flow.rb:124:3:124:3 | i : | pathname_flow.rb:125:8:125:8 | i : | | pathname_flow.rb:124:7:124:7 | a : | pathname_flow.rb:124:7:124:38 | call to relative_path_from : | -| pathname_flow.rb:124:7:124:38 | call to relative_path_from : | pathname_flow.rb:125:8:125:8 | i : | +| pathname_flow.rb:124:7:124:38 | call to relative_path_from : | pathname_flow.rb:124:3:124:3 | i : | | pathname_flow.rb:125:8:125:8 | i : | pathname_flow.rb:125:8:125:17 | call to realpath | +| pathname_flow.rb:127:3:127:3 | j : | pathname_flow.rb:128:8:128:8 | j : | | pathname_flow.rb:127:7:127:7 | a : | pathname_flow.rb:127:7:127:25 | call to sub : | -| pathname_flow.rb:127:7:127:25 | call to sub : | pathname_flow.rb:128:8:128:8 | j : | +| pathname_flow.rb:127:7:127:25 | call to sub : | pathname_flow.rb:127:3:127:3 | j : | | pathname_flow.rb:128:8:128:8 | j : | pathname_flow.rb:128:8:128:17 | call to realpath | +| pathname_flow.rb:130:3:130:3 | k : | pathname_flow.rb:131:8:131:8 | k : | | pathname_flow.rb:130:7:130:7 | a : | pathname_flow.rb:130:7:130:23 | call to sub_ext : | -| pathname_flow.rb:130:7:130:23 | call to sub_ext : | pathname_flow.rb:131:8:131:8 | k : | +| pathname_flow.rb:130:7:130:23 | call to sub_ext : | pathname_flow.rb:130:3:130:3 | k : | | pathname_flow.rb:131:8:131:8 | k : | pathname_flow.rb:131:8:131:17 | call to realpath | +| pathname_flow.rb:133:3:133:3 | l : | pathname_flow.rb:134:8:134:8 | l : | | pathname_flow.rb:133:7:133:7 | a : | pathname_flow.rb:133:7:133:15 | call to to_path : | -| pathname_flow.rb:133:7:133:15 | call to to_path : | pathname_flow.rb:134:8:134:8 | l : | +| pathname_flow.rb:133:7:133:15 | call to to_path : | pathname_flow.rb:133:3:133:3 | l : | | pathname_flow.rb:134:8:134:8 | l : | pathname_flow.rb:134:8:134:17 | call to realpath | nodes +| pathname_flow.rb:4:5:4:6 | pn : | semmle.label | pn : | | pathname_flow.rb:4:10:4:33 | call to new : | semmle.label | call to new : | | pathname_flow.rb:4:23:4:32 | call to source : | semmle.label | call to source : | | pathname_flow.rb:5:10:5:11 | pn | semmle.label | pn | +| pathname_flow.rb:9:3:9:3 | a : | semmle.label | a : | | pathname_flow.rb:9:7:9:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:9:20:9:29 | call to source : | semmle.label | call to source : | +| pathname_flow.rb:10:3:10:3 | b : | semmle.label | b : | | pathname_flow.rb:10:7:10:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:10:20:10:29 | call to source : | semmle.label | call to source : | | pathname_flow.rb:11:8:11:12 | ... + ... | semmle.label | ... + ... | +| pathname_flow.rb:15:3:15:4 | pn : | semmle.label | pn : | | pathname_flow.rb:15:8:15:31 | call to new : | semmle.label | call to new : | | pathname_flow.rb:15:21:15:30 | call to source : | semmle.label | call to source : | | pathname_flow.rb:16:8:16:9 | pn : | semmle.label | pn : | | pathname_flow.rb:16:8:16:17 | call to dirname | semmle.label | call to dirname | +| pathname_flow.rb:20:3:20:3 | a : | semmle.label | a : | | pathname_flow.rb:20:7:20:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:20:20:20:29 | call to source : | semmle.label | call to source : | | pathname_flow.rb:21:3:21:3 | a : | semmle.label | a : | | pathname_flow.rb:21:23:21:23 | x : | semmle.label | x : | | pathname_flow.rb:22:10:22:10 | x | semmle.label | x | +| pathname_flow.rb:27:3:27:3 | a : | semmle.label | a : | | pathname_flow.rb:27:7:27:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:27:20:27:29 | call to source : | semmle.label | call to source : | | pathname_flow.rb:28:8:28:8 | a : | semmle.label | a : | | pathname_flow.rb:28:8:28:22 | call to expand_path | semmle.label | call to expand_path | +| pathname_flow.rb:32:3:32:3 | a : | semmle.label | a : | | pathname_flow.rb:32:7:32:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:32:20:32:29 | call to source : | semmle.label | call to source : | +| pathname_flow.rb:34:3:34:3 | c : | semmle.label | c : | | pathname_flow.rb:34:7:34:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:34:20:34:29 | call to source : | semmle.label | call to source : | | pathname_flow.rb:35:8:35:8 | a : | semmle.label | a : | | pathname_flow.rb:35:8:35:19 | call to join | semmle.label | call to join | | pathname_flow.rb:35:18:35:18 | c : | semmle.label | c : | +| pathname_flow.rb:39:3:39:3 | a : | semmle.label | a : | | pathname_flow.rb:39:7:39:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:39:20:39:29 | call to source : | semmle.label | call to source : | | pathname_flow.rb:40:8:40:8 | a : | semmle.label | a : | | pathname_flow.rb:40:8:40:17 | call to parent | semmle.label | call to parent | +| pathname_flow.rb:44:3:44:3 | a : | semmle.label | a : | | pathname_flow.rb:44:7:44:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:44:20:44:29 | call to source : | semmle.label | call to source : | | pathname_flow.rb:45:8:45:8 | a : | semmle.label | a : | | pathname_flow.rb:45:8:45:19 | call to realpath | semmle.label | call to realpath | +| pathname_flow.rb:49:3:49:3 | a : | semmle.label | a : | | pathname_flow.rb:49:7:49:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:49:20:49:29 | call to source : | semmle.label | call to source : | | pathname_flow.rb:50:8:50:8 | a : | semmle.label | a : | | pathname_flow.rb:50:8:50:39 | call to relative_path_from | semmle.label | call to relative_path_from | +| pathname_flow.rb:54:3:54:3 | a : | semmle.label | a : | | pathname_flow.rb:54:7:54:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:54:20:54:29 | call to source : | semmle.label | call to source : | | pathname_flow.rb:55:8:55:8 | a : | semmle.label | a : | | pathname_flow.rb:55:8:55:16 | call to to_path | semmle.label | call to to_path | +| pathname_flow.rb:59:3:59:3 | a : | semmle.label | a : | | pathname_flow.rb:59:7:59:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:59:20:59:29 | call to source : | semmle.label | call to source : | | pathname_flow.rb:60:8:60:8 | a : | semmle.label | a : | | pathname_flow.rb:60:8:60:13 | call to to_s | semmle.label | call to to_s | +| pathname_flow.rb:64:3:64:3 | a : | semmle.label | a : | | pathname_flow.rb:64:7:64:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:64:20:64:29 | call to source : | semmle.label | call to source : | +| pathname_flow.rb:65:3:65:3 | b : | semmle.label | b : | | pathname_flow.rb:66:8:66:8 | b | semmle.label | b | +| pathname_flow.rb:70:3:70:3 | a : | semmle.label | a : | | pathname_flow.rb:70:7:70:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:70:20:70:29 | call to source : | semmle.label | call to source : | +| pathname_flow.rb:71:3:71:3 | b : | semmle.label | b : | | pathname_flow.rb:72:8:72:8 | b | semmle.label | b | +| pathname_flow.rb:76:3:76:3 | a : | semmle.label | a : | | pathname_flow.rb:76:7:76:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:76:20:76:29 | call to source : | semmle.label | call to source : | +| pathname_flow.rb:77:3:77:3 | b : | semmle.label | b : | | pathname_flow.rb:77:7:77:7 | a : | semmle.label | a : | | pathname_flow.rb:77:7:77:16 | call to basename : | semmle.label | call to basename : | | pathname_flow.rb:78:8:78:8 | b | semmle.label | b | +| pathname_flow.rb:82:3:82:3 | a : | semmle.label | a : | | pathname_flow.rb:82:7:82:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:82:20:82:29 | call to source : | semmle.label | call to source : | +| pathname_flow.rb:83:3:83:3 | b : | semmle.label | b : | | pathname_flow.rb:83:7:83:7 | a : | semmle.label | a : | | pathname_flow.rb:83:7:83:17 | call to cleanpath : | semmle.label | call to cleanpath : | | pathname_flow.rb:84:8:84:8 | b | semmle.label | b | +| pathname_flow.rb:88:3:88:3 | a : | semmle.label | a : | | pathname_flow.rb:88:7:88:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:88:20:88:29 | call to source : | semmle.label | call to source : | +| pathname_flow.rb:89:3:89:3 | b : | semmle.label | b : | | pathname_flow.rb:89:7:89:7 | a : | semmle.label | a : | | pathname_flow.rb:89:7:89:25 | call to sub : | semmle.label | call to sub : | | pathname_flow.rb:90:8:90:8 | b | semmle.label | b | +| pathname_flow.rb:94:3:94:3 | a : | semmle.label | a : | | pathname_flow.rb:94:7:94:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:94:20:94:29 | call to source : | semmle.label | call to source : | +| pathname_flow.rb:95:3:95:3 | b : | semmle.label | b : | | pathname_flow.rb:95:7:95:7 | a : | semmle.label | a : | | pathname_flow.rb:95:7:95:23 | call to sub_ext : | semmle.label | call to sub_ext : | | pathname_flow.rb:96:8:96:8 | b | semmle.label | b | +| pathname_flow.rb:101:3:101:3 | a : | semmle.label | a : | | pathname_flow.rb:101:7:101:30 | call to new : | semmle.label | call to new : | | pathname_flow.rb:101:20:101:29 | call to source : | semmle.label | call to source : | +| pathname_flow.rb:103:3:103:3 | b : | semmle.label | b : | | pathname_flow.rb:104:8:104:8 | b : | semmle.label | b : | | pathname_flow.rb:104:8:104:17 | call to realpath | semmle.label | call to realpath | +| pathname_flow.rb:106:3:106:3 | c : | semmle.label | c : | | pathname_flow.rb:107:8:107:8 | c : | semmle.label | c : | | pathname_flow.rb:107:8:107:17 | call to realpath | semmle.label | call to realpath | +| pathname_flow.rb:109:3:109:3 | d : | semmle.label | d : | | pathname_flow.rb:109:7:109:7 | a : | semmle.label | a : | | pathname_flow.rb:109:7:109:16 | call to basename : | semmle.label | call to basename : | | pathname_flow.rb:110:8:110:8 | d : | semmle.label | d : | | pathname_flow.rb:110:8:110:17 | call to realpath | semmle.label | call to realpath | +| pathname_flow.rb:112:3:112:3 | e : | semmle.label | e : | | pathname_flow.rb:112:7:112:7 | a : | semmle.label | a : | | pathname_flow.rb:112:7:112:17 | call to cleanpath : | semmle.label | call to cleanpath : | | pathname_flow.rb:113:8:113:8 | e : | semmle.label | e : | | pathname_flow.rb:113:8:113:17 | call to realpath | semmle.label | call to realpath | +| pathname_flow.rb:115:3:115:3 | f : | semmle.label | f : | | pathname_flow.rb:115:7:115:7 | a : | semmle.label | a : | | pathname_flow.rb:115:7:115:19 | call to expand_path : | semmle.label | call to expand_path : | | pathname_flow.rb:116:8:116:8 | f : | semmle.label | f : | | pathname_flow.rb:116:8:116:17 | call to realpath | semmle.label | call to realpath | +| pathname_flow.rb:118:3:118:3 | g : | semmle.label | g : | | pathname_flow.rb:118:7:118:7 | a : | semmle.label | a : | | pathname_flow.rb:118:7:118:19 | call to join : | semmle.label | call to join : | | pathname_flow.rb:119:8:119:8 | g : | semmle.label | g : | | pathname_flow.rb:119:8:119:17 | call to realpath | semmle.label | call to realpath | +| pathname_flow.rb:121:3:121:3 | h : | semmle.label | h : | | pathname_flow.rb:121:7:121:7 | a : | semmle.label | a : | | pathname_flow.rb:121:7:121:16 | call to realpath : | semmle.label | call to realpath : | | pathname_flow.rb:122:8:122:8 | h : | semmle.label | h : | | pathname_flow.rb:122:8:122:17 | call to realpath | semmle.label | call to realpath | +| pathname_flow.rb:124:3:124:3 | i : | semmle.label | i : | | pathname_flow.rb:124:7:124:7 | a : | semmle.label | a : | | pathname_flow.rb:124:7:124:38 | call to relative_path_from : | semmle.label | call to relative_path_from : | | pathname_flow.rb:125:8:125:8 | i : | semmle.label | i : | | pathname_flow.rb:125:8:125:17 | call to realpath | semmle.label | call to realpath | +| pathname_flow.rb:127:3:127:3 | j : | semmle.label | j : | | pathname_flow.rb:127:7:127:7 | a : | semmle.label | a : | | pathname_flow.rb:127:7:127:25 | call to sub : | semmle.label | call to sub : | | pathname_flow.rb:128:8:128:8 | j : | semmle.label | j : | | pathname_flow.rb:128:8:128:17 | call to realpath | semmle.label | call to realpath | +| pathname_flow.rb:130:3:130:3 | k : | semmle.label | k : | | pathname_flow.rb:130:7:130:7 | a : | semmle.label | a : | | pathname_flow.rb:130:7:130:23 | call to sub_ext : | semmle.label | call to sub_ext : | | pathname_flow.rb:131:8:131:8 | k : | semmle.label | k : | | pathname_flow.rb:131:8:131:17 | call to realpath | semmle.label | call to realpath | +| pathname_flow.rb:133:3:133:3 | l : | semmle.label | l : | | pathname_flow.rb:133:7:133:7 | a : | semmle.label | a : | | pathname_flow.rb:133:7:133:15 | call to to_path : | semmle.label | call to to_path : | | pathname_flow.rb:134:8:134:8 | l : | semmle.label | l : | diff --git a/ruby/ql/test/library-tests/dataflow/string-flow/string-flow.expected b/ruby/ql/test/library-tests/dataflow/string-flow/string-flow.expected index 122a1d8eb1f..651a6affec7 100644 --- a/ruby/ql/test/library-tests/dataflow/string-flow/string-flow.expected +++ b/ruby/ql/test/library-tests/dataflow/string-flow/string-flow.expected @@ -2,126 +2,161 @@ failures | string_flow.rb:85:10:85:10 | a | Unexpected result: hasValueFlow=a | | string_flow.rb:227:10:227:10 | a | Unexpected result: hasValueFlow=a | edges -| string_flow.rb:2:9:2:18 | call to source : | string_flow.rb:3:21:3:21 | a : | -| string_flow.rb:2:9:2:18 | call to source : | string_flow.rb:3:21:3:21 | a : | +| string_flow.rb:2:5:2:5 | a : | string_flow.rb:3:21:3:21 | a : | +| string_flow.rb:2:5:2:5 | a : | string_flow.rb:3:21:3:21 | a : | +| string_flow.rb:2:9:2:18 | call to source : | string_flow.rb:2:5:2:5 | a : | +| string_flow.rb:2:9:2:18 | call to source : | string_flow.rb:2:5:2:5 | a : | | string_flow.rb:3:21:3:21 | a : | string_flow.rb:3:10:3:22 | call to new | | string_flow.rb:3:21:3:21 | a : | string_flow.rb:3:10:3:22 | call to new | -| string_flow.rb:7:9:7:18 | call to source : | string_flow.rb:9:29:9:29 | a : | -| string_flow.rb:8:9:8:16 | call to source : | string_flow.rb:10:29:10:29 | b : | +| string_flow.rb:7:5:7:5 | a : | string_flow.rb:9:29:9:29 | a : | +| string_flow.rb:7:9:7:18 | call to source : | string_flow.rb:7:5:7:5 | a : | +| string_flow.rb:8:5:8:5 | b : | string_flow.rb:10:29:10:29 | b : | +| string_flow.rb:8:9:8:16 | call to source : | string_flow.rb:8:5:8:5 | b : | | string_flow.rb:9:29:9:29 | a : | string_flow.rb:9:10:9:30 | call to try_convert | | string_flow.rb:10:29:10:29 | b : | string_flow.rb:10:10:10:30 | call to try_convert | -| string_flow.rb:14:9:14:18 | call to source : | string_flow.rb:15:10:15:17 | ... % ... | -| string_flow.rb:14:9:14:18 | call to source : | string_flow.rb:15:17:15:17 | a : | -| string_flow.rb:14:9:14:18 | call to source : | string_flow.rb:16:10:16:29 | ... % ... | -| string_flow.rb:14:9:14:18 | call to source : | string_flow.rb:16:28:16:28 | a : | -| string_flow.rb:14:9:14:18 | call to source : | string_flow.rb:17:10:17:10 | a : | -| string_flow.rb:14:9:14:18 | call to source : | string_flow.rb:17:10:17:18 | ... % ... | +| string_flow.rb:14:5:14:5 | a : | string_flow.rb:15:10:15:17 | ... % ... | +| string_flow.rb:14:5:14:5 | a : | string_flow.rb:15:17:15:17 | a : | +| string_flow.rb:14:5:14:5 | a : | string_flow.rb:16:10:16:29 | ... % ... | +| string_flow.rb:14:5:14:5 | a : | string_flow.rb:16:28:16:28 | a : | +| string_flow.rb:14:5:14:5 | a : | string_flow.rb:17:10:17:10 | a : | +| string_flow.rb:14:5:14:5 | a : | string_flow.rb:17:10:17:18 | ... % ... | +| string_flow.rb:14:9:14:18 | call to source : | string_flow.rb:14:5:14:5 | a : | | string_flow.rb:15:17:15:17 | a : | string_flow.rb:15:10:15:17 | ... % ... | | string_flow.rb:16:28:16:28 | a : | string_flow.rb:16:10:16:29 | ... % ... | | string_flow.rb:17:10:17:10 | a : | string_flow.rb:17:10:17:18 | ... % ... | -| string_flow.rb:21:9:21:18 | call to source : | string_flow.rb:23:10:23:10 | b | -| string_flow.rb:27:9:27:18 | call to source : | string_flow.rb:29:10:29:10 | b | -| string_flow.rb:33:9:33:18 | call to source : | string_flow.rb:35:10:35:10 | b | -| string_flow.rb:33:9:33:18 | call to source : | string_flow.rb:37:10:37:10 | c | -| string_flow.rb:41:9:41:18 | call to source : | string_flow.rb:42:10:42:10 | a : | +| string_flow.rb:21:5:21:5 | a : | string_flow.rb:22:5:22:5 | b : | +| string_flow.rb:21:9:21:18 | call to source : | string_flow.rb:21:5:21:5 | a : | +| string_flow.rb:22:5:22:5 | b : | string_flow.rb:23:10:23:10 | b | +| string_flow.rb:27:5:27:5 | a : | string_flow.rb:28:5:28:5 | b : | +| string_flow.rb:27:9:27:18 | call to source : | string_flow.rb:27:5:27:5 | a : | +| string_flow.rb:28:5:28:5 | b : | string_flow.rb:29:10:29:10 | b | +| string_flow.rb:33:5:33:5 | a : | string_flow.rb:34:5:34:5 | b : | +| string_flow.rb:33:5:33:5 | a : | string_flow.rb:36:5:36:5 | c : | +| string_flow.rb:33:9:33:18 | call to source : | string_flow.rb:33:5:33:5 | a : | +| string_flow.rb:34:5:34:5 | b : | string_flow.rb:35:10:35:10 | b | +| string_flow.rb:36:5:36:5 | c : | string_flow.rb:37:10:37:10 | c | +| string_flow.rb:41:5:41:5 | a : | string_flow.rb:42:10:42:10 | a : | +| string_flow.rb:41:9:41:18 | call to source : | string_flow.rb:41:5:41:5 | a : | | string_flow.rb:42:10:42:10 | a : | string_flow.rb:42:10:42:12 | call to b | -| string_flow.rb:46:9:46:18 | call to source : | string_flow.rb:47:10:47:10 | a : | -| string_flow.rb:46:9:46:18 | call to source : | string_flow.rb:48:10:48:10 | a : | -| string_flow.rb:46:9:46:18 | call to source : | string_flow.rb:49:10:49:10 | a : | +| string_flow.rb:46:5:46:5 | a : | string_flow.rb:47:10:47:10 | a : | +| string_flow.rb:46:5:46:5 | a : | string_flow.rb:48:10:48:10 | a : | +| string_flow.rb:46:5:46:5 | a : | string_flow.rb:49:10:49:10 | a : | +| string_flow.rb:46:9:46:18 | call to source : | string_flow.rb:46:5:46:5 | a : | | string_flow.rb:47:10:47:10 | a : | string_flow.rb:47:10:47:23 | call to byteslice | | string_flow.rb:48:10:48:10 | a : | string_flow.rb:48:10:48:26 | call to byteslice | | string_flow.rb:49:10:49:10 | a : | string_flow.rb:49:10:49:26 | call to byteslice | -| string_flow.rb:53:9:53:18 | call to source : | string_flow.rb:54:10:54:10 | a : | -| string_flow.rb:53:9:53:18 | call to source : | string_flow.rb:55:10:55:10 | a : | +| string_flow.rb:53:5:53:5 | a : | string_flow.rb:54:10:54:10 | a : | +| string_flow.rb:53:5:53:5 | a : | string_flow.rb:55:10:55:10 | a : | +| string_flow.rb:53:9:53:18 | call to source : | string_flow.rb:53:5:53:5 | a : | | string_flow.rb:54:10:54:10 | a : | string_flow.rb:54:10:54:21 | call to capitalize | | string_flow.rb:55:10:55:10 | a : | string_flow.rb:55:10:55:22 | call to capitalize! | -| string_flow.rb:59:9:59:18 | call to source : | string_flow.rb:60:10:60:10 | a : | -| string_flow.rb:59:9:59:18 | call to source : | string_flow.rb:61:27:61:27 | a : | -| string_flow.rb:59:9:59:18 | call to source : | string_flow.rb:62:10:62:10 | a : | -| string_flow.rb:59:9:59:18 | call to source : | string_flow.rb:63:26:63:26 | a : | -| string_flow.rb:59:9:59:18 | call to source : | string_flow.rb:64:10:64:10 | a : | -| string_flow.rb:59:9:59:18 | call to source : | string_flow.rb:65:26:65:26 | a : | +| string_flow.rb:59:5:59:5 | a : | string_flow.rb:60:10:60:10 | a : | +| string_flow.rb:59:5:59:5 | a : | string_flow.rb:61:27:61:27 | a : | +| string_flow.rb:59:5:59:5 | a : | string_flow.rb:62:10:62:10 | a : | +| string_flow.rb:59:5:59:5 | a : | string_flow.rb:63:26:63:26 | a : | +| string_flow.rb:59:5:59:5 | a : | string_flow.rb:64:10:64:10 | a : | +| string_flow.rb:59:5:59:5 | a : | string_flow.rb:65:26:65:26 | a : | +| string_flow.rb:59:9:59:18 | call to source : | string_flow.rb:59:5:59:5 | a : | | string_flow.rb:60:10:60:10 | a : | string_flow.rb:60:10:60:21 | call to center | | string_flow.rb:61:27:61:27 | a : | string_flow.rb:61:10:61:28 | call to center | | string_flow.rb:62:10:62:10 | a : | string_flow.rb:62:10:62:20 | call to ljust | | string_flow.rb:63:26:63:26 | a : | string_flow.rb:63:10:63:27 | call to ljust | | string_flow.rb:64:10:64:10 | a : | string_flow.rb:64:10:64:20 | call to rjust | | string_flow.rb:65:26:65:26 | a : | string_flow.rb:65:10:65:27 | call to rjust | -| string_flow.rb:69:9:69:18 | call to source : | string_flow.rb:70:10:70:10 | a : | -| string_flow.rb:69:9:69:18 | call to source : | string_flow.rb:71:10:71:10 | a : | +| string_flow.rb:69:5:69:5 | a : | string_flow.rb:70:10:70:10 | a : | +| string_flow.rb:69:5:69:5 | a : | string_flow.rb:71:10:71:10 | a : | +| string_flow.rb:69:9:69:18 | call to source : | string_flow.rb:69:5:69:5 | a : | | string_flow.rb:70:10:70:10 | a : | string_flow.rb:70:10:70:16 | call to chomp | | string_flow.rb:71:10:71:10 | a : | string_flow.rb:71:10:71:17 | call to chomp! | -| string_flow.rb:75:9:75:18 | call to source : | string_flow.rb:76:10:76:10 | a : | -| string_flow.rb:75:9:75:18 | call to source : | string_flow.rb:77:10:77:10 | a : | +| string_flow.rb:75:5:75:5 | a : | string_flow.rb:76:10:76:10 | a : | +| string_flow.rb:75:5:75:5 | a : | string_flow.rb:77:10:77:10 | a : | +| string_flow.rb:75:9:75:18 | call to source : | string_flow.rb:75:5:75:5 | a : | | string_flow.rb:76:10:76:10 | a : | string_flow.rb:76:10:76:15 | call to chop | | string_flow.rb:77:10:77:10 | a : | string_flow.rb:77:10:77:16 | call to chop! | -| string_flow.rb:83:9:83:18 | call to source : | string_flow.rb:84:5:84:5 | a : | -| string_flow.rb:83:9:83:18 | call to source : | string_flow.rb:84:5:84:5 | a : | +| string_flow.rb:83:5:83:5 | a : | string_flow.rb:84:5:84:5 | a : | +| string_flow.rb:83:5:83:5 | a : | string_flow.rb:84:5:84:5 | a : | +| string_flow.rb:83:9:83:18 | call to source : | string_flow.rb:83:5:83:5 | a : | +| string_flow.rb:83:9:83:18 | call to source : | string_flow.rb:83:5:83:5 | a : | | string_flow.rb:84:5:84:5 | [post] a : | string_flow.rb:85:10:85:10 | a | | string_flow.rb:84:5:84:5 | [post] a : | string_flow.rb:85:10:85:10 | a | | string_flow.rb:84:5:84:5 | a : | string_flow.rb:84:5:84:5 | [post] a : | | string_flow.rb:84:5:84:5 | a : | string_flow.rb:84:5:84:5 | [post] a : | -| string_flow.rb:108:9:108:18 | call to source : | string_flow.rb:109:10:109:10 | a : | +| string_flow.rb:108:5:108:5 | a : | string_flow.rb:109:10:109:10 | a : | +| string_flow.rb:108:9:108:18 | call to source : | string_flow.rb:108:5:108:5 | a : | | string_flow.rb:109:10:109:10 | [post] a : | string_flow.rb:110:10:110:10 | a : | | string_flow.rb:109:10:109:10 | [post] a : | string_flow.rb:111:10:111:10 | a : | | string_flow.rb:109:10:109:10 | a : | string_flow.rb:109:10:109:10 | [post] a : | | string_flow.rb:109:10:109:10 | a : | string_flow.rb:109:10:109:22 | call to delete | | string_flow.rb:110:10:110:10 | a : | string_flow.rb:110:10:110:29 | call to delete_prefix | | string_flow.rb:111:10:111:10 | a : | string_flow.rb:111:10:111:29 | call to delete_suffix | -| string_flow.rb:115:9:115:18 | call to source : | string_flow.rb:116:10:116:10 | a : | -| string_flow.rb:115:9:115:18 | call to source : | string_flow.rb:117:10:117:10 | a : | -| string_flow.rb:115:9:115:18 | call to source : | string_flow.rb:118:10:118:10 | a : | -| string_flow.rb:115:9:115:18 | call to source : | string_flow.rb:119:10:119:10 | a : | -| string_flow.rb:115:9:115:18 | call to source : | string_flow.rb:120:10:120:10 | a : | -| string_flow.rb:115:9:115:18 | call to source : | string_flow.rb:121:10:121:10 | a : | +| string_flow.rb:115:5:115:5 | a : | string_flow.rb:116:10:116:10 | a : | +| string_flow.rb:115:5:115:5 | a : | string_flow.rb:117:10:117:10 | a : | +| string_flow.rb:115:5:115:5 | a : | string_flow.rb:118:10:118:10 | a : | +| string_flow.rb:115:5:115:5 | a : | string_flow.rb:119:10:119:10 | a : | +| string_flow.rb:115:5:115:5 | a : | string_flow.rb:120:10:120:10 | a : | +| string_flow.rb:115:5:115:5 | a : | string_flow.rb:121:10:121:10 | a : | +| string_flow.rb:115:9:115:18 | call to source : | string_flow.rb:115:5:115:5 | a : | | string_flow.rb:116:10:116:10 | a : | string_flow.rb:116:10:116:19 | call to downcase | | string_flow.rb:117:10:117:10 | a : | string_flow.rb:117:10:117:20 | call to downcase! | | string_flow.rb:118:10:118:10 | a : | string_flow.rb:118:10:118:19 | call to swapcase | | string_flow.rb:119:10:119:10 | a : | string_flow.rb:119:10:119:20 | call to swapcase! | | string_flow.rb:120:10:120:10 | a : | string_flow.rb:120:10:120:17 | call to upcase | | string_flow.rb:121:10:121:10 | a : | string_flow.rb:121:10:121:18 | call to upcase! | -| string_flow.rb:125:9:125:18 | call to source : | string_flow.rb:126:9:126:9 | a : | +| string_flow.rb:125:5:125:5 | a : | string_flow.rb:126:9:126:9 | a : | +| string_flow.rb:125:9:125:18 | call to source : | string_flow.rb:125:5:125:5 | a : | +| string_flow.rb:126:5:126:5 | b : | string_flow.rb:127:10:127:10 | b | +| string_flow.rb:126:5:126:5 | b : | string_flow.rb:128:10:128:10 | b : | | string_flow.rb:126:9:126:9 | a : | string_flow.rb:126:9:126:14 | call to dump : | -| string_flow.rb:126:9:126:14 | call to dump : | string_flow.rb:127:10:127:10 | b | -| string_flow.rb:126:9:126:14 | call to dump : | string_flow.rb:128:10:128:10 | b : | +| string_flow.rb:126:9:126:14 | call to dump : | string_flow.rb:126:5:126:5 | b : | | string_flow.rb:128:10:128:10 | b : | string_flow.rb:128:10:128:17 | call to undump | -| string_flow.rb:132:9:132:18 | call to source : | string_flow.rb:133:9:133:9 | a : | -| string_flow.rb:132:9:132:18 | call to source : | string_flow.rb:135:9:135:9 | a : | +| string_flow.rb:132:5:132:5 | a : | string_flow.rb:133:9:133:9 | a : | +| string_flow.rb:132:5:132:5 | a : | string_flow.rb:135:9:135:9 | a : | +| string_flow.rb:132:9:132:18 | call to source : | string_flow.rb:132:5:132:5 | a : | +| string_flow.rb:133:5:133:5 | b : | string_flow.rb:134:10:134:10 | b | | string_flow.rb:133:9:133:9 | a : | string_flow.rb:133:9:133:40 | call to each_line : | | string_flow.rb:133:9:133:9 | a : | string_flow.rb:133:24:133:27 | line : | -| string_flow.rb:133:9:133:40 | call to each_line : | string_flow.rb:134:10:134:10 | b | +| string_flow.rb:133:9:133:40 | call to each_line : | string_flow.rb:133:5:133:5 | b : | | string_flow.rb:133:24:133:27 | line : | string_flow.rb:133:35:133:38 | line | +| string_flow.rb:135:5:135:5 | c [element] : | string_flow.rb:136:10:136:10 | c [element] : | | string_flow.rb:135:9:135:9 | a : | string_flow.rb:135:9:135:19 | call to each_line [element] : | -| string_flow.rb:135:9:135:19 | call to each_line [element] : | string_flow.rb:136:10:136:10 | c [element] : | +| string_flow.rb:135:9:135:19 | call to each_line [element] : | string_flow.rb:135:5:135:5 | c [element] : | | string_flow.rb:136:10:136:10 | c [element] : | string_flow.rb:136:10:136:15 | call to to_a [element] : | | string_flow.rb:136:10:136:15 | call to to_a [element] : | string_flow.rb:136:10:136:18 | ...[...] | -| string_flow.rb:140:9:140:18 | call to source : | string_flow.rb:141:9:141:9 | a : | -| string_flow.rb:140:9:140:18 | call to source : | string_flow.rb:143:9:143:9 | a : | +| string_flow.rb:140:5:140:5 | a : | string_flow.rb:141:9:141:9 | a : | +| string_flow.rb:140:5:140:5 | a : | string_flow.rb:143:9:143:9 | a : | +| string_flow.rb:140:9:140:18 | call to source : | string_flow.rb:140:5:140:5 | a : | +| string_flow.rb:141:5:141:5 | b : | string_flow.rb:142:10:142:10 | b | | string_flow.rb:141:9:141:9 | a : | string_flow.rb:141:9:141:36 | call to lines : | | string_flow.rb:141:9:141:9 | a : | string_flow.rb:141:20:141:23 | line : | -| string_flow.rb:141:9:141:36 | call to lines : | string_flow.rb:142:10:142:10 | b | +| string_flow.rb:141:9:141:36 | call to lines : | string_flow.rb:141:5:141:5 | b : | | string_flow.rb:141:20:141:23 | line : | string_flow.rb:141:31:141:34 | line | +| string_flow.rb:143:5:143:5 | c [element] : | string_flow.rb:144:10:144:10 | c [element] : | | string_flow.rb:143:9:143:9 | a : | string_flow.rb:143:9:143:15 | call to lines [element] : | -| string_flow.rb:143:9:143:15 | call to lines [element] : | string_flow.rb:144:10:144:10 | c [element] : | +| string_flow.rb:143:9:143:15 | call to lines [element] : | string_flow.rb:143:5:143:5 | c [element] : | | string_flow.rb:144:10:144:10 | c [element] : | string_flow.rb:144:10:144:13 | ...[...] | -| string_flow.rb:148:9:148:18 | call to source : | string_flow.rb:149:10:149:10 | a : | -| string_flow.rb:148:9:148:18 | call to source : | string_flow.rb:150:10:150:10 | a : | -| string_flow.rb:148:9:148:18 | call to source : | string_flow.rb:151:10:151:10 | a : | -| string_flow.rb:148:9:148:18 | call to source : | string_flow.rb:152:10:152:10 | a : | +| string_flow.rb:148:5:148:5 | a : | string_flow.rb:149:10:149:10 | a : | +| string_flow.rb:148:5:148:5 | a : | string_flow.rb:150:10:150:10 | a : | +| string_flow.rb:148:5:148:5 | a : | string_flow.rb:151:10:151:10 | a : | +| string_flow.rb:148:5:148:5 | a : | string_flow.rb:152:10:152:10 | a : | +| string_flow.rb:148:9:148:18 | call to source : | string_flow.rb:148:5:148:5 | a : | | string_flow.rb:149:10:149:10 | a : | string_flow.rb:149:10:149:26 | call to encode | | string_flow.rb:150:10:150:10 | a : | string_flow.rb:150:10:150:27 | call to encode! | | string_flow.rb:151:10:151:10 | a : | string_flow.rb:151:10:151:28 | call to unicode_normalize | | string_flow.rb:152:10:152:10 | a : | string_flow.rb:152:10:152:29 | call to unicode_normalize! | -| string_flow.rb:156:9:156:18 | call to source : | string_flow.rb:157:10:157:10 | a : | +| string_flow.rb:156:5:156:5 | a : | string_flow.rb:157:10:157:10 | a : | +| string_flow.rb:156:9:156:18 | call to source : | string_flow.rb:156:5:156:5 | a : | | string_flow.rb:157:10:157:10 | a : | string_flow.rb:157:10:157:34 | call to force_encoding | -| string_flow.rb:161:9:161:18 | call to source : | string_flow.rb:162:10:162:10 | a : | +| string_flow.rb:161:5:161:5 | a : | string_flow.rb:162:10:162:10 | a : | +| string_flow.rb:161:9:161:18 | call to source : | string_flow.rb:161:5:161:5 | a : | | string_flow.rb:162:10:162:10 | a : | string_flow.rb:162:10:162:17 | call to freeze | -| string_flow.rb:166:9:166:18 | call to source : | string_flow.rb:168:10:168:10 | a : | -| string_flow.rb:166:9:166:18 | call to source : | string_flow.rb:169:10:169:10 | a : | -| string_flow.rb:166:9:166:18 | call to source : | string_flow.rb:170:10:170:10 | a : | -| string_flow.rb:166:9:166:18 | call to source : | string_flow.rb:171:10:171:10 | a : | -| string_flow.rb:167:9:167:18 | call to source : | string_flow.rb:168:22:168:22 | c : | -| string_flow.rb:167:9:167:18 | call to source : | string_flow.rb:169:23:169:23 | c : | +| string_flow.rb:166:5:166:5 | a : | string_flow.rb:168:10:168:10 | a : | +| string_flow.rb:166:5:166:5 | a : | string_flow.rb:169:10:169:10 | a : | +| string_flow.rb:166:5:166:5 | a : | string_flow.rb:170:10:170:10 | a : | +| string_flow.rb:166:5:166:5 | a : | string_flow.rb:171:10:171:10 | a : | +| string_flow.rb:166:9:166:18 | call to source : | string_flow.rb:166:5:166:5 | a : | +| string_flow.rb:167:5:167:5 | c : | string_flow.rb:168:22:168:22 | c : | +| string_flow.rb:167:5:167:5 | c : | string_flow.rb:169:23:169:23 | c : | +| string_flow.rb:167:9:167:18 | call to source : | string_flow.rb:167:5:167:5 | c : | | string_flow.rb:168:10:168:10 | a : | string_flow.rb:168:10:168:23 | call to gsub | | string_flow.rb:168:22:168:22 | c : | string_flow.rb:168:10:168:23 | call to gsub | | string_flow.rb:169:10:169:10 | a : | string_flow.rb:169:10:169:24 | call to gsub! | @@ -130,12 +165,14 @@ edges | string_flow.rb:170:32:170:41 | call to source : | string_flow.rb:170:10:170:43 | call to gsub | | string_flow.rb:171:10:171:10 | a : | string_flow.rb:171:10:171:44 | call to gsub! | | string_flow.rb:171:33:171:42 | call to source : | string_flow.rb:171:10:171:44 | call to gsub! | -| string_flow.rb:175:9:175:18 | call to source : | string_flow.rb:177:10:177:10 | a : | -| string_flow.rb:175:9:175:18 | call to source : | string_flow.rb:178:10:178:10 | a : | -| string_flow.rb:175:9:175:18 | call to source : | string_flow.rb:179:10:179:10 | a : | -| string_flow.rb:175:9:175:18 | call to source : | string_flow.rb:180:10:180:10 | a : | -| string_flow.rb:176:9:176:18 | call to source : | string_flow.rb:177:21:177:21 | c : | -| string_flow.rb:176:9:176:18 | call to source : | string_flow.rb:178:22:178:22 | c : | +| string_flow.rb:175:5:175:5 | a : | string_flow.rb:177:10:177:10 | a : | +| string_flow.rb:175:5:175:5 | a : | string_flow.rb:178:10:178:10 | a : | +| string_flow.rb:175:5:175:5 | a : | string_flow.rb:179:10:179:10 | a : | +| string_flow.rb:175:5:175:5 | a : | string_flow.rb:180:10:180:10 | a : | +| string_flow.rb:175:9:175:18 | call to source : | string_flow.rb:175:5:175:5 | a : | +| string_flow.rb:176:5:176:5 | c : | string_flow.rb:177:21:177:21 | c : | +| string_flow.rb:176:5:176:5 | c : | string_flow.rb:178:22:178:22 | c : | +| string_flow.rb:176:9:176:18 | call to source : | string_flow.rb:176:5:176:5 | c : | | string_flow.rb:177:10:177:10 | a : | string_flow.rb:177:10:177:22 | call to sub | | string_flow.rb:177:21:177:21 | c : | string_flow.rb:177:10:177:22 | call to sub | | string_flow.rb:178:10:178:10 | a : | string_flow.rb:178:10:178:23 | call to sub! | @@ -144,70 +181,84 @@ edges | string_flow.rb:179:31:179:40 | call to source : | string_flow.rb:179:10:179:42 | call to sub | | string_flow.rb:180:10:180:10 | a : | string_flow.rb:180:10:180:43 | call to sub! | | string_flow.rb:180:32:180:41 | call to source : | string_flow.rb:180:10:180:43 | call to sub! | -| string_flow.rb:191:9:191:18 | call to source : | string_flow.rb:192:10:192:10 | a : | +| string_flow.rb:191:5:191:5 | a : | string_flow.rb:192:10:192:10 | a : | +| string_flow.rb:191:9:191:18 | call to source : | string_flow.rb:191:5:191:5 | a : | | string_flow.rb:192:10:192:10 | a : | string_flow.rb:192:10:192:18 | call to inspect | -| string_flow.rb:196:9:196:18 | call to source : | string_flow.rb:197:10:197:10 | a : | -| string_flow.rb:196:9:196:18 | call to source : | string_flow.rb:198:10:198:10 | a : | -| string_flow.rb:196:9:196:18 | call to source : | string_flow.rb:199:10:199:10 | a : | -| string_flow.rb:196:9:196:18 | call to source : | string_flow.rb:200:10:200:10 | a : | -| string_flow.rb:196:9:196:18 | call to source : | string_flow.rb:201:10:201:10 | a : | -| string_flow.rb:196:9:196:18 | call to source : | string_flow.rb:202:10:202:10 | a : | +| string_flow.rb:196:5:196:5 | a : | string_flow.rb:197:10:197:10 | a : | +| string_flow.rb:196:5:196:5 | a : | string_flow.rb:198:10:198:10 | a : | +| string_flow.rb:196:5:196:5 | a : | string_flow.rb:199:10:199:10 | a : | +| string_flow.rb:196:5:196:5 | a : | string_flow.rb:200:10:200:10 | a : | +| string_flow.rb:196:5:196:5 | a : | string_flow.rb:201:10:201:10 | a : | +| string_flow.rb:196:5:196:5 | a : | string_flow.rb:202:10:202:10 | a : | +| string_flow.rb:196:9:196:18 | call to source : | string_flow.rb:196:5:196:5 | a : | | string_flow.rb:197:10:197:10 | a : | string_flow.rb:197:10:197:16 | call to strip | | string_flow.rb:198:10:198:10 | a : | string_flow.rb:198:10:198:17 | call to strip! | | string_flow.rb:199:10:199:10 | a : | string_flow.rb:199:10:199:17 | call to lstrip | | string_flow.rb:200:10:200:10 | a : | string_flow.rb:200:10:200:18 | call to lstrip! | | string_flow.rb:201:10:201:10 | a : | string_flow.rb:201:10:201:17 | call to rstrip | | string_flow.rb:202:10:202:10 | a : | string_flow.rb:202:10:202:18 | call to rstrip! | -| string_flow.rb:206:9:206:18 | call to source : | string_flow.rb:207:10:207:10 | a : | -| string_flow.rb:206:9:206:18 | call to source : | string_flow.rb:208:10:208:10 | a : | -| string_flow.rb:206:9:206:18 | call to source : | string_flow.rb:209:10:209:10 | a : | -| string_flow.rb:206:9:206:18 | call to source : | string_flow.rb:210:10:210:10 | a : | +| string_flow.rb:206:5:206:5 | a : | string_flow.rb:207:10:207:10 | a : | +| string_flow.rb:206:5:206:5 | a : | string_flow.rb:208:10:208:10 | a : | +| string_flow.rb:206:5:206:5 | a : | string_flow.rb:209:10:209:10 | a : | +| string_flow.rb:206:5:206:5 | a : | string_flow.rb:210:10:210:10 | a : | +| string_flow.rb:206:9:206:18 | call to source : | string_flow.rb:206:5:206:5 | a : | | string_flow.rb:207:10:207:10 | a : | string_flow.rb:207:10:207:15 | call to next | | string_flow.rb:208:10:208:10 | a : | string_flow.rb:208:10:208:16 | call to next! | | string_flow.rb:209:10:209:10 | a : | string_flow.rb:209:10:209:15 | call to succ | | string_flow.rb:210:10:210:10 | a : | string_flow.rb:210:10:210:16 | call to succ! | -| string_flow.rb:214:9:214:18 | call to source : | string_flow.rb:215:9:215:9 | a : | +| string_flow.rb:214:5:214:5 | a : | string_flow.rb:215:9:215:9 | a : | +| string_flow.rb:214:9:214:18 | call to source : | string_flow.rb:214:5:214:5 | a : | +| string_flow.rb:215:5:215:5 | b [element 0] : | string_flow.rb:216:10:216:10 | b [element 0] : | +| string_flow.rb:215:5:215:5 | b [element 1] : | string_flow.rb:217:10:217:10 | b [element 1] : | +| string_flow.rb:215:5:215:5 | b [element 2] : | string_flow.rb:218:10:218:10 | b [element 2] : | | string_flow.rb:215:9:215:9 | a : | string_flow.rb:215:9:215:24 | call to partition [element 0] : | | string_flow.rb:215:9:215:9 | a : | string_flow.rb:215:9:215:24 | call to partition [element 1] : | | string_flow.rb:215:9:215:9 | a : | string_flow.rb:215:9:215:24 | call to partition [element 2] : | -| string_flow.rb:215:9:215:24 | call to partition [element 0] : | string_flow.rb:216:10:216:10 | b [element 0] : | -| string_flow.rb:215:9:215:24 | call to partition [element 1] : | string_flow.rb:217:10:217:10 | b [element 1] : | -| string_flow.rb:215:9:215:24 | call to partition [element 2] : | string_flow.rb:218:10:218:10 | b [element 2] : | +| string_flow.rb:215:9:215:24 | call to partition [element 0] : | string_flow.rb:215:5:215:5 | b [element 0] : | +| string_flow.rb:215:9:215:24 | call to partition [element 1] : | string_flow.rb:215:5:215:5 | b [element 1] : | +| string_flow.rb:215:9:215:24 | call to partition [element 2] : | string_flow.rb:215:5:215:5 | b [element 2] : | | string_flow.rb:216:10:216:10 | b [element 0] : | string_flow.rb:216:10:216:13 | ...[...] | | string_flow.rb:217:10:217:10 | b [element 1] : | string_flow.rb:217:10:217:13 | ...[...] | | string_flow.rb:218:10:218:10 | b [element 2] : | string_flow.rb:218:10:218:13 | ...[...] | -| string_flow.rb:223:9:223:18 | call to source : | string_flow.rb:225:10:225:10 | a : | -| string_flow.rb:223:9:223:18 | call to source : | string_flow.rb:225:10:225:10 | a : | -| string_flow.rb:224:9:224:18 | call to source : | string_flow.rb:225:20:225:20 | b : | +| string_flow.rb:223:5:223:5 | a : | string_flow.rb:225:10:225:10 | a : | +| string_flow.rb:223:5:223:5 | a : | string_flow.rb:225:10:225:10 | a : | +| string_flow.rb:223:9:223:18 | call to source : | string_flow.rb:223:5:223:5 | a : | +| string_flow.rb:223:9:223:18 | call to source : | string_flow.rb:223:5:223:5 | a : | +| string_flow.rb:224:5:224:5 | b : | string_flow.rb:225:20:225:20 | b : | +| string_flow.rb:224:9:224:18 | call to source : | string_flow.rb:224:5:224:5 | b : | | string_flow.rb:225:10:225:10 | [post] a : | string_flow.rb:227:10:227:10 | a | | string_flow.rb:225:10:225:10 | [post] a : | string_flow.rb:227:10:227:10 | a | | string_flow.rb:225:10:225:10 | a : | string_flow.rb:225:10:225:10 | [post] a : | | string_flow.rb:225:10:225:10 | a : | string_flow.rb:225:10:225:10 | [post] a : | | string_flow.rb:225:20:225:20 | b : | string_flow.rb:225:10:225:10 | [post] a : | | string_flow.rb:225:20:225:20 | b : | string_flow.rb:225:10:225:21 | call to replace | -| string_flow.rb:231:9:231:18 | call to source : | string_flow.rb:232:10:232:10 | a : | +| string_flow.rb:231:5:231:5 | a : | string_flow.rb:232:10:232:10 | a : | +| string_flow.rb:231:9:231:18 | call to source : | string_flow.rb:231:5:231:5 | a : | | string_flow.rb:232:10:232:10 | a : | string_flow.rb:232:10:232:18 | call to reverse | -| string_flow.rb:236:9:236:18 | call to source : | string_flow.rb:237:9:237:9 | a : | -| string_flow.rb:236:9:236:18 | call to source : | string_flow.rb:238:9:238:9 | a : | -| string_flow.rb:236:9:236:18 | call to source : | string_flow.rb:240:9:240:9 | a : | +| string_flow.rb:236:5:236:5 | a : | string_flow.rb:237:9:237:9 | a : | +| string_flow.rb:236:5:236:5 | a : | string_flow.rb:238:9:238:9 | a : | +| string_flow.rb:236:5:236:5 | a : | string_flow.rb:240:9:240:9 | a : | +| string_flow.rb:236:9:236:18 | call to source : | string_flow.rb:236:5:236:5 | a : | | string_flow.rb:237:9:237:9 | a : | string_flow.rb:237:24:237:24 | x : | | string_flow.rb:237:24:237:24 | x : | string_flow.rb:237:35:237:35 | x | +| string_flow.rb:238:5:238:5 | b : | string_flow.rb:239:10:239:10 | b | | string_flow.rb:238:9:238:9 | a : | string_flow.rb:238:9:238:37 | call to scan : | | string_flow.rb:238:9:238:9 | a : | string_flow.rb:238:27:238:27 | y : | -| string_flow.rb:238:9:238:37 | call to scan : | string_flow.rb:239:10:239:10 | b | +| string_flow.rb:238:9:238:37 | call to scan : | string_flow.rb:238:5:238:5 | b : | | string_flow.rb:238:27:238:27 | y : | string_flow.rb:238:35:238:35 | y | +| string_flow.rb:240:5:240:5 | b [element] : | string_flow.rb:241:10:241:10 | b [element] : | +| string_flow.rb:240:5:240:5 | b [element] : | string_flow.rb:242:10:242:10 | b [element] : | | string_flow.rb:240:9:240:9 | a : | string_flow.rb:240:9:240:19 | call to scan [element] : | -| string_flow.rb:240:9:240:19 | call to scan [element] : | string_flow.rb:241:10:241:10 | b [element] : | -| string_flow.rb:240:9:240:19 | call to scan [element] : | string_flow.rb:242:10:242:10 | b [element] : | +| string_flow.rb:240:9:240:19 | call to scan [element] : | string_flow.rb:240:5:240:5 | b [element] : | | string_flow.rb:241:10:241:10 | b [element] : | string_flow.rb:241:10:241:13 | ...[...] | | string_flow.rb:242:10:242:10 | b [element] : | string_flow.rb:242:10:242:13 | ...[...] | -| string_flow.rb:246:5:246:18 | ... = ... : | string_flow.rb:250:26:250:26 | a : | -| string_flow.rb:246:9:246:18 | call to source : | string_flow.rb:246:5:246:18 | ... = ... : | -| string_flow.rb:246:9:246:18 | call to source : | string_flow.rb:247:10:247:10 | a : | -| string_flow.rb:246:9:246:18 | call to source : | string_flow.rb:248:20:248:20 | a : | -| string_flow.rb:246:9:246:18 | call to source : | string_flow.rb:249:5:249:5 | a : | -| string_flow.rb:246:9:246:18 | call to source : | string_flow.rb:252:10:252:10 | a : | -| string_flow.rb:246:9:246:18 | call to source : | string_flow.rb:253:21:253:21 | a : | +| string_flow.rb:246:5:246:5 | a : | string_flow.rb:247:10:247:10 | a : | +| string_flow.rb:246:5:246:5 | a : | string_flow.rb:248:20:248:20 | a : | +| string_flow.rb:246:5:246:5 | a : | string_flow.rb:249:5:249:5 | a : | +| string_flow.rb:246:5:246:5 | a : | string_flow.rb:250:26:250:26 | a : | +| string_flow.rb:246:5:246:5 | a : | string_flow.rb:252:10:252:10 | a : | +| string_flow.rb:246:5:246:5 | a : | string_flow.rb:253:21:253:21 | a : | +| string_flow.rb:246:9:246:18 | call to source : | string_flow.rb:246:5:246:5 | a : | | string_flow.rb:247:10:247:10 | a : | string_flow.rb:247:10:247:21 | call to scrub | | string_flow.rb:248:20:248:20 | a : | string_flow.rb:248:10:248:21 | call to scrub | | string_flow.rb:249:5:249:5 | a : | string_flow.rb:249:16:249:16 | x : | @@ -215,23 +266,29 @@ edges | string_flow.rb:250:26:250:26 | a : | string_flow.rb:250:10:250:28 | call to scrub | | string_flow.rb:252:10:252:10 | a : | string_flow.rb:252:10:252:22 | call to scrub! | | string_flow.rb:253:21:253:21 | a : | string_flow.rb:253:10:253:22 | call to scrub! | -| string_flow.rb:255:5:255:18 | ... = ... : | string_flow.rb:258:27:258:27 | a : | -| string_flow.rb:255:9:255:18 | call to source : | string_flow.rb:255:5:255:18 | ... = ... : | -| string_flow.rb:255:9:255:18 | call to source : | string_flow.rb:256:5:256:5 | a : | +| string_flow.rb:255:5:255:5 | a : | string_flow.rb:256:5:256:5 | a : | +| string_flow.rb:255:5:255:5 | a : | string_flow.rb:258:27:258:27 | a : | +| string_flow.rb:255:9:255:18 | call to source : | string_flow.rb:255:5:255:5 | a : | | string_flow.rb:256:5:256:5 | a : | string_flow.rb:256:17:256:17 | x : | | string_flow.rb:256:17:256:17 | x : | string_flow.rb:256:25:256:25 | x | | string_flow.rb:258:27:258:27 | a : | string_flow.rb:258:10:258:29 | call to scrub! | -| string_flow.rb:262:9:262:18 | call to source : | string_flow.rb:263:10:263:10 | a : | +| string_flow.rb:262:5:262:5 | a : | string_flow.rb:263:10:263:10 | a : | +| string_flow.rb:262:9:262:18 | call to source : | string_flow.rb:262:5:262:5 | a : | | string_flow.rb:263:10:263:10 | a : | string_flow.rb:263:10:263:22 | call to shellescape | -| string_flow.rb:267:9:267:18 | call to source : | string_flow.rb:268:9:268:9 | a : | +| string_flow.rb:267:5:267:5 | a : | string_flow.rb:268:9:268:9 | a : | +| string_flow.rb:267:9:267:18 | call to source : | string_flow.rb:267:5:267:5 | a : | +| string_flow.rb:268:5:268:5 | b [element] : | string_flow.rb:269:10:269:10 | b [element] : | | string_flow.rb:268:9:268:9 | a : | string_flow.rb:268:9:268:20 | call to shellsplit [element] : | -| string_flow.rb:268:9:268:20 | call to shellsplit [element] : | string_flow.rb:269:10:269:10 | b [element] : | +| string_flow.rb:268:9:268:20 | call to shellsplit [element] : | string_flow.rb:268:5:268:5 | b [element] : | | string_flow.rb:269:10:269:10 | b [element] : | string_flow.rb:269:10:269:13 | ...[...] | -| string_flow.rb:273:9:273:18 | call to source : | string_flow.rb:274:9:274:9 | a : | -| string_flow.rb:273:9:273:18 | call to source : | string_flow.rb:277:9:277:9 | a : | +| string_flow.rb:273:5:273:5 | a : | string_flow.rb:274:9:274:9 | a : | +| string_flow.rb:273:5:273:5 | a : | string_flow.rb:277:9:277:9 | a : | +| string_flow.rb:273:9:273:18 | call to source : | string_flow.rb:273:5:273:5 | a : | +| string_flow.rb:274:5:274:5 | b : | string_flow.rb:275:10:275:10 | b : | | string_flow.rb:274:9:274:9 | a : | string_flow.rb:274:9:274:18 | call to slice : | -| string_flow.rb:274:9:274:18 | call to slice : | string_flow.rb:275:10:275:10 | b : | +| string_flow.rb:274:9:274:18 | call to slice : | string_flow.rb:274:5:274:5 | b : | | string_flow.rb:275:10:275:10 | b : | string_flow.rb:275:10:275:13 | ...[...] | +| string_flow.rb:277:5:277:5 | b : | string_flow.rb:278:10:278:10 | b : | | string_flow.rb:277:9:277:9 | [post] a : | string_flow.rb:280:9:280:9 | a : | | string_flow.rb:277:9:277:9 | [post] a : | string_flow.rb:283:9:283:9 | a : | | string_flow.rb:277:9:277:9 | [post] a [element 1] : | string_flow.rb:283:9:283:9 | a [element 1] : | @@ -242,45 +299,53 @@ edges | string_flow.rb:277:9:277:9 | a : | string_flow.rb:277:9:277:9 | [post] a [element 2] : | | string_flow.rb:277:9:277:9 | a : | string_flow.rb:277:9:277:9 | [post] a [element] : | | string_flow.rb:277:9:277:9 | a : | string_flow.rb:277:9:277:19 | call to slice! : | -| string_flow.rb:277:9:277:19 | call to slice! : | string_flow.rb:278:10:278:10 | b : | +| string_flow.rb:277:9:277:19 | call to slice! : | string_flow.rb:277:5:277:5 | b : | | string_flow.rb:278:10:278:10 | b : | string_flow.rb:278:10:278:13 | ...[...] | +| string_flow.rb:280:5:280:5 | b : | string_flow.rb:281:10:281:10 | b : | | string_flow.rb:280:9:280:9 | a : | string_flow.rb:280:9:280:20 | call to split : | -| string_flow.rb:280:9:280:20 | call to split : | string_flow.rb:281:10:281:10 | b : | +| string_flow.rb:280:9:280:20 | call to split : | string_flow.rb:280:5:280:5 | b : | | string_flow.rb:281:10:281:10 | b : | string_flow.rb:281:10:281:13 | ...[...] | +| string_flow.rb:283:5:283:5 | b : | string_flow.rb:284:10:284:10 | b : | +| string_flow.rb:283:5:283:5 | b [element 0] : | string_flow.rb:284:10:284:10 | b [element 0] : | +| string_flow.rb:283:5:283:5 | b [element 1] : | string_flow.rb:284:10:284:10 | b [element 1] : | +| string_flow.rb:283:5:283:5 | b [element] : | string_flow.rb:284:10:284:10 | b [element] : | | string_flow.rb:283:9:283:9 | a : | string_flow.rb:283:9:283:14 | ...[...] : | | string_flow.rb:283:9:283:9 | a : | string_flow.rb:283:9:283:14 | ...[...] [element 0] : | | string_flow.rb:283:9:283:9 | a : | string_flow.rb:283:9:283:14 | ...[...] [element 1] : | | string_flow.rb:283:9:283:9 | a [element 1] : | string_flow.rb:283:9:283:14 | ...[...] [element 0] : | | string_flow.rb:283:9:283:9 | a [element 2] : | string_flow.rb:283:9:283:14 | ...[...] [element 1] : | | string_flow.rb:283:9:283:9 | a [element] : | string_flow.rb:283:9:283:14 | ...[...] [element] : | -| string_flow.rb:283:9:283:14 | ...[...] : | string_flow.rb:284:10:284:10 | b : | -| string_flow.rb:283:9:283:14 | ...[...] [element 0] : | string_flow.rb:284:10:284:10 | b [element 0] : | -| string_flow.rb:283:9:283:14 | ...[...] [element 1] : | string_flow.rb:284:10:284:10 | b [element 1] : | -| string_flow.rb:283:9:283:14 | ...[...] [element] : | string_flow.rb:284:10:284:10 | b [element] : | +| string_flow.rb:283:9:283:14 | ...[...] : | string_flow.rb:283:5:283:5 | b : | +| string_flow.rb:283:9:283:14 | ...[...] [element 0] : | string_flow.rb:283:5:283:5 | b [element 0] : | +| string_flow.rb:283:9:283:14 | ...[...] [element 1] : | string_flow.rb:283:5:283:5 | b [element 1] : | +| string_flow.rb:283:9:283:14 | ...[...] [element] : | string_flow.rb:283:5:283:5 | b [element] : | | string_flow.rb:284:10:284:10 | b : | string_flow.rb:284:10:284:13 | ...[...] | | string_flow.rb:284:10:284:10 | b [element 0] : | string_flow.rb:284:10:284:13 | ...[...] | | string_flow.rb:284:10:284:10 | b [element 1] : | string_flow.rb:284:10:284:13 | ...[...] | | string_flow.rb:284:10:284:10 | b [element] : | string_flow.rb:284:10:284:13 | ...[...] | -| string_flow.rb:288:9:288:18 | call to source : | string_flow.rb:289:10:289:10 | a : | -| string_flow.rb:288:9:288:18 | call to source : | string_flow.rb:290:10:290:10 | a : | -| string_flow.rb:288:9:288:18 | call to source : | string_flow.rb:291:10:291:10 | a : | -| string_flow.rb:288:9:288:18 | call to source : | string_flow.rb:292:10:292:10 | a : | +| string_flow.rb:288:5:288:5 | a : | string_flow.rb:289:10:289:10 | a : | +| string_flow.rb:288:5:288:5 | a : | string_flow.rb:290:10:290:10 | a : | +| string_flow.rb:288:5:288:5 | a : | string_flow.rb:291:10:291:10 | a : | +| string_flow.rb:288:5:288:5 | a : | string_flow.rb:292:10:292:10 | a : | +| string_flow.rb:288:9:288:18 | call to source : | string_flow.rb:288:5:288:5 | a : | | string_flow.rb:289:10:289:10 | a : | string_flow.rb:289:10:289:18 | call to squeeze | | string_flow.rb:290:10:290:10 | a : | string_flow.rb:290:10:290:23 | call to squeeze | | string_flow.rb:291:10:291:10 | a : | string_flow.rb:291:10:291:19 | call to squeeze! | | string_flow.rb:292:10:292:10 | a : | string_flow.rb:292:10:292:24 | call to squeeze! | -| string_flow.rb:296:9:296:18 | call to source : | string_flow.rb:297:10:297:10 | a : | -| string_flow.rb:296:9:296:18 | call to source : | string_flow.rb:298:10:298:10 | a : | +| string_flow.rb:296:5:296:5 | a : | string_flow.rb:297:10:297:10 | a : | +| string_flow.rb:296:5:296:5 | a : | string_flow.rb:298:10:298:10 | a : | +| string_flow.rb:296:9:296:18 | call to source : | string_flow.rb:296:5:296:5 | a : | | string_flow.rb:297:10:297:10 | a : | string_flow.rb:297:10:297:17 | call to to_str | | string_flow.rb:298:10:298:10 | a : | string_flow.rb:298:10:298:15 | call to to_s | -| string_flow.rb:302:9:302:18 | call to source : | string_flow.rb:303:10:303:10 | a : | -| string_flow.rb:302:9:302:18 | call to source : | string_flow.rb:304:22:304:22 | a : | -| string_flow.rb:302:9:302:18 | call to source : | string_flow.rb:305:10:305:10 | a : | -| string_flow.rb:302:9:302:18 | call to source : | string_flow.rb:306:23:306:23 | a : | -| string_flow.rb:302:9:302:18 | call to source : | string_flow.rb:307:10:307:10 | a : | -| string_flow.rb:302:9:302:18 | call to source : | string_flow.rb:308:24:308:24 | a : | -| string_flow.rb:302:9:302:18 | call to source : | string_flow.rb:309:10:309:10 | a : | -| string_flow.rb:302:9:302:18 | call to source : | string_flow.rb:310:25:310:25 | a : | +| string_flow.rb:302:5:302:5 | a : | string_flow.rb:303:10:303:10 | a : | +| string_flow.rb:302:5:302:5 | a : | string_flow.rb:304:22:304:22 | a : | +| string_flow.rb:302:5:302:5 | a : | string_flow.rb:305:10:305:10 | a : | +| string_flow.rb:302:5:302:5 | a : | string_flow.rb:306:23:306:23 | a : | +| string_flow.rb:302:5:302:5 | a : | string_flow.rb:307:10:307:10 | a : | +| string_flow.rb:302:5:302:5 | a : | string_flow.rb:308:24:308:24 | a : | +| string_flow.rb:302:5:302:5 | a : | string_flow.rb:309:10:309:10 | a : | +| string_flow.rb:302:5:302:5 | a : | string_flow.rb:310:25:310:25 | a : | +| string_flow.rb:302:9:302:18 | call to source : | string_flow.rb:302:5:302:5 | a : | | string_flow.rb:303:10:303:10 | a : | string_flow.rb:303:10:303:23 | call to tr | | string_flow.rb:304:22:304:22 | a : | string_flow.rb:304:10:304:23 | call to tr | | string_flow.rb:305:10:305:10 | a : | string_flow.rb:305:10:305:24 | call to tr! | @@ -289,9 +354,10 @@ edges | string_flow.rb:308:24:308:24 | a : | string_flow.rb:308:10:308:25 | call to tr_s | | string_flow.rb:309:10:309:10 | a : | string_flow.rb:309:10:309:26 | call to tr_s! | | string_flow.rb:310:25:310:25 | a : | string_flow.rb:310:10:310:26 | call to tr_s! | -| string_flow.rb:314:9:314:18 | call to source : | string_flow.rb:315:5:315:5 | a : | -| string_flow.rb:314:9:314:18 | call to source : | string_flow.rb:316:5:316:5 | a : | -| string_flow.rb:314:9:314:18 | call to source : | string_flow.rb:317:14:317:14 | a : | +| string_flow.rb:314:5:314:5 | a : | string_flow.rb:315:5:315:5 | a : | +| string_flow.rb:314:5:314:5 | a : | string_flow.rb:316:5:316:5 | a : | +| string_flow.rb:314:5:314:5 | a : | string_flow.rb:317:14:317:14 | a : | +| string_flow.rb:314:9:314:18 | call to source : | string_flow.rb:314:5:314:5 | a : | | string_flow.rb:315:5:315:5 | a : | string_flow.rb:315:20:315:20 | x : | | string_flow.rb:315:20:315:20 | x : | string_flow.rb:315:28:315:28 | x | | string_flow.rb:316:5:316:5 | a : | string_flow.rb:316:26:316:26 | x : | @@ -299,18 +365,23 @@ edges | string_flow.rb:317:14:317:14 | a : | string_flow.rb:317:20:317:20 | x : | | string_flow.rb:317:20:317:20 | x : | string_flow.rb:317:28:317:28 | x | nodes +| string_flow.rb:2:5:2:5 | a : | semmle.label | a : | +| string_flow.rb:2:5:2:5 | a : | semmle.label | a : | | string_flow.rb:2:9:2:18 | call to source : | semmle.label | call to source : | | string_flow.rb:2:9:2:18 | call to source : | semmle.label | call to source : | | string_flow.rb:3:10:3:22 | call to new | semmle.label | call to new | | string_flow.rb:3:10:3:22 | call to new | semmle.label | call to new | | string_flow.rb:3:21:3:21 | a : | semmle.label | a : | | string_flow.rb:3:21:3:21 | a : | semmle.label | a : | +| string_flow.rb:7:5:7:5 | a : | semmle.label | a : | | string_flow.rb:7:9:7:18 | call to source : | semmle.label | call to source : | +| string_flow.rb:8:5:8:5 | b : | semmle.label | b : | | string_flow.rb:8:9:8:16 | call to source : | semmle.label | call to source : | | string_flow.rb:9:10:9:30 | call to try_convert | semmle.label | call to try_convert | | string_flow.rb:9:29:9:29 | a : | semmle.label | a : | | string_flow.rb:10:10:10:30 | call to try_convert | semmle.label | call to try_convert | | string_flow.rb:10:29:10:29 | b : | semmle.label | b : | +| string_flow.rb:14:5:14:5 | a : | semmle.label | a : | | string_flow.rb:14:9:14:18 | call to source : | semmle.label | call to source : | | string_flow.rb:15:10:15:17 | ... % ... | semmle.label | ... % ... | | string_flow.rb:15:17:15:17 | a : | semmle.label | a : | @@ -318,16 +389,25 @@ nodes | string_flow.rb:16:28:16:28 | a : | semmle.label | a : | | string_flow.rb:17:10:17:10 | a : | semmle.label | a : | | string_flow.rb:17:10:17:18 | ... % ... | semmle.label | ... % ... | +| string_flow.rb:21:5:21:5 | a : | semmle.label | a : | | string_flow.rb:21:9:21:18 | call to source : | semmle.label | call to source : | +| string_flow.rb:22:5:22:5 | b : | semmle.label | b : | | string_flow.rb:23:10:23:10 | b | semmle.label | b | +| string_flow.rb:27:5:27:5 | a : | semmle.label | a : | | string_flow.rb:27:9:27:18 | call to source : | semmle.label | call to source : | +| string_flow.rb:28:5:28:5 | b : | semmle.label | b : | | string_flow.rb:29:10:29:10 | b | semmle.label | b | +| string_flow.rb:33:5:33:5 | a : | semmle.label | a : | | string_flow.rb:33:9:33:18 | call to source : | semmle.label | call to source : | +| string_flow.rb:34:5:34:5 | b : | semmle.label | b : | | string_flow.rb:35:10:35:10 | b | semmle.label | b | +| string_flow.rb:36:5:36:5 | c : | semmle.label | c : | | string_flow.rb:37:10:37:10 | c | semmle.label | c | +| string_flow.rb:41:5:41:5 | a : | semmle.label | a : | | string_flow.rb:41:9:41:18 | call to source : | semmle.label | call to source : | | string_flow.rb:42:10:42:10 | a : | semmle.label | a : | | string_flow.rb:42:10:42:12 | call to b | semmle.label | call to b | +| string_flow.rb:46:5:46:5 | a : | semmle.label | a : | | string_flow.rb:46:9:46:18 | call to source : | semmle.label | call to source : | | string_flow.rb:47:10:47:10 | a : | semmle.label | a : | | string_flow.rb:47:10:47:23 | call to byteslice | semmle.label | call to byteslice | @@ -335,11 +415,13 @@ nodes | string_flow.rb:48:10:48:26 | call to byteslice | semmle.label | call to byteslice | | string_flow.rb:49:10:49:10 | a : | semmle.label | a : | | string_flow.rb:49:10:49:26 | call to byteslice | semmle.label | call to byteslice | +| string_flow.rb:53:5:53:5 | a : | semmle.label | a : | | string_flow.rb:53:9:53:18 | call to source : | semmle.label | call to source : | | string_flow.rb:54:10:54:10 | a : | semmle.label | a : | | string_flow.rb:54:10:54:21 | call to capitalize | semmle.label | call to capitalize | | string_flow.rb:55:10:55:10 | a : | semmle.label | a : | | string_flow.rb:55:10:55:22 | call to capitalize! | semmle.label | call to capitalize! | +| string_flow.rb:59:5:59:5 | a : | semmle.label | a : | | string_flow.rb:59:9:59:18 | call to source : | semmle.label | call to source : | | string_flow.rb:60:10:60:10 | a : | semmle.label | a : | | string_flow.rb:60:10:60:21 | call to center | semmle.label | call to center | @@ -353,16 +435,20 @@ nodes | string_flow.rb:64:10:64:20 | call to rjust | semmle.label | call to rjust | | string_flow.rb:65:10:65:27 | call to rjust | semmle.label | call to rjust | | string_flow.rb:65:26:65:26 | a : | semmle.label | a : | +| string_flow.rb:69:5:69:5 | a : | semmle.label | a : | | string_flow.rb:69:9:69:18 | call to source : | semmle.label | call to source : | | string_flow.rb:70:10:70:10 | a : | semmle.label | a : | | string_flow.rb:70:10:70:16 | call to chomp | semmle.label | call to chomp | | string_flow.rb:71:10:71:10 | a : | semmle.label | a : | | string_flow.rb:71:10:71:17 | call to chomp! | semmle.label | call to chomp! | +| string_flow.rb:75:5:75:5 | a : | semmle.label | a : | | string_flow.rb:75:9:75:18 | call to source : | semmle.label | call to source : | | string_flow.rb:76:10:76:10 | a : | semmle.label | a : | | string_flow.rb:76:10:76:15 | call to chop | semmle.label | call to chop | | string_flow.rb:77:10:77:10 | a : | semmle.label | a : | | string_flow.rb:77:10:77:16 | call to chop! | semmle.label | call to chop! | +| string_flow.rb:83:5:83:5 | a : | semmle.label | a : | +| string_flow.rb:83:5:83:5 | a : | semmle.label | a : | | string_flow.rb:83:9:83:18 | call to source : | semmle.label | call to source : | | string_flow.rb:83:9:83:18 | call to source : | semmle.label | call to source : | | string_flow.rb:84:5:84:5 | [post] a : | semmle.label | [post] a : | @@ -371,6 +457,7 @@ nodes | string_flow.rb:84:5:84:5 | a : | semmle.label | a : | | string_flow.rb:85:10:85:10 | a | semmle.label | a | | string_flow.rb:85:10:85:10 | a | semmle.label | a | +| string_flow.rb:108:5:108:5 | a : | semmle.label | a : | | string_flow.rb:108:9:108:18 | call to source : | semmle.label | call to source : | | string_flow.rb:109:10:109:10 | [post] a : | semmle.label | [post] a : | | string_flow.rb:109:10:109:10 | a : | semmle.label | a : | @@ -379,6 +466,7 @@ nodes | string_flow.rb:110:10:110:29 | call to delete_prefix | semmle.label | call to delete_prefix | | string_flow.rb:111:10:111:10 | a : | semmle.label | a : | | string_flow.rb:111:10:111:29 | call to delete_suffix | semmle.label | call to delete_suffix | +| string_flow.rb:115:5:115:5 | a : | semmle.label | a : | | string_flow.rb:115:9:115:18 | call to source : | semmle.label | call to source : | | string_flow.rb:116:10:116:10 | a : | semmle.label | a : | | string_flow.rb:116:10:116:19 | call to downcase | semmle.label | call to downcase | @@ -392,33 +480,42 @@ nodes | string_flow.rb:120:10:120:17 | call to upcase | semmle.label | call to upcase | | string_flow.rb:121:10:121:10 | a : | semmle.label | a : | | string_flow.rb:121:10:121:18 | call to upcase! | semmle.label | call to upcase! | +| string_flow.rb:125:5:125:5 | a : | semmle.label | a : | | string_flow.rb:125:9:125:18 | call to source : | semmle.label | call to source : | +| string_flow.rb:126:5:126:5 | b : | semmle.label | b : | | string_flow.rb:126:9:126:9 | a : | semmle.label | a : | | string_flow.rb:126:9:126:14 | call to dump : | semmle.label | call to dump : | | string_flow.rb:127:10:127:10 | b | semmle.label | b | | string_flow.rb:128:10:128:10 | b : | semmle.label | b : | | string_flow.rb:128:10:128:17 | call to undump | semmle.label | call to undump | +| string_flow.rb:132:5:132:5 | a : | semmle.label | a : | | string_flow.rb:132:9:132:18 | call to source : | semmle.label | call to source : | +| string_flow.rb:133:5:133:5 | b : | semmle.label | b : | | string_flow.rb:133:9:133:9 | a : | semmle.label | a : | | string_flow.rb:133:9:133:40 | call to each_line : | semmle.label | call to each_line : | | string_flow.rb:133:24:133:27 | line : | semmle.label | line : | | string_flow.rb:133:35:133:38 | line | semmle.label | line | | string_flow.rb:134:10:134:10 | b | semmle.label | b | +| string_flow.rb:135:5:135:5 | c [element] : | semmle.label | c [element] : | | string_flow.rb:135:9:135:9 | a : | semmle.label | a : | | string_flow.rb:135:9:135:19 | call to each_line [element] : | semmle.label | call to each_line [element] : | | string_flow.rb:136:10:136:10 | c [element] : | semmle.label | c [element] : | | string_flow.rb:136:10:136:15 | call to to_a [element] : | semmle.label | call to to_a [element] : | | string_flow.rb:136:10:136:18 | ...[...] | semmle.label | ...[...] | +| string_flow.rb:140:5:140:5 | a : | semmle.label | a : | | string_flow.rb:140:9:140:18 | call to source : | semmle.label | call to source : | +| string_flow.rb:141:5:141:5 | b : | semmle.label | b : | | string_flow.rb:141:9:141:9 | a : | semmle.label | a : | | string_flow.rb:141:9:141:36 | call to lines : | semmle.label | call to lines : | | string_flow.rb:141:20:141:23 | line : | semmle.label | line : | | string_flow.rb:141:31:141:34 | line | semmle.label | line | | string_flow.rb:142:10:142:10 | b | semmle.label | b | +| string_flow.rb:143:5:143:5 | c [element] : | semmle.label | c [element] : | | string_flow.rb:143:9:143:9 | a : | semmle.label | a : | | string_flow.rb:143:9:143:15 | call to lines [element] : | semmle.label | call to lines [element] : | | string_flow.rb:144:10:144:10 | c [element] : | semmle.label | c [element] : | | string_flow.rb:144:10:144:13 | ...[...] | semmle.label | ...[...] | +| string_flow.rb:148:5:148:5 | a : | semmle.label | a : | | string_flow.rb:148:9:148:18 | call to source : | semmle.label | call to source : | | string_flow.rb:149:10:149:10 | a : | semmle.label | a : | | string_flow.rb:149:10:149:26 | call to encode | semmle.label | call to encode | @@ -428,13 +525,17 @@ nodes | string_flow.rb:151:10:151:28 | call to unicode_normalize | semmle.label | call to unicode_normalize | | string_flow.rb:152:10:152:10 | a : | semmle.label | a : | | string_flow.rb:152:10:152:29 | call to unicode_normalize! | semmle.label | call to unicode_normalize! | +| string_flow.rb:156:5:156:5 | a : | semmle.label | a : | | string_flow.rb:156:9:156:18 | call to source : | semmle.label | call to source : | | string_flow.rb:157:10:157:10 | a : | semmle.label | a : | | string_flow.rb:157:10:157:34 | call to force_encoding | semmle.label | call to force_encoding | +| string_flow.rb:161:5:161:5 | a : | semmle.label | a : | | string_flow.rb:161:9:161:18 | call to source : | semmle.label | call to source : | | string_flow.rb:162:10:162:10 | a : | semmle.label | a : | | string_flow.rb:162:10:162:17 | call to freeze | semmle.label | call to freeze | +| string_flow.rb:166:5:166:5 | a : | semmle.label | a : | | string_flow.rb:166:9:166:18 | call to source : | semmle.label | call to source : | +| string_flow.rb:167:5:167:5 | c : | semmle.label | c : | | string_flow.rb:167:9:167:18 | call to source : | semmle.label | call to source : | | string_flow.rb:168:10:168:10 | a : | semmle.label | a : | | string_flow.rb:168:10:168:23 | call to gsub | semmle.label | call to gsub | @@ -448,7 +549,9 @@ nodes | string_flow.rb:171:10:171:10 | a : | semmle.label | a : | | string_flow.rb:171:10:171:44 | call to gsub! | semmle.label | call to gsub! | | string_flow.rb:171:33:171:42 | call to source : | semmle.label | call to source : | +| string_flow.rb:175:5:175:5 | a : | semmle.label | a : | | string_flow.rb:175:9:175:18 | call to source : | semmle.label | call to source : | +| string_flow.rb:176:5:176:5 | c : | semmle.label | c : | | string_flow.rb:176:9:176:18 | call to source : | semmle.label | call to source : | | string_flow.rb:177:10:177:10 | a : | semmle.label | a : | | string_flow.rb:177:10:177:22 | call to sub | semmle.label | call to sub | @@ -462,9 +565,11 @@ nodes | string_flow.rb:180:10:180:10 | a : | semmle.label | a : | | string_flow.rb:180:10:180:43 | call to sub! | semmle.label | call to sub! | | string_flow.rb:180:32:180:41 | call to source : | semmle.label | call to source : | +| string_flow.rb:191:5:191:5 | a : | semmle.label | a : | | string_flow.rb:191:9:191:18 | call to source : | semmle.label | call to source : | | string_flow.rb:192:10:192:10 | a : | semmle.label | a : | | string_flow.rb:192:10:192:18 | call to inspect | semmle.label | call to inspect | +| string_flow.rb:196:5:196:5 | a : | semmle.label | a : | | string_flow.rb:196:9:196:18 | call to source : | semmle.label | call to source : | | string_flow.rb:197:10:197:10 | a : | semmle.label | a : | | string_flow.rb:197:10:197:16 | call to strip | semmle.label | call to strip | @@ -478,6 +583,7 @@ nodes | string_flow.rb:201:10:201:17 | call to rstrip | semmle.label | call to rstrip | | string_flow.rb:202:10:202:10 | a : | semmle.label | a : | | string_flow.rb:202:10:202:18 | call to rstrip! | semmle.label | call to rstrip! | +| string_flow.rb:206:5:206:5 | a : | semmle.label | a : | | string_flow.rb:206:9:206:18 | call to source : | semmle.label | call to source : | | string_flow.rb:207:10:207:10 | a : | semmle.label | a : | | string_flow.rb:207:10:207:15 | call to next | semmle.label | call to next | @@ -487,7 +593,11 @@ nodes | string_flow.rb:209:10:209:15 | call to succ | semmle.label | call to succ | | string_flow.rb:210:10:210:10 | a : | semmle.label | a : | | string_flow.rb:210:10:210:16 | call to succ! | semmle.label | call to succ! | +| string_flow.rb:214:5:214:5 | a : | semmle.label | a : | | string_flow.rb:214:9:214:18 | call to source : | semmle.label | call to source : | +| string_flow.rb:215:5:215:5 | b [element 0] : | semmle.label | b [element 0] : | +| string_flow.rb:215:5:215:5 | b [element 1] : | semmle.label | b [element 1] : | +| string_flow.rb:215:5:215:5 | b [element 2] : | semmle.label | b [element 2] : | | string_flow.rb:215:9:215:9 | a : | semmle.label | a : | | string_flow.rb:215:9:215:24 | call to partition [element 0] : | semmle.label | call to partition [element 0] : | | string_flow.rb:215:9:215:24 | call to partition [element 1] : | semmle.label | call to partition [element 1] : | @@ -498,8 +608,11 @@ nodes | string_flow.rb:217:10:217:13 | ...[...] | semmle.label | ...[...] | | string_flow.rb:218:10:218:10 | b [element 2] : | semmle.label | b [element 2] : | | string_flow.rb:218:10:218:13 | ...[...] | semmle.label | ...[...] | +| string_flow.rb:223:5:223:5 | a : | semmle.label | a : | +| string_flow.rb:223:5:223:5 | a : | semmle.label | a : | | string_flow.rb:223:9:223:18 | call to source : | semmle.label | call to source : | | string_flow.rb:223:9:223:18 | call to source : | semmle.label | call to source : | +| string_flow.rb:224:5:224:5 | b : | semmle.label | b : | | string_flow.rb:224:9:224:18 | call to source : | semmle.label | call to source : | | string_flow.rb:225:10:225:10 | [post] a : | semmle.label | [post] a : | | string_flow.rb:225:10:225:10 | [post] a : | semmle.label | [post] a : | @@ -509,25 +622,29 @@ nodes | string_flow.rb:225:20:225:20 | b : | semmle.label | b : | | string_flow.rb:227:10:227:10 | a | semmle.label | a | | string_flow.rb:227:10:227:10 | a | semmle.label | a | +| string_flow.rb:231:5:231:5 | a : | semmle.label | a : | | string_flow.rb:231:9:231:18 | call to source : | semmle.label | call to source : | | string_flow.rb:232:10:232:10 | a : | semmle.label | a : | | string_flow.rb:232:10:232:18 | call to reverse | semmle.label | call to reverse | +| string_flow.rb:236:5:236:5 | a : | semmle.label | a : | | string_flow.rb:236:9:236:18 | call to source : | semmle.label | call to source : | | string_flow.rb:237:9:237:9 | a : | semmle.label | a : | | string_flow.rb:237:24:237:24 | x : | semmle.label | x : | | string_flow.rb:237:35:237:35 | x | semmle.label | x | +| string_flow.rb:238:5:238:5 | b : | semmle.label | b : | | string_flow.rb:238:9:238:9 | a : | semmle.label | a : | | string_flow.rb:238:9:238:37 | call to scan : | semmle.label | call to scan : | | string_flow.rb:238:27:238:27 | y : | semmle.label | y : | | string_flow.rb:238:35:238:35 | y | semmle.label | y | | string_flow.rb:239:10:239:10 | b | semmle.label | b | +| string_flow.rb:240:5:240:5 | b [element] : | semmle.label | b [element] : | | string_flow.rb:240:9:240:9 | a : | semmle.label | a : | | string_flow.rb:240:9:240:19 | call to scan [element] : | semmle.label | call to scan [element] : | | string_flow.rb:241:10:241:10 | b [element] : | semmle.label | b [element] : | | string_flow.rb:241:10:241:13 | ...[...] | semmle.label | ...[...] | | string_flow.rb:242:10:242:10 | b [element] : | semmle.label | b [element] : | | string_flow.rb:242:10:242:13 | ...[...] | semmle.label | ...[...] | -| string_flow.rb:246:5:246:18 | ... = ... : | semmle.label | ... = ... : | +| string_flow.rb:246:5:246:5 | a : | semmle.label | a : | | string_flow.rb:246:9:246:18 | call to source : | semmle.label | call to source : | | string_flow.rb:247:10:247:10 | a : | semmle.label | a : | | string_flow.rb:247:10:247:21 | call to scrub | semmle.label | call to scrub | @@ -542,26 +659,32 @@ nodes | string_flow.rb:252:10:252:22 | call to scrub! | semmle.label | call to scrub! | | string_flow.rb:253:10:253:22 | call to scrub! | semmle.label | call to scrub! | | string_flow.rb:253:21:253:21 | a : | semmle.label | a : | -| string_flow.rb:255:5:255:18 | ... = ... : | semmle.label | ... = ... : | +| string_flow.rb:255:5:255:5 | a : | semmle.label | a : | | string_flow.rb:255:9:255:18 | call to source : | semmle.label | call to source : | | string_flow.rb:256:5:256:5 | a : | semmle.label | a : | | string_flow.rb:256:17:256:17 | x : | semmle.label | x : | | string_flow.rb:256:25:256:25 | x | semmle.label | x | | string_flow.rb:258:10:258:29 | call to scrub! | semmle.label | call to scrub! | | string_flow.rb:258:27:258:27 | a : | semmle.label | a : | +| string_flow.rb:262:5:262:5 | a : | semmle.label | a : | | string_flow.rb:262:9:262:18 | call to source : | semmle.label | call to source : | | string_flow.rb:263:10:263:10 | a : | semmle.label | a : | | string_flow.rb:263:10:263:22 | call to shellescape | semmle.label | call to shellescape | +| string_flow.rb:267:5:267:5 | a : | semmle.label | a : | | string_flow.rb:267:9:267:18 | call to source : | semmle.label | call to source : | +| string_flow.rb:268:5:268:5 | b [element] : | semmle.label | b [element] : | | string_flow.rb:268:9:268:9 | a : | semmle.label | a : | | string_flow.rb:268:9:268:20 | call to shellsplit [element] : | semmle.label | call to shellsplit [element] : | | string_flow.rb:269:10:269:10 | b [element] : | semmle.label | b [element] : | | string_flow.rb:269:10:269:13 | ...[...] | semmle.label | ...[...] | +| string_flow.rb:273:5:273:5 | a : | semmle.label | a : | | string_flow.rb:273:9:273:18 | call to source : | semmle.label | call to source : | +| string_flow.rb:274:5:274:5 | b : | semmle.label | b : | | string_flow.rb:274:9:274:9 | a : | semmle.label | a : | | string_flow.rb:274:9:274:18 | call to slice : | semmle.label | call to slice : | | string_flow.rb:275:10:275:10 | b : | semmle.label | b : | | string_flow.rb:275:10:275:13 | ...[...] | semmle.label | ...[...] | +| string_flow.rb:277:5:277:5 | b : | semmle.label | b : | | string_flow.rb:277:9:277:9 | [post] a : | semmle.label | [post] a : | | string_flow.rb:277:9:277:9 | [post] a [element 1] : | semmle.label | [post] a [element 1] : | | string_flow.rb:277:9:277:9 | [post] a [element 2] : | semmle.label | [post] a [element 2] : | @@ -570,10 +693,15 @@ nodes | string_flow.rb:277:9:277:19 | call to slice! : | semmle.label | call to slice! : | | string_flow.rb:278:10:278:10 | b : | semmle.label | b : | | string_flow.rb:278:10:278:13 | ...[...] | semmle.label | ...[...] | +| string_flow.rb:280:5:280:5 | b : | semmle.label | b : | | string_flow.rb:280:9:280:9 | a : | semmle.label | a : | | string_flow.rb:280:9:280:20 | call to split : | semmle.label | call to split : | | string_flow.rb:281:10:281:10 | b : | semmle.label | b : | | string_flow.rb:281:10:281:13 | ...[...] | semmle.label | ...[...] | +| string_flow.rb:283:5:283:5 | b : | semmle.label | b : | +| string_flow.rb:283:5:283:5 | b [element 0] : | semmle.label | b [element 0] : | +| string_flow.rb:283:5:283:5 | b [element 1] : | semmle.label | b [element 1] : | +| string_flow.rb:283:5:283:5 | b [element] : | semmle.label | b [element] : | | string_flow.rb:283:9:283:9 | a : | semmle.label | a : | | string_flow.rb:283:9:283:9 | a [element 1] : | semmle.label | a [element 1] : | | string_flow.rb:283:9:283:9 | a [element 2] : | semmle.label | a [element 2] : | @@ -587,6 +715,7 @@ nodes | string_flow.rb:284:10:284:10 | b [element 1] : | semmle.label | b [element 1] : | | string_flow.rb:284:10:284:10 | b [element] : | semmle.label | b [element] : | | string_flow.rb:284:10:284:13 | ...[...] | semmle.label | ...[...] | +| string_flow.rb:288:5:288:5 | a : | semmle.label | a : | | string_flow.rb:288:9:288:18 | call to source : | semmle.label | call to source : | | string_flow.rb:289:10:289:10 | a : | semmle.label | a : | | string_flow.rb:289:10:289:18 | call to squeeze | semmle.label | call to squeeze | @@ -596,11 +725,13 @@ nodes | string_flow.rb:291:10:291:19 | call to squeeze! | semmle.label | call to squeeze! | | string_flow.rb:292:10:292:10 | a : | semmle.label | a : | | string_flow.rb:292:10:292:24 | call to squeeze! | semmle.label | call to squeeze! | +| string_flow.rb:296:5:296:5 | a : | semmle.label | a : | | string_flow.rb:296:9:296:18 | call to source : | semmle.label | call to source : | | string_flow.rb:297:10:297:10 | a : | semmle.label | a : | | string_flow.rb:297:10:297:17 | call to to_str | semmle.label | call to to_str | | string_flow.rb:298:10:298:10 | a : | semmle.label | a : | | string_flow.rb:298:10:298:15 | call to to_s | semmle.label | call to to_s | +| string_flow.rb:302:5:302:5 | a : | semmle.label | a : | | string_flow.rb:302:9:302:18 | call to source : | semmle.label | call to source : | | string_flow.rb:303:10:303:10 | a : | semmle.label | a : | | string_flow.rb:303:10:303:23 | call to tr | semmle.label | call to tr | @@ -618,6 +749,7 @@ nodes | string_flow.rb:309:10:309:26 | call to tr_s! | semmle.label | call to tr_s! | | string_flow.rb:310:10:310:26 | call to tr_s! | semmle.label | call to tr_s! | | string_flow.rb:310:25:310:25 | a : | semmle.label | a : | +| string_flow.rb:314:5:314:5 | a : | semmle.label | a : | | string_flow.rb:314:9:314:18 | call to source : | semmle.label | call to source : | | string_flow.rb:315:5:315:5 | a : | semmle.label | a : | | string_flow.rb:315:20:315:20 | x : | semmle.label | x : | diff --git a/ruby/ql/test/library-tests/dataflow/summaries/Summaries.expected b/ruby/ql/test/library-tests/dataflow/summaries/Summaries.expected index f916520c8ce..a69c52963cb 100644 --- a/ruby/ql/test/library-tests/dataflow/summaries/Summaries.expected +++ b/ruby/ql/test/library-tests/dataflow/summaries/Summaries.expected @@ -1,53 +1,57 @@ failures edges -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:2:6:2:12 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:2:6:2:12 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:4:24:4:30 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:4:24:4:30 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:16:36:16:42 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:16:36:16:42 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:20:25:20:31 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:26:31:26:37 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:30:24:30:30 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:31:27:31:33 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:34:16:34:22 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:34:16:34:22 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:35:16:35:22 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:35:16:35:22 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:36:21:36:27 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:36:21:36:27 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:37:36:37:42 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:37:36:37:42 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:51:24:51:30 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:56:22:56:28 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:57:17:57:23 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:59:27:59:33 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:63:32:63:38 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:65:23:65:29 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:122:16:122:22 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:128:14:128:20 | tainted : | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:131:16:131:22 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:131:16:131:22 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:132:21:132:27 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:132:21:132:27 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:135:26:135:32 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:135:26:135:32 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:137:23:137:29 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:137:23:137:29 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:140:19:140:25 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:140:19:140:25 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:141:19:141:25 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:141:19:141:25 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:145:26:145:32 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:145:26:145:32 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:147:16:147:22 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:147:16:147:22 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:150:39:150:45 | tainted | -| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:150:39:150:45 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:2:6:2:12 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:2:6:2:12 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:4:24:4:30 | tainted : | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:4:24:4:30 | tainted : | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:16:36:16:42 | tainted : | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:16:36:16:42 | tainted : | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:20:25:20:31 | tainted : | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:26:31:26:37 | tainted : | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:30:24:30:30 | tainted : | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:31:27:31:33 | tainted : | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:34:16:34:22 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:34:16:34:22 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:35:16:35:22 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:35:16:35:22 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:36:21:36:27 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:36:21:36:27 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:37:36:37:42 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:37:36:37:42 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:51:24:51:30 | tainted : | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:56:22:56:28 | tainted : | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:57:17:57:23 | tainted : | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:59:27:59:33 | tainted : | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:63:32:63:38 | tainted : | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:65:23:65:29 | tainted : | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:122:16:122:22 | tainted : | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:128:14:128:20 | tainted : | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:131:16:131:22 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:131:16:131:22 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:132:21:132:27 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:132:21:132:27 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:135:26:135:32 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:135:26:135:32 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:137:23:137:29 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:137:23:137:29 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:140:19:140:25 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:140:19:140:25 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:141:19:141:25 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:141:19:141:25 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:145:26:145:32 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:145:26:145:32 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:147:16:147:22 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:147:16:147:22 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:150:39:150:45 | tainted | +| summaries.rb:1:1:1:7 | tainted : | summaries.rb:150:39:150:45 | tainted | +| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:1:1:1:7 | tainted : | +| summaries.rb:1:11:1:36 | call to identity : | summaries.rb:1:1:1:7 | tainted : | | summaries.rb:1:20:1:36 | call to source : | summaries.rb:1:11:1:36 | call to identity : | | summaries.rb:1:20:1:36 | call to source : | summaries.rb:1:11:1:36 | call to identity : | -| summaries.rb:4:12:7:3 | call to apply_block : | summaries.rb:9:6:9:13 | tainted2 | -| summaries.rb:4:12:7:3 | call to apply_block : | summaries.rb:9:6:9:13 | tainted2 | +| summaries.rb:4:1:4:8 | tainted2 : | summaries.rb:9:6:9:13 | tainted2 | +| summaries.rb:4:1:4:8 | tainted2 : | summaries.rb:9:6:9:13 | tainted2 | +| summaries.rb:4:12:7:3 | call to apply_block : | summaries.rb:4:1:4:8 | tainted2 : | +| summaries.rb:4:12:7:3 | call to apply_block : | summaries.rb:4:1:4:8 | tainted2 : | | summaries.rb:4:24:4:30 | tainted : | summaries.rb:4:12:7:3 | call to apply_block : | | summaries.rb:4:24:4:30 | tainted : | summaries.rb:4:12:7:3 | call to apply_block : | | summaries.rb:4:24:4:30 | tainted : | summaries.rb:4:36:4:36 | x : | @@ -56,27 +60,33 @@ edges | summaries.rb:4:36:4:36 | x : | summaries.rb:5:8:5:8 | x | | summaries.rb:11:17:11:17 | x : | summaries.rb:12:8:12:8 | x | | summaries.rb:11:17:11:17 | x : | summaries.rb:12:8:12:8 | x | -| summaries.rb:16:12:16:43 | call to apply_lambda : | summaries.rb:18:6:18:13 | tainted3 | -| summaries.rb:16:12:16:43 | call to apply_lambda : | summaries.rb:18:6:18:13 | tainted3 | +| summaries.rb:16:1:16:8 | tainted3 : | summaries.rb:18:6:18:13 | tainted3 | +| summaries.rb:16:1:16:8 | tainted3 : | summaries.rb:18:6:18:13 | tainted3 | +| summaries.rb:16:12:16:43 | call to apply_lambda : | summaries.rb:16:1:16:8 | tainted3 : | +| summaries.rb:16:12:16:43 | call to apply_lambda : | summaries.rb:16:1:16:8 | tainted3 : | | summaries.rb:16:36:16:42 | tainted : | summaries.rb:11:17:11:17 | x : | | summaries.rb:16:36:16:42 | tainted : | summaries.rb:11:17:11:17 | x : | | summaries.rb:16:36:16:42 | tainted : | summaries.rb:16:12:16:43 | call to apply_lambda : | | summaries.rb:16:36:16:42 | tainted : | summaries.rb:16:12:16:43 | call to apply_lambda : | -| summaries.rb:20:12:20:32 | call to firstArg : | summaries.rb:21:6:21:13 | tainted4 | +| summaries.rb:20:1:20:8 | tainted4 : | summaries.rb:21:6:21:13 | tainted4 | +| summaries.rb:20:12:20:32 | call to firstArg : | summaries.rb:20:1:20:8 | tainted4 : | | summaries.rb:20:25:20:31 | tainted : | summaries.rb:20:12:20:32 | call to firstArg : | -| summaries.rb:26:12:26:38 | call to secondArg : | summaries.rb:27:6:27:13 | tainted5 | +| summaries.rb:26:1:26:8 | tainted5 : | summaries.rb:27:6:27:13 | tainted5 | +| summaries.rb:26:12:26:38 | call to secondArg : | summaries.rb:26:1:26:8 | tainted5 : | | summaries.rb:26:31:26:37 | tainted : | summaries.rb:26:12:26:38 | call to secondArg : | | summaries.rb:30:24:30:30 | tainted : | summaries.rb:30:6:30:42 | call to onlyWithBlock | | summaries.rb:31:27:31:33 | tainted : | summaries.rb:31:6:31:34 | call to onlyWithoutBlock | -| summaries.rb:40:7:40:17 | call to source : | summaries.rb:41:24:41:24 | t : | -| summaries.rb:40:7:40:17 | call to source : | summaries.rb:42:24:42:24 | t : | -| summaries.rb:40:7:40:17 | call to source : | summaries.rb:44:8:44:8 | t : | +| summaries.rb:40:3:40:3 | t : | summaries.rb:41:24:41:24 | t : | +| summaries.rb:40:3:40:3 | t : | summaries.rb:42:24:42:24 | t : | +| summaries.rb:40:3:40:3 | t : | summaries.rb:44:8:44:8 | t : | +| summaries.rb:40:7:40:17 | call to source : | summaries.rb:40:3:40:3 | t : | | summaries.rb:41:24:41:24 | t : | summaries.rb:41:8:41:25 | call to matchedByName | | summaries.rb:42:24:42:24 | t : | summaries.rb:42:8:42:25 | call to matchedByName | | summaries.rb:44:8:44:8 | t : | summaries.rb:44:8:44:27 | call to matchedByNameRcv | | summaries.rb:48:24:48:41 | call to source : | summaries.rb:48:8:48:42 | call to preserveTaint | | summaries.rb:51:24:51:30 | tainted : | summaries.rb:51:6:51:31 | call to namedArg | -| summaries.rb:53:15:53:31 | call to source : | summaries.rb:54:21:54:24 | args [element :foo] : | +| summaries.rb:53:1:53:4 | args [element :foo] : | summaries.rb:54:21:54:24 | args [element :foo] : | +| summaries.rb:53:15:53:31 | call to source : | summaries.rb:53:1:53:4 | args [element :foo] : | | summaries.rb:54:19:54:24 | ** ... [element :foo] : | summaries.rb:54:6:54:25 | call to namedArg | | summaries.rb:54:21:54:24 | args [element :foo] : | summaries.rb:54:19:54:24 | ** ... [element :foo] : | | summaries.rb:56:22:56:28 | tainted : | summaries.rb:56:6:56:29 | call to anyArg | @@ -87,20 +97,24 @@ edges | summaries.rb:65:40:65:40 | x : | summaries.rb:66:8:66:8 | x | | summaries.rb:73:24:73:53 | call to source : | summaries.rb:73:8:73:54 | call to preserveTaint | | summaries.rb:76:26:76:56 | call to source : | summaries.rb:76:8:76:57 | call to preserveTaint | -| summaries.rb:79:15:79:29 | call to source : | summaries.rb:82:6:82:6 | a [element 1] : | -| summaries.rb:79:15:79:29 | call to source : | summaries.rb:82:6:82:6 | a [element 1] : | -| summaries.rb:79:15:79:29 | call to source : | summaries.rb:83:6:83:6 | a [element 1] : | -| summaries.rb:79:15:79:29 | call to source : | summaries.rb:83:6:83:6 | a [element 1] : | -| summaries.rb:79:15:79:29 | call to source : | summaries.rb:85:6:85:6 | a [element 1] : | -| summaries.rb:79:15:79:29 | call to source : | summaries.rb:85:6:85:6 | a [element 1] : | -| summaries.rb:79:15:79:29 | call to source : | summaries.rb:87:5:87:5 | a [element 1] : | -| summaries.rb:79:15:79:29 | call to source : | summaries.rb:87:5:87:5 | a [element 1] : | -| summaries.rb:79:15:79:29 | call to source : | summaries.rb:91:5:91:5 | a [element 1] : | -| summaries.rb:79:15:79:29 | call to source : | summaries.rb:91:5:91:5 | a [element 1] : | -| summaries.rb:79:32:79:46 | call to source : | summaries.rb:86:6:86:6 | a [element 2] : | -| summaries.rb:79:32:79:46 | call to source : | summaries.rb:86:6:86:6 | a [element 2] : | -| summaries.rb:79:32:79:46 | call to source : | summaries.rb:95:1:95:1 | a [element 2] : | -| summaries.rb:79:32:79:46 | call to source : | summaries.rb:95:1:95:1 | a [element 2] : | +| summaries.rb:79:1:79:1 | a [element 1] : | summaries.rb:82:6:82:6 | a [element 1] : | +| summaries.rb:79:1:79:1 | a [element 1] : | summaries.rb:82:6:82:6 | a [element 1] : | +| summaries.rb:79:1:79:1 | a [element 1] : | summaries.rb:83:6:83:6 | a [element 1] : | +| summaries.rb:79:1:79:1 | a [element 1] : | summaries.rb:83:6:83:6 | a [element 1] : | +| summaries.rb:79:1:79:1 | a [element 1] : | summaries.rb:85:6:85:6 | a [element 1] : | +| summaries.rb:79:1:79:1 | a [element 1] : | summaries.rb:85:6:85:6 | a [element 1] : | +| summaries.rb:79:1:79:1 | a [element 1] : | summaries.rb:87:5:87:5 | a [element 1] : | +| summaries.rb:79:1:79:1 | a [element 1] : | summaries.rb:87:5:87:5 | a [element 1] : | +| summaries.rb:79:1:79:1 | a [element 1] : | summaries.rb:91:5:91:5 | a [element 1] : | +| summaries.rb:79:1:79:1 | a [element 1] : | summaries.rb:91:5:91:5 | a [element 1] : | +| summaries.rb:79:1:79:1 | a [element 2] : | summaries.rb:86:6:86:6 | a [element 2] : | +| summaries.rb:79:1:79:1 | a [element 2] : | summaries.rb:86:6:86:6 | a [element 2] : | +| summaries.rb:79:1:79:1 | a [element 2] : | summaries.rb:95:1:95:1 | a [element 2] : | +| summaries.rb:79:1:79:1 | a [element 2] : | summaries.rb:95:1:95:1 | a [element 2] : | +| summaries.rb:79:15:79:29 | call to source : | summaries.rb:79:1:79:1 | a [element 1] : | +| summaries.rb:79:15:79:29 | call to source : | summaries.rb:79:1:79:1 | a [element 1] : | +| summaries.rb:79:32:79:46 | call to source : | summaries.rb:79:1:79:1 | a [element 2] : | +| summaries.rb:79:32:79:46 | call to source : | summaries.rb:79:1:79:1 | a [element 2] : | | summaries.rb:81:1:81:1 | [post] a [element] : | summaries.rb:82:6:82:6 | a [element] : | | summaries.rb:81:1:81:1 | [post] a [element] : | summaries.rb:82:6:82:6 | a [element] : | | summaries.rb:81:1:81:1 | [post] a [element] : | summaries.rb:84:6:84:6 | a [element] : | @@ -131,18 +145,22 @@ edges | summaries.rb:86:6:86:6 | a [element 2] : | summaries.rb:86:6:86:9 | ...[...] | | summaries.rb:86:6:86:6 | a [element] : | summaries.rb:86:6:86:9 | ...[...] | | summaries.rb:86:6:86:6 | a [element] : | summaries.rb:86:6:86:9 | ...[...] | +| summaries.rb:87:1:87:1 | b [element 1] : | summaries.rb:89:6:89:6 | b [element 1] : | +| summaries.rb:87:1:87:1 | b [element 1] : | summaries.rb:89:6:89:6 | b [element 1] : | +| summaries.rb:87:1:87:1 | b [element] : | summaries.rb:88:6:88:6 | b [element] : | +| summaries.rb:87:1:87:1 | b [element] : | summaries.rb:88:6:88:6 | b [element] : | +| summaries.rb:87:1:87:1 | b [element] : | summaries.rb:89:6:89:6 | b [element] : | +| summaries.rb:87:1:87:1 | b [element] : | summaries.rb:89:6:89:6 | b [element] : | +| summaries.rb:87:1:87:1 | b [element] : | summaries.rb:90:6:90:6 | b [element] : | +| summaries.rb:87:1:87:1 | b [element] : | summaries.rb:90:6:90:6 | b [element] : | | summaries.rb:87:5:87:5 | a [element 1] : | summaries.rb:87:5:87:22 | call to withElementOne [element 1] : | | summaries.rb:87:5:87:5 | a [element 1] : | summaries.rb:87:5:87:22 | call to withElementOne [element 1] : | | summaries.rb:87:5:87:5 | a [element] : | summaries.rb:87:5:87:22 | call to withElementOne [element] : | | summaries.rb:87:5:87:5 | a [element] : | summaries.rb:87:5:87:22 | call to withElementOne [element] : | -| summaries.rb:87:5:87:22 | call to withElementOne [element 1] : | summaries.rb:89:6:89:6 | b [element 1] : | -| summaries.rb:87:5:87:22 | call to withElementOne [element 1] : | summaries.rb:89:6:89:6 | b [element 1] : | -| summaries.rb:87:5:87:22 | call to withElementOne [element] : | summaries.rb:88:6:88:6 | b [element] : | -| summaries.rb:87:5:87:22 | call to withElementOne [element] : | summaries.rb:88:6:88:6 | b [element] : | -| summaries.rb:87:5:87:22 | call to withElementOne [element] : | summaries.rb:89:6:89:6 | b [element] : | -| summaries.rb:87:5:87:22 | call to withElementOne [element] : | summaries.rb:89:6:89:6 | b [element] : | -| summaries.rb:87:5:87:22 | call to withElementOne [element] : | summaries.rb:90:6:90:6 | b [element] : | -| summaries.rb:87:5:87:22 | call to withElementOne [element] : | summaries.rb:90:6:90:6 | b [element] : | +| summaries.rb:87:5:87:22 | call to withElementOne [element 1] : | summaries.rb:87:1:87:1 | b [element 1] : | +| summaries.rb:87:5:87:22 | call to withElementOne [element 1] : | summaries.rb:87:1:87:1 | b [element 1] : | +| summaries.rb:87:5:87:22 | call to withElementOne [element] : | summaries.rb:87:1:87:1 | b [element] : | +| summaries.rb:87:5:87:22 | call to withElementOne [element] : | summaries.rb:87:1:87:1 | b [element] : | | summaries.rb:88:6:88:6 | b [element] : | summaries.rb:88:6:88:9 | ...[...] | | summaries.rb:88:6:88:6 | b [element] : | summaries.rb:88:6:88:9 | ...[...] | | summaries.rb:89:6:89:6 | b [element 1] : | summaries.rb:89:6:89:9 | ...[...] | @@ -151,10 +169,12 @@ edges | summaries.rb:89:6:89:6 | b [element] : | summaries.rb:89:6:89:9 | ...[...] | | summaries.rb:90:6:90:6 | b [element] : | summaries.rb:90:6:90:9 | ...[...] | | summaries.rb:90:6:90:6 | b [element] : | summaries.rb:90:6:90:9 | ...[...] | +| summaries.rb:91:1:91:1 | c [element 1] : | summaries.rb:93:6:93:6 | c [element 1] : | +| summaries.rb:91:1:91:1 | c [element 1] : | summaries.rb:93:6:93:6 | c [element 1] : | | summaries.rb:91:5:91:5 | a [element 1] : | summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] : | | summaries.rb:91:5:91:5 | a [element 1] : | summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] : | -| summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] : | summaries.rb:93:6:93:6 | c [element 1] : | -| summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] : | summaries.rb:93:6:93:6 | c [element 1] : | +| summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] : | summaries.rb:91:1:91:1 | c [element 1] : | +| summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] : | summaries.rb:91:1:91:1 | c [element 1] : | | summaries.rb:93:6:93:6 | c [element 1] : | summaries.rb:93:6:93:9 | ...[...] | | summaries.rb:93:6:93:6 | c [element 1] : | summaries.rb:93:6:93:9 | ...[...] | | summaries.rb:95:1:95:1 | [post] a [element 2] : | summaries.rb:98:6:98:6 | a [element 2] : | @@ -219,12 +239,16 @@ edges | summaries.rb:128:1:128:1 | [post] x : | summaries.rb:129:6:129:6 | x | | summaries.rb:128:14:128:20 | tainted : | summaries.rb:128:1:128:1 | [post] x : | nodes +| summaries.rb:1:1:1:7 | tainted : | semmle.label | tainted : | +| summaries.rb:1:1:1:7 | tainted : | semmle.label | tainted : | | summaries.rb:1:11:1:36 | call to identity : | semmle.label | call to identity : | | summaries.rb:1:11:1:36 | call to identity : | semmle.label | call to identity : | | summaries.rb:1:20:1:36 | call to source : | semmle.label | call to source : | | summaries.rb:1:20:1:36 | call to source : | semmle.label | call to source : | | summaries.rb:2:6:2:12 | tainted | semmle.label | tainted | | summaries.rb:2:6:2:12 | tainted | semmle.label | tainted | +| summaries.rb:4:1:4:8 | tainted2 : | semmle.label | tainted2 : | +| summaries.rb:4:1:4:8 | tainted2 : | semmle.label | tainted2 : | | summaries.rb:4:12:7:3 | call to apply_block : | semmle.label | call to apply_block : | | summaries.rb:4:12:7:3 | call to apply_block : | semmle.label | call to apply_block : | | summaries.rb:4:24:4:30 | tainted : | semmle.label | tainted : | @@ -239,15 +263,19 @@ nodes | summaries.rb:11:17:11:17 | x : | semmle.label | x : | | summaries.rb:12:8:12:8 | x | semmle.label | x | | summaries.rb:12:8:12:8 | x | semmle.label | x | +| summaries.rb:16:1:16:8 | tainted3 : | semmle.label | tainted3 : | +| summaries.rb:16:1:16:8 | tainted3 : | semmle.label | tainted3 : | | summaries.rb:16:12:16:43 | call to apply_lambda : | semmle.label | call to apply_lambda : | | summaries.rb:16:12:16:43 | call to apply_lambda : | semmle.label | call to apply_lambda : | | summaries.rb:16:36:16:42 | tainted : | semmle.label | tainted : | | summaries.rb:16:36:16:42 | tainted : | semmle.label | tainted : | | summaries.rb:18:6:18:13 | tainted3 | semmle.label | tainted3 | | summaries.rb:18:6:18:13 | tainted3 | semmle.label | tainted3 | +| summaries.rb:20:1:20:8 | tainted4 : | semmle.label | tainted4 : | | summaries.rb:20:12:20:32 | call to firstArg : | semmle.label | call to firstArg : | | summaries.rb:20:25:20:31 | tainted : | semmle.label | tainted : | | summaries.rb:21:6:21:13 | tainted4 | semmle.label | tainted4 | +| summaries.rb:26:1:26:8 | tainted5 : | semmle.label | tainted5 : | | summaries.rb:26:12:26:38 | call to secondArg : | semmle.label | call to secondArg : | | summaries.rb:26:31:26:37 | tainted : | semmle.label | tainted : | | summaries.rb:27:6:27:13 | tainted5 | semmle.label | tainted5 | @@ -263,6 +291,7 @@ nodes | summaries.rb:36:21:36:27 | tainted | semmle.label | tainted | | summaries.rb:37:36:37:42 | tainted | semmle.label | tainted | | summaries.rb:37:36:37:42 | tainted | semmle.label | tainted | +| summaries.rb:40:3:40:3 | t : | semmle.label | t : | | summaries.rb:40:7:40:17 | call to source : | semmle.label | call to source : | | summaries.rb:41:8:41:25 | call to matchedByName | semmle.label | call to matchedByName | | summaries.rb:41:24:41:24 | t : | semmle.label | t : | @@ -274,6 +303,7 @@ nodes | summaries.rb:48:24:48:41 | call to source : | semmle.label | call to source : | | summaries.rb:51:6:51:31 | call to namedArg | semmle.label | call to namedArg | | summaries.rb:51:24:51:30 | tainted : | semmle.label | tainted : | +| summaries.rb:53:1:53:4 | args [element :foo] : | semmle.label | args [element :foo] : | | summaries.rb:53:15:53:31 | call to source : | semmle.label | call to source : | | summaries.rb:54:6:54:25 | call to namedArg | semmle.label | call to namedArg | | summaries.rb:54:19:54:24 | ** ... [element :foo] : | semmle.label | ** ... [element :foo] : | @@ -293,6 +323,10 @@ nodes | summaries.rb:73:24:73:53 | call to source : | semmle.label | call to source : | | summaries.rb:76:8:76:57 | call to preserveTaint | semmle.label | call to preserveTaint | | summaries.rb:76:26:76:56 | call to source : | semmle.label | call to source : | +| summaries.rb:79:1:79:1 | a [element 1] : | semmle.label | a [element 1] : | +| summaries.rb:79:1:79:1 | a [element 1] : | semmle.label | a [element 1] : | +| summaries.rb:79:1:79:1 | a [element 2] : | semmle.label | a [element 2] : | +| summaries.rb:79:1:79:1 | a [element 2] : | semmle.label | a [element 2] : | | summaries.rb:79:15:79:29 | call to source : | semmle.label | call to source : | | summaries.rb:79:15:79:29 | call to source : | semmle.label | call to source : | | summaries.rb:79:32:79:46 | call to source : | semmle.label | call to source : | @@ -327,6 +361,10 @@ nodes | summaries.rb:86:6:86:6 | a [element] : | semmle.label | a [element] : | | summaries.rb:86:6:86:9 | ...[...] | semmle.label | ...[...] | | summaries.rb:86:6:86:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:87:1:87:1 | b [element 1] : | semmle.label | b [element 1] : | +| summaries.rb:87:1:87:1 | b [element 1] : | semmle.label | b [element 1] : | +| summaries.rb:87:1:87:1 | b [element] : | semmle.label | b [element] : | +| summaries.rb:87:1:87:1 | b [element] : | semmle.label | b [element] : | | summaries.rb:87:5:87:5 | a [element 1] : | semmle.label | a [element 1] : | | summaries.rb:87:5:87:5 | a [element 1] : | semmle.label | a [element 1] : | | summaries.rb:87:5:87:5 | a [element] : | semmle.label | a [element] : | @@ -349,6 +387,8 @@ nodes | summaries.rb:90:6:90:6 | b [element] : | semmle.label | b [element] : | | summaries.rb:90:6:90:9 | ...[...] | semmle.label | ...[...] | | summaries.rb:90:6:90:9 | ...[...] | semmle.label | ...[...] | +| summaries.rb:91:1:91:1 | c [element 1] : | semmle.label | c [element 1] : | +| summaries.rb:91:1:91:1 | c [element 1] : | semmle.label | c [element 1] : | | summaries.rb:91:5:91:5 | a [element 1] : | semmle.label | a [element 1] : | | summaries.rb:91:5:91:5 | a [element 1] : | semmle.label | a [element 1] : | | summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] : | semmle.label | call to withExactlyElementOne [element 1] : | diff --git a/ruby/ql/test/library-tests/dataflow/type-tracker/TypeTracker.expected b/ruby/ql/test/library-tests/dataflow/type-tracker/TypeTracker.expected index 0c35a350c41..bc7b35eb941 100644 --- a/ruby/ql/test/library-tests/dataflow/type-tracker/TypeTracker.expected +++ b/ruby/ql/test/library-tests/dataflow/type-tracker/TypeTracker.expected @@ -446,7 +446,7 @@ trackEnd | type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:7:5:9:7 | self (field) | | type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:7:5:9:7 | self in field | | type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:8:9:8:14 | self | -| type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:13:5:13:23 | ... = ... | +| type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:13:5:13:7 | var | | type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:13:5:13:23 | ... = ... | | type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:13:11:13:23 | call to new | | type_tracker.rb:13:11:13:23 | call to new | type_tracker.rb:14:5:14:7 | var | @@ -467,7 +467,7 @@ trackEnd | type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:14:5:14:23 | ... | | type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:14:17:14:23 | "hello" | | type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:14:17:14:23 | ... = ... | -| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:14:17:14:23 | ... = ... | +| type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:14:17:14:23 | __synth__0 | | type_tracker.rb:14:17:14:23 | "hello" | type_tracker.rb:15:10:15:18 | call to field | | type_tracker.rb:14:17:14:23 | __synth__0 | type_tracker.rb:14:17:14:23 | __synth__0 | | type_tracker.rb:15:5:15:18 | call to puts | type_tracker.rb:12:1:16:3 | return return in m | @@ -606,8 +606,8 @@ trackEnd | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:5:39:18 | ... | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:16:39:18 | ... = ... | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:16:39:18 | ... = ... | -| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:16:39:18 | ... = ... | -| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:16:39:18 | ... = ... | +| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:16:39:18 | __synth__0 | +| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:16:39:18 | __synth__0 | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:16:39:18 | obj | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:39:16:39:18 | obj | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:40:5:40:12 | ...[...] | @@ -618,8 +618,8 @@ trackEnd | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:5:43:19 | ... | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:17:43:19 | ... = ... | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:17:43:19 | ... = ... | -| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:17:43:19 | ... = ... | -| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:17:43:19 | ... = ... | +| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:17:43:19 | __synth__0 | +| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:17:43:19 | __synth__0 | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:17:43:19 | obj | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:43:17:43:19 | obj | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:44:5:44:13 | ...[...] | @@ -630,8 +630,8 @@ trackEnd | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:5:47:19 | ... | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:17:47:19 | ... = ... | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:17:47:19 | ... = ... | -| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:17:47:19 | ... = ... | -| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:17:47:19 | ... = ... | +| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:17:47:19 | __synth__0 | +| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:17:47:19 | __synth__0 | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:17:47:19 | obj | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:47:17:47:19 | obj | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:5:51:13 | __synth__0 | @@ -640,8 +640,8 @@ trackEnd | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:5:51:19 | ... | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:17:51:19 | ... = ... | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:17:51:19 | ... = ... | -| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:17:51:19 | ... = ... | -| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:17:51:19 | ... = ... | +| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:17:51:19 | __synth__0 | +| type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:17:51:19 | __synth__0 | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:17:51:19 | obj | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:51:17:51:19 | obj | | type_tracker.rb:34:18:34:20 | obj | type_tracker.rb:52:5:52:13 | ...[...] | @@ -664,7 +664,7 @@ trackEnd | type_tracker.rb:34:26:34:26 | z | type_tracker.rb:52:12:52:12 | z | | type_tracker.rb:35:5:35:7 | tmp | type_tracker.rb:35:5:35:7 | tmp | | type_tracker.rb:35:11:35:15 | Array | type_tracker.rb:35:11:35:15 | Array | -| type_tracker.rb:35:11:35:15 | call to [] | type_tracker.rb:35:5:35:15 | ... = ... | +| type_tracker.rb:35:11:35:15 | call to [] | type_tracker.rb:35:5:35:7 | tmp | | type_tracker.rb:35:11:35:15 | call to [] | type_tracker.rb:35:5:35:15 | ... = ... | | type_tracker.rb:35:11:35:15 | call to [] | type_tracker.rb:35:11:35:15 | call to [] | | type_tracker.rb:35:11:35:15 | call to [] | type_tracker.rb:36:5:36:7 | tmp | @@ -672,7 +672,7 @@ trackEnd | type_tracker.rb:36:9:36:9 | 0 | type_tracker.rb:36:9:36:9 | 0 | | type_tracker.rb:38:5:38:9 | array | type_tracker.rb:38:5:38:9 | array | | type_tracker.rb:38:13:38:25 | Array | type_tracker.rb:38:13:38:25 | Array | -| type_tracker.rb:38:13:38:25 | call to [] | type_tracker.rb:38:5:38:25 | ... = ... | +| type_tracker.rb:38:13:38:25 | call to [] | type_tracker.rb:38:5:38:9 | array | | type_tracker.rb:38:13:38:25 | call to [] | type_tracker.rb:38:5:38:25 | ... = ... | | type_tracker.rb:38:13:38:25 | call to [] | type_tracker.rb:38:13:38:25 | call to [] | | type_tracker.rb:38:13:38:25 | call to [] | type_tracker.rb:39:5:39:9 | array | @@ -692,7 +692,7 @@ trackEnd | type_tracker.rb:40:11:40:11 | 0 | type_tracker.rb:40:11:40:11 | 0 | | type_tracker.rb:42:5:42:10 | array2 | type_tracker.rb:42:5:42:10 | array2 | | type_tracker.rb:42:14:42:26 | Array | type_tracker.rb:42:14:42:26 | Array | -| type_tracker.rb:42:14:42:26 | call to [] | type_tracker.rb:42:5:42:26 | ... = ... | +| type_tracker.rb:42:14:42:26 | call to [] | type_tracker.rb:42:5:42:10 | array2 | | type_tracker.rb:42:14:42:26 | call to [] | type_tracker.rb:42:5:42:26 | ... = ... | | type_tracker.rb:42:14:42:26 | call to [] | type_tracker.rb:42:14:42:26 | call to [] | | type_tracker.rb:42:14:42:26 | call to [] | type_tracker.rb:43:5:43:10 | array2 | @@ -717,7 +717,7 @@ trackEnd | type_tracker.rb:44:5:44:13 | ...[...] | type_tracker.rb:44:5:44:13 | ...[...] | | type_tracker.rb:46:5:46:10 | array3 | type_tracker.rb:46:5:46:10 | array3 | | type_tracker.rb:46:14:46:26 | Array | type_tracker.rb:46:14:46:26 | Array | -| type_tracker.rb:46:14:46:26 | call to [] | type_tracker.rb:46:5:46:26 | ... = ... | +| type_tracker.rb:46:14:46:26 | call to [] | type_tracker.rb:46:5:46:10 | array3 | | type_tracker.rb:46:14:46:26 | call to [] | type_tracker.rb:46:5:46:26 | ... = ... | | type_tracker.rb:46:14:46:26 | call to [] | type_tracker.rb:46:14:46:26 | call to [] | | type_tracker.rb:46:14:46:26 | call to [] | type_tracker.rb:47:5:47:10 | array3 | @@ -738,7 +738,7 @@ trackEnd | type_tracker.rb:48:12:48:12 | 1 | type_tracker.rb:48:12:48:12 | 1 | | type_tracker.rb:50:5:50:10 | array4 | type_tracker.rb:50:5:50:10 | array4 | | type_tracker.rb:50:14:50:26 | Array | type_tracker.rb:50:14:50:26 | Array | -| type_tracker.rb:50:14:50:26 | call to [] | type_tracker.rb:50:5:50:26 | ... = ... | +| type_tracker.rb:50:14:50:26 | call to [] | type_tracker.rb:50:5:50:10 | array4 | | type_tracker.rb:50:14:50:26 | call to [] | type_tracker.rb:50:5:50:26 | ... = ... | | type_tracker.rb:50:14:50:26 | call to [] | type_tracker.rb:50:14:50:26 | call to [] | | type_tracker.rb:50:14:50:26 | call to [] | type_tracker.rb:51:5:51:10 | array4 | diff --git a/ruby/ql/test/library-tests/frameworks/active_record/ActiveRecord.expected b/ruby/ql/test/library-tests/frameworks/active_record/ActiveRecord.expected index 918bd5c19ea..0374a54c0c1 100644 --- a/ruby/ql/test/library-tests/frameworks/active_record/ActiveRecord.expected +++ b/ruby/ql/test/library-tests/frameworks/active_record/ActiveRecord.expected @@ -20,10 +20,10 @@ activeRecordInstances | ActiveRecord.rb:76:5:76:66 | call to create | | ActiveRecord.rb:80:5:80:68 | call to create | | ActiveRecord.rb:84:5:84:16 | call to create | -| associations.rb:19:1:19:20 | ... = ... | +| associations.rb:19:1:19:7 | author1 | | associations.rb:19:1:19:20 | ... = ... | | associations.rb:19:11:19:20 | call to new | -| associations.rb:21:1:21:28 | ... = ... | +| associations.rb:21:1:21:5 | post1 | | associations.rb:21:1:21:28 | ... = ... | | associations.rb:21:9:21:15 | author1 | | associations.rb:21:9:21:21 | call to posts | @@ -32,11 +32,11 @@ activeRecordInstances | associations.rb:23:12:23:16 | post1 | | associations.rb:23:12:23:25 | call to comments | | associations.rb:23:12:23:32 | call to create | -| associations.rb:25:1:25:22 | ... = ... | +| associations.rb:25:1:25:7 | author2 | | associations.rb:25:1:25:22 | ... = ... | | associations.rb:25:11:25:15 | post1 | | associations.rb:25:11:25:22 | call to author | -| associations.rb:27:1:27:28 | ... = ... | +| associations.rb:27:1:27:5 | post2 | | associations.rb:27:1:27:28 | ... = ... | | associations.rb:27:9:27:15 | author2 | | associations.rb:27:9:27:21 | call to posts | @@ -50,7 +50,7 @@ activeRecordInstances | associations.rb:31:1:31:12 | call to author= | | associations.rb:31:1:31:22 | ... | | associations.rb:31:16:31:22 | ... = ... | -| associations.rb:31:16:31:22 | ... = ... | +| associations.rb:31:16:31:22 | __synth__0 | | associations.rb:31:16:31:22 | author2 | | associations.rb:35:1:35:5 | post2 | | associations.rb:35:1:35:14 | call to comments | diff --git a/ruby/ql/test/library-tests/frameworks/active_resource/ActiveResource.expected b/ruby/ql/test/library-tests/frameworks/active_resource/ActiveResource.expected index 3cb31c4c12c..a55946c1852 100644 --- a/ruby/ql/test/library-tests/frameworks/active_resource/ActiveResource.expected +++ b/ruby/ql/test/library-tests/frameworks/active_resource/ActiveResource.expected @@ -11,11 +11,11 @@ modelClassMethodCalls | active_resource.rb:24:10:24:26 | call to find | | active_resource.rb:30:3:30:11 | call to site= | modelInstances -| active_resource.rb:5:1:5:33 | ... = ... | +| active_resource.rb:5:1:5:5 | alice | | active_resource.rb:5:1:5:33 | ... = ... | | active_resource.rb:5:9:5:33 | call to new | | active_resource.rb:6:1:6:5 | alice | -| active_resource.rb:8:1:8:22 | ... = ... | +| active_resource.rb:8:1:8:5 | alice | | active_resource.rb:8:1:8:22 | ... = ... | | active_resource.rb:8:9:8:22 | call to find | | active_resource.rb:9:1:9:5 | alice | @@ -25,10 +25,10 @@ modelInstances | active_resource.rb:17:1:17:5 | alice | | active_resource.rb:18:1:18:22 | call to get | | active_resource.rb:19:1:19:5 | alice | -| active_resource.rb:24:1:24:26 | ... = ... | +| active_resource.rb:24:1:24:6 | people | | active_resource.rb:24:1:24:26 | ... = ... | | active_resource.rb:24:10:24:26 | call to find | -| active_resource.rb:26:1:26:20 | ... = ... | +| active_resource.rb:26:1:26:5 | alice | | active_resource.rb:26:1:26:20 | ... = ... | | active_resource.rb:26:9:26:14 | people | | active_resource.rb:26:9:26:20 | call to first | @@ -46,7 +46,7 @@ modelInstanceMethodCalls collections | active_resource.rb:23:1:23:19 | ... = ... | | active_resource.rb:23:10:23:19 | call to all | -| active_resource.rb:24:1:24:26 | ... = ... | +| active_resource.rb:24:1:24:6 | people | | active_resource.rb:24:1:24:26 | ... = ... | | active_resource.rb:24:10:24:26 | call to find | | active_resource.rb:26:9:26:14 | people | diff --git a/ruby/ql/test/library-tests/frameworks/active_storage/ActiveStorage.expected b/ruby/ql/test/library-tests/frameworks/active_storage/ActiveStorage.expected index 8c788bda20d..cd2c9c57cc7 100644 --- a/ruby/ql/test/library-tests/frameworks/active_storage/ActiveStorage.expected +++ b/ruby/ql/test/library-tests/frameworks/active_storage/ActiveStorage.expected @@ -1,12 +1,12 @@ attachmentInstances -| active_storage.rb:11:1:11:25 | ... = ... | +| active_storage.rb:11:1:11:11 | user_avatar | | active_storage.rb:11:1:11:25 | ... = ... | | active_storage.rb:11:15:11:25 | call to avatar | | active_storage.rb:13:1:13:11 | user_avatar | | active_storage.rb:14:1:14:11 | user_avatar | | active_storage.rb:15:1:15:11 | user_avatar | | active_storage.rb:17:1:17:11 | call to avatar | -| active_storage.rb:19:1:19:42 | ... = ... | +| active_storage.rb:19:1:19:10 | attachment | | active_storage.rb:19:1:19:42 | ... = ... | | active_storage.rb:19:14:19:42 | call to new | | active_storage.rb:23:11:23:20 | attachment | diff --git a/ruby/ql/test/library-tests/frameworks/active_support/ActiveSupportDataFlow.expected b/ruby/ql/test/library-tests/frameworks/active_support/ActiveSupportDataFlow.expected index b84d576ad19..e10e038a7cc 100644 --- a/ruby/ql/test/library-tests/frameworks/active_support/ActiveSupportDataFlow.expected +++ b/ruby/ql/test/library-tests/frameworks/active_support/ActiveSupportDataFlow.expected @@ -1,122 +1,178 @@ failures | hash_extensions.rb:126:10:126:19 | call to sole | Unexpected result: hasValueFlow=b | edges -| active_support.rb:10:9:10:18 | call to source : | active_support.rb:11:10:11:10 | x : | +| active_support.rb:10:5:10:5 | x : | active_support.rb:11:10:11:10 | x : | +| active_support.rb:10:9:10:18 | call to source : | active_support.rb:10:5:10:5 | x : | | active_support.rb:11:10:11:10 | x : | active_support.rb:11:10:11:19 | call to at | -| active_support.rb:15:9:15:18 | call to source : | active_support.rb:16:10:16:10 | x : | +| active_support.rb:15:5:15:5 | x : | active_support.rb:16:10:16:10 | x : | +| active_support.rb:15:9:15:18 | call to source : | active_support.rb:15:5:15:5 | x : | | active_support.rb:16:10:16:10 | x : | active_support.rb:16:10:16:19 | call to camelize | -| active_support.rb:20:9:20:18 | call to source : | active_support.rb:21:10:21:10 | x : | +| active_support.rb:20:5:20:5 | x : | active_support.rb:21:10:21:10 | x : | +| active_support.rb:20:9:20:18 | call to source : | active_support.rb:20:5:20:5 | x : | | active_support.rb:21:10:21:10 | x : | active_support.rb:21:10:21:20 | call to camelcase | -| active_support.rb:25:9:25:18 | call to source : | active_support.rb:26:10:26:10 | x : | +| active_support.rb:25:5:25:5 | x : | active_support.rb:26:10:26:10 | x : | +| active_support.rb:25:9:25:18 | call to source : | active_support.rb:25:5:25:5 | x : | | active_support.rb:26:10:26:10 | x : | active_support.rb:26:10:26:19 | call to classify | -| active_support.rb:30:9:30:18 | call to source : | active_support.rb:31:10:31:10 | x : | +| active_support.rb:30:5:30:5 | x : | active_support.rb:31:10:31:10 | x : | +| active_support.rb:30:9:30:18 | call to source : | active_support.rb:30:5:30:5 | x : | | active_support.rb:31:10:31:10 | x : | active_support.rb:31:10:31:20 | call to dasherize | -| active_support.rb:35:9:35:18 | call to source : | active_support.rb:36:10:36:10 | x : | +| active_support.rb:35:5:35:5 | x : | active_support.rb:36:10:36:10 | x : | +| active_support.rb:35:9:35:18 | call to source : | active_support.rb:35:5:35:5 | x : | | active_support.rb:36:10:36:10 | x : | active_support.rb:36:10:36:24 | call to deconstantize | -| active_support.rb:40:9:40:18 | call to source : | active_support.rb:41:10:41:10 | x : | +| active_support.rb:40:5:40:5 | x : | active_support.rb:41:10:41:10 | x : | +| active_support.rb:40:9:40:18 | call to source : | active_support.rb:40:5:40:5 | x : | | active_support.rb:41:10:41:10 | x : | active_support.rb:41:10:41:21 | call to demodulize | -| active_support.rb:45:9:45:18 | call to source : | active_support.rb:46:10:46:10 | x : | +| active_support.rb:45:5:45:5 | x : | active_support.rb:46:10:46:10 | x : | +| active_support.rb:45:9:45:18 | call to source : | active_support.rb:45:5:45:5 | x : | | active_support.rb:46:10:46:10 | x : | active_support.rb:46:10:46:19 | call to first | -| active_support.rb:50:9:50:18 | call to source : | active_support.rb:51:10:51:10 | x : | +| active_support.rb:50:5:50:5 | x : | active_support.rb:51:10:51:10 | x : | +| active_support.rb:50:9:50:18 | call to source : | active_support.rb:50:5:50:5 | x : | | active_support.rb:51:10:51:10 | x : | active_support.rb:51:10:51:22 | call to foreign_key | -| active_support.rb:55:9:55:18 | call to source : | active_support.rb:56:10:56:10 | x : | +| active_support.rb:55:5:55:5 | x : | active_support.rb:56:10:56:10 | x : | +| active_support.rb:55:9:55:18 | call to source : | active_support.rb:55:5:55:5 | x : | | active_support.rb:56:10:56:10 | x : | active_support.rb:56:10:56:18 | call to from | -| active_support.rb:60:9:60:18 | call to source : | active_support.rb:61:10:61:10 | x : | +| active_support.rb:60:5:60:5 | x : | active_support.rb:61:10:61:10 | x : | +| active_support.rb:60:9:60:18 | call to source : | active_support.rb:60:5:60:5 | x : | | active_support.rb:61:10:61:10 | x : | active_support.rb:61:10:61:20 | call to html_safe | -| active_support.rb:65:9:65:18 | call to source : | active_support.rb:66:10:66:10 | x : | +| active_support.rb:65:5:65:5 | x : | active_support.rb:66:10:66:10 | x : | +| active_support.rb:65:9:65:18 | call to source : | active_support.rb:65:5:65:5 | x : | | active_support.rb:66:10:66:10 | x : | active_support.rb:66:10:66:19 | call to humanize | -| active_support.rb:70:9:70:18 | call to source : | active_support.rb:71:10:71:10 | x : | +| active_support.rb:70:5:70:5 | x : | active_support.rb:71:10:71:10 | x : | +| active_support.rb:70:9:70:18 | call to source : | active_support.rb:70:5:70:5 | x : | | active_support.rb:71:10:71:10 | x : | active_support.rb:71:10:71:20 | call to indent | -| active_support.rb:75:9:75:18 | call to source : | active_support.rb:76:10:76:10 | x : | +| active_support.rb:75:5:75:5 | x : | active_support.rb:76:10:76:10 | x : | +| active_support.rb:75:9:75:18 | call to source : | active_support.rb:75:5:75:5 | x : | | active_support.rb:76:10:76:10 | x : | active_support.rb:76:10:76:21 | call to indent! | -| active_support.rb:80:9:80:18 | call to source : | active_support.rb:81:10:81:10 | x : | +| active_support.rb:80:5:80:5 | x : | active_support.rb:81:10:81:10 | x : | +| active_support.rb:80:9:80:18 | call to source : | active_support.rb:80:5:80:5 | x : | | active_support.rb:81:10:81:10 | x : | active_support.rb:81:10:81:18 | call to inquiry | -| active_support.rb:85:9:85:18 | call to source : | active_support.rb:86:10:86:10 | x : | +| active_support.rb:85:5:85:5 | x : | active_support.rb:86:10:86:10 | x : | +| active_support.rb:85:9:85:18 | call to source : | active_support.rb:85:5:85:5 | x : | | active_support.rb:86:10:86:10 | x : | active_support.rb:86:10:86:18 | call to last | -| active_support.rb:90:9:90:18 | call to source : | active_support.rb:91:10:91:10 | x : | +| active_support.rb:90:5:90:5 | x : | active_support.rb:91:10:91:10 | x : | +| active_support.rb:90:9:90:18 | call to source : | active_support.rb:90:5:90:5 | x : | | active_support.rb:91:10:91:10 | x : | active_support.rb:91:10:91:19 | call to mb_chars | -| active_support.rb:95:9:95:18 | call to source : | active_support.rb:96:10:96:10 | x : | +| active_support.rb:95:5:95:5 | x : | active_support.rb:96:10:96:10 | x : | +| active_support.rb:95:9:95:18 | call to source : | active_support.rb:95:5:95:5 | x : | | active_support.rb:96:10:96:10 | x : | active_support.rb:96:10:96:23 | call to parameterize | -| active_support.rb:100:9:100:18 | call to source : | active_support.rb:101:10:101:10 | x : | +| active_support.rb:100:5:100:5 | x : | active_support.rb:101:10:101:10 | x : | +| active_support.rb:100:9:100:18 | call to source : | active_support.rb:100:5:100:5 | x : | | active_support.rb:101:10:101:10 | x : | active_support.rb:101:10:101:20 | call to pluralize | -| active_support.rb:105:9:105:18 | call to source : | active_support.rb:106:10:106:10 | x : | +| active_support.rb:105:5:105:5 | x : | active_support.rb:106:10:106:10 | x : | +| active_support.rb:105:9:105:18 | call to source : | active_support.rb:105:5:105:5 | x : | | active_support.rb:106:10:106:10 | x : | active_support.rb:106:10:106:24 | call to remove | -| active_support.rb:110:9:110:18 | call to source : | active_support.rb:111:10:111:10 | x : | +| active_support.rb:110:5:110:5 | x : | active_support.rb:111:10:111:10 | x : | +| active_support.rb:110:9:110:18 | call to source : | active_support.rb:110:5:110:5 | x : | | active_support.rb:111:10:111:10 | x : | active_support.rb:111:10:111:25 | call to remove! | -| active_support.rb:115:9:115:18 | call to source : | active_support.rb:116:10:116:10 | x : | +| active_support.rb:115:5:115:5 | x : | active_support.rb:116:10:116:10 | x : | +| active_support.rb:115:9:115:18 | call to source : | active_support.rb:115:5:115:5 | x : | | active_support.rb:116:10:116:10 | x : | active_support.rb:116:10:116:22 | call to singularize | -| active_support.rb:120:9:120:18 | call to source : | active_support.rb:121:10:121:10 | x : | +| active_support.rb:120:5:120:5 | x : | active_support.rb:121:10:121:10 | x : | +| active_support.rb:120:9:120:18 | call to source : | active_support.rb:120:5:120:5 | x : | | active_support.rb:121:10:121:10 | x : | active_support.rb:121:10:121:17 | call to squish | -| active_support.rb:125:9:125:18 | call to source : | active_support.rb:126:10:126:10 | x : | +| active_support.rb:125:5:125:5 | x : | active_support.rb:126:10:126:10 | x : | +| active_support.rb:125:9:125:18 | call to source : | active_support.rb:125:5:125:5 | x : | | active_support.rb:126:10:126:10 | x : | active_support.rb:126:10:126:18 | call to squish! | -| active_support.rb:130:9:130:18 | call to source : | active_support.rb:131:10:131:10 | x : | +| active_support.rb:130:5:130:5 | x : | active_support.rb:131:10:131:10 | x : | +| active_support.rb:130:9:130:18 | call to source : | active_support.rb:130:5:130:5 | x : | | active_support.rb:131:10:131:10 | x : | active_support.rb:131:10:131:24 | call to strip_heredoc | -| active_support.rb:135:9:135:18 | call to source : | active_support.rb:136:10:136:10 | x : | +| active_support.rb:135:5:135:5 | x : | active_support.rb:136:10:136:10 | x : | +| active_support.rb:135:9:135:18 | call to source : | active_support.rb:135:5:135:5 | x : | | active_support.rb:136:10:136:10 | x : | active_support.rb:136:10:136:19 | call to tableize | -| active_support.rb:140:9:140:18 | call to source : | active_support.rb:141:10:141:10 | x : | +| active_support.rb:140:5:140:5 | x : | active_support.rb:141:10:141:10 | x : | +| active_support.rb:140:9:140:18 | call to source : | active_support.rb:140:5:140:5 | x : | | active_support.rb:141:10:141:10 | x : | active_support.rb:141:10:141:20 | call to titlecase | -| active_support.rb:145:9:145:18 | call to source : | active_support.rb:146:10:146:10 | x : | +| active_support.rb:145:5:145:5 | x : | active_support.rb:146:10:146:10 | x : | +| active_support.rb:145:9:145:18 | call to source : | active_support.rb:145:5:145:5 | x : | | active_support.rb:146:10:146:10 | x : | active_support.rb:146:10:146:19 | call to titleize | -| active_support.rb:150:9:150:18 | call to source : | active_support.rb:151:10:151:10 | x : | +| active_support.rb:150:5:150:5 | x : | active_support.rb:151:10:151:10 | x : | +| active_support.rb:150:9:150:18 | call to source : | active_support.rb:150:5:150:5 | x : | | active_support.rb:151:10:151:10 | x : | active_support.rb:151:10:151:16 | call to to | -| active_support.rb:155:9:155:18 | call to source : | active_support.rb:156:10:156:10 | x : | +| active_support.rb:155:5:155:5 | x : | active_support.rb:156:10:156:10 | x : | +| active_support.rb:155:9:155:18 | call to source : | active_support.rb:155:5:155:5 | x : | | active_support.rb:156:10:156:10 | x : | active_support.rb:156:10:156:22 | call to truncate | -| active_support.rb:160:9:160:18 | call to source : | active_support.rb:161:10:161:10 | x : | +| active_support.rb:160:5:160:5 | x : | active_support.rb:161:10:161:10 | x : | +| active_support.rb:160:9:160:18 | call to source : | active_support.rb:160:5:160:5 | x : | | active_support.rb:161:10:161:10 | x : | active_support.rb:161:10:161:28 | call to truncate_bytes | -| active_support.rb:165:9:165:18 | call to source : | active_support.rb:166:10:166:10 | x : | +| active_support.rb:165:5:165:5 | x : | active_support.rb:166:10:166:10 | x : | +| active_support.rb:165:9:165:18 | call to source : | active_support.rb:165:5:165:5 | x : | | active_support.rb:166:10:166:10 | x : | active_support.rb:166:10:166:28 | call to truncate_words | -| active_support.rb:170:9:170:18 | call to source : | active_support.rb:171:10:171:10 | x : | +| active_support.rb:170:5:170:5 | x : | active_support.rb:171:10:171:10 | x : | +| active_support.rb:170:9:170:18 | call to source : | active_support.rb:170:5:170:5 | x : | | active_support.rb:171:10:171:10 | x : | active_support.rb:171:10:171:21 | call to underscore | -| active_support.rb:175:9:175:18 | call to source : | active_support.rb:176:10:176:10 | x : | +| active_support.rb:175:5:175:5 | x : | active_support.rb:176:10:176:10 | x : | +| active_support.rb:175:9:175:18 | call to source : | active_support.rb:175:5:175:5 | x : | | active_support.rb:176:10:176:10 | x : | active_support.rb:176:10:176:23 | call to upcase_first | -| active_support.rb:180:10:180:17 | call to source : | active_support.rb:181:9:181:9 | x [element 0] : | -| active_support.rb:180:10:180:17 | call to source : | active_support.rb:181:9:181:9 | x [element 0] : | +| active_support.rb:180:5:180:5 | x [element 0] : | active_support.rb:181:9:181:9 | x [element 0] : | +| active_support.rb:180:5:180:5 | x [element 0] : | active_support.rb:181:9:181:9 | x [element 0] : | +| active_support.rb:180:10:180:17 | call to source : | active_support.rb:180:5:180:5 | x [element 0] : | +| active_support.rb:180:10:180:17 | call to source : | active_support.rb:180:5:180:5 | x [element 0] : | +| active_support.rb:181:5:181:5 | y [element] : | active_support.rb:182:10:182:10 | y [element] : | +| active_support.rb:181:5:181:5 | y [element] : | active_support.rb:182:10:182:10 | y [element] : | | active_support.rb:181:9:181:9 | x [element 0] : | active_support.rb:181:9:181:23 | call to compact_blank [element] : | | active_support.rb:181:9:181:9 | x [element 0] : | active_support.rb:181:9:181:23 | call to compact_blank [element] : | -| active_support.rb:181:9:181:23 | call to compact_blank [element] : | active_support.rb:182:10:182:10 | y [element] : | -| active_support.rb:181:9:181:23 | call to compact_blank [element] : | active_support.rb:182:10:182:10 | y [element] : | +| active_support.rb:181:9:181:23 | call to compact_blank [element] : | active_support.rb:181:5:181:5 | y [element] : | +| active_support.rb:181:9:181:23 | call to compact_blank [element] : | active_support.rb:181:5:181:5 | y [element] : | | active_support.rb:182:10:182:10 | y [element] : | active_support.rb:182:10:182:13 | ...[...] | | active_support.rb:182:10:182:10 | y [element] : | active_support.rb:182:10:182:13 | ...[...] | -| active_support.rb:186:10:186:18 | call to source : | active_support.rb:187:9:187:9 | x [element 0] : | -| active_support.rb:186:10:186:18 | call to source : | active_support.rb:187:9:187:9 | x [element 0] : | +| active_support.rb:186:5:186:5 | x [element 0] : | active_support.rb:187:9:187:9 | x [element 0] : | +| active_support.rb:186:5:186:5 | x [element 0] : | active_support.rb:187:9:187:9 | x [element 0] : | +| active_support.rb:186:10:186:18 | call to source : | active_support.rb:186:5:186:5 | x [element 0] : | +| active_support.rb:186:10:186:18 | call to source : | active_support.rb:186:5:186:5 | x [element 0] : | +| active_support.rb:187:5:187:5 | y [element] : | active_support.rb:188:10:188:10 | y [element] : | +| active_support.rb:187:5:187:5 | y [element] : | active_support.rb:188:10:188:10 | y [element] : | | active_support.rb:187:9:187:9 | x [element 0] : | active_support.rb:187:9:187:21 | call to excluding [element] : | | active_support.rb:187:9:187:9 | x [element 0] : | active_support.rb:187:9:187:21 | call to excluding [element] : | -| active_support.rb:187:9:187:21 | call to excluding [element] : | active_support.rb:188:10:188:10 | y [element] : | -| active_support.rb:187:9:187:21 | call to excluding [element] : | active_support.rb:188:10:188:10 | y [element] : | +| active_support.rb:187:9:187:21 | call to excluding [element] : | active_support.rb:187:5:187:5 | y [element] : | +| active_support.rb:187:9:187:21 | call to excluding [element] : | active_support.rb:187:5:187:5 | y [element] : | | active_support.rb:188:10:188:10 | y [element] : | active_support.rb:188:10:188:13 | ...[...] | | active_support.rb:188:10:188:10 | y [element] : | active_support.rb:188:10:188:13 | ...[...] | -| active_support.rb:192:10:192:18 | call to source : | active_support.rb:193:9:193:9 | x [element 0] : | -| active_support.rb:192:10:192:18 | call to source : | active_support.rb:193:9:193:9 | x [element 0] : | +| active_support.rb:192:5:192:5 | x [element 0] : | active_support.rb:193:9:193:9 | x [element 0] : | +| active_support.rb:192:5:192:5 | x [element 0] : | active_support.rb:193:9:193:9 | x [element 0] : | +| active_support.rb:192:10:192:18 | call to source : | active_support.rb:192:5:192:5 | x [element 0] : | +| active_support.rb:192:10:192:18 | call to source : | active_support.rb:192:5:192:5 | x [element 0] : | +| active_support.rb:193:5:193:5 | y [element] : | active_support.rb:194:10:194:10 | y [element] : | +| active_support.rb:193:5:193:5 | y [element] : | active_support.rb:194:10:194:10 | y [element] : | | active_support.rb:193:9:193:9 | x [element 0] : | active_support.rb:193:9:193:19 | call to without [element] : | | active_support.rb:193:9:193:9 | x [element 0] : | active_support.rb:193:9:193:19 | call to without [element] : | -| active_support.rb:193:9:193:19 | call to without [element] : | active_support.rb:194:10:194:10 | y [element] : | -| active_support.rb:193:9:193:19 | call to without [element] : | active_support.rb:194:10:194:10 | y [element] : | +| active_support.rb:193:9:193:19 | call to without [element] : | active_support.rb:193:5:193:5 | y [element] : | +| active_support.rb:193:9:193:19 | call to without [element] : | active_support.rb:193:5:193:5 | y [element] : | | active_support.rb:194:10:194:10 | y [element] : | active_support.rb:194:10:194:13 | ...[...] | | active_support.rb:194:10:194:10 | y [element] : | active_support.rb:194:10:194:13 | ...[...] | -| active_support.rb:198:10:198:18 | call to source : | active_support.rb:199:9:199:9 | x [element 0] : | -| active_support.rb:198:10:198:18 | call to source : | active_support.rb:199:9:199:9 | x [element 0] : | +| active_support.rb:198:5:198:5 | x [element 0] : | active_support.rb:199:9:199:9 | x [element 0] : | +| active_support.rb:198:5:198:5 | x [element 0] : | active_support.rb:199:9:199:9 | x [element 0] : | +| active_support.rb:198:10:198:18 | call to source : | active_support.rb:198:5:198:5 | x [element 0] : | +| active_support.rb:198:10:198:18 | call to source : | active_support.rb:198:5:198:5 | x [element 0] : | +| active_support.rb:199:5:199:5 | y [element] : | active_support.rb:200:10:200:10 | y [element] : | +| active_support.rb:199:5:199:5 | y [element] : | active_support.rb:200:10:200:10 | y [element] : | | active_support.rb:199:9:199:9 | x [element 0] : | active_support.rb:199:9:199:37 | call to in_order_of [element] : | | active_support.rb:199:9:199:9 | x [element 0] : | active_support.rb:199:9:199:37 | call to in_order_of [element] : | -| active_support.rb:199:9:199:37 | call to in_order_of [element] : | active_support.rb:200:10:200:10 | y [element] : | -| active_support.rb:199:9:199:37 | call to in_order_of [element] : | active_support.rb:200:10:200:10 | y [element] : | +| active_support.rb:199:9:199:37 | call to in_order_of [element] : | active_support.rb:199:5:199:5 | y [element] : | +| active_support.rb:199:9:199:37 | call to in_order_of [element] : | active_support.rb:199:5:199:5 | y [element] : | | active_support.rb:200:10:200:10 | y [element] : | active_support.rb:200:10:200:13 | ...[...] | | active_support.rb:200:10:200:10 | y [element] : | active_support.rb:200:10:200:13 | ...[...] | -| active_support.rb:204:10:204:18 | call to source : | active_support.rb:205:9:205:9 | a [element 0] : | -| active_support.rb:204:10:204:18 | call to source : | active_support.rb:205:9:205:9 | a [element 0] : | -| active_support.rb:204:10:204:18 | call to source : | active_support.rb:206:10:206:10 | a [element 0] : | -| active_support.rb:204:10:204:18 | call to source : | active_support.rb:206:10:206:10 | a [element 0] : | +| active_support.rb:204:5:204:5 | a [element 0] : | active_support.rb:205:9:205:9 | a [element 0] : | +| active_support.rb:204:5:204:5 | a [element 0] : | active_support.rb:205:9:205:9 | a [element 0] : | +| active_support.rb:204:5:204:5 | a [element 0] : | active_support.rb:206:10:206:10 | a [element 0] : | +| active_support.rb:204:5:204:5 | a [element 0] : | active_support.rb:206:10:206:10 | a [element 0] : | +| active_support.rb:204:10:204:18 | call to source : | active_support.rb:204:5:204:5 | a [element 0] : | +| active_support.rb:204:10:204:18 | call to source : | active_support.rb:204:5:204:5 | a [element 0] : | +| active_support.rb:205:5:205:5 | b [element 0] : | active_support.rb:208:10:208:10 | b [element 0] : | +| active_support.rb:205:5:205:5 | b [element 0] : | active_support.rb:208:10:208:10 | b [element 0] : | +| active_support.rb:205:5:205:5 | b [element] : | active_support.rb:208:10:208:10 | b [element] : | +| active_support.rb:205:5:205:5 | b [element] : | active_support.rb:208:10:208:10 | b [element] : | +| active_support.rb:205:5:205:5 | b [element] : | active_support.rb:209:10:209:10 | b [element] : | +| active_support.rb:205:5:205:5 | b [element] : | active_support.rb:209:10:209:10 | b [element] : | +| active_support.rb:205:5:205:5 | b [element] : | active_support.rb:210:10:210:10 | b [element] : | +| active_support.rb:205:5:205:5 | b [element] : | active_support.rb:210:10:210:10 | b [element] : | +| active_support.rb:205:5:205:5 | b [element] : | active_support.rb:211:10:211:10 | b [element] : | +| active_support.rb:205:5:205:5 | b [element] : | active_support.rb:211:10:211:10 | b [element] : | | active_support.rb:205:9:205:9 | a [element 0] : | active_support.rb:205:9:205:41 | call to including [element 0] : | | active_support.rb:205:9:205:9 | a [element 0] : | active_support.rb:205:9:205:41 | call to including [element 0] : | -| active_support.rb:205:9:205:41 | call to including [element 0] : | active_support.rb:208:10:208:10 | b [element 0] : | -| active_support.rb:205:9:205:41 | call to including [element 0] : | active_support.rb:208:10:208:10 | b [element 0] : | -| active_support.rb:205:9:205:41 | call to including [element] : | active_support.rb:208:10:208:10 | b [element] : | -| active_support.rb:205:9:205:41 | call to including [element] : | active_support.rb:208:10:208:10 | b [element] : | -| active_support.rb:205:9:205:41 | call to including [element] : | active_support.rb:209:10:209:10 | b [element] : | -| active_support.rb:205:9:205:41 | call to including [element] : | active_support.rb:209:10:209:10 | b [element] : | -| active_support.rb:205:9:205:41 | call to including [element] : | active_support.rb:210:10:210:10 | b [element] : | -| active_support.rb:205:9:205:41 | call to including [element] : | active_support.rb:210:10:210:10 | b [element] : | -| active_support.rb:205:9:205:41 | call to including [element] : | active_support.rb:211:10:211:10 | b [element] : | -| active_support.rb:205:9:205:41 | call to including [element] : | active_support.rb:211:10:211:10 | b [element] : | +| active_support.rb:205:9:205:41 | call to including [element 0] : | active_support.rb:205:5:205:5 | b [element 0] : | +| active_support.rb:205:9:205:41 | call to including [element 0] : | active_support.rb:205:5:205:5 | b [element 0] : | +| active_support.rb:205:9:205:41 | call to including [element] : | active_support.rb:205:5:205:5 | b [element] : | +| active_support.rb:205:9:205:41 | call to including [element] : | active_support.rb:205:5:205:5 | b [element] : | | active_support.rb:205:21:205:29 | call to source : | active_support.rb:205:9:205:41 | call to including [element] : | | active_support.rb:205:21:205:29 | call to source : | active_support.rb:205:9:205:41 | call to including [element] : | | active_support.rb:205:32:205:40 | call to source : | active_support.rb:205:9:205:41 | call to including [element] : | @@ -133,130 +189,202 @@ edges | active_support.rb:210:10:210:10 | b [element] : | active_support.rb:210:10:210:13 | ...[...] | | active_support.rb:211:10:211:10 | b [element] : | active_support.rb:211:10:211:13 | ...[...] | | active_support.rb:211:10:211:10 | b [element] : | active_support.rb:211:10:211:13 | ...[...] | -| active_support.rb:215:7:215:16 | call to source : | active_support.rb:216:34:216:34 | x : | -| active_support.rb:216:7:216:35 | call to new : | active_support.rb:217:8:217:8 | y | +| active_support.rb:215:3:215:3 | x : | active_support.rb:216:34:216:34 | x : | +| active_support.rb:215:7:215:16 | call to source : | active_support.rb:215:3:215:3 | x : | +| active_support.rb:216:3:216:3 | y : | active_support.rb:217:8:217:8 | y | +| active_support.rb:216:7:216:35 | call to new : | active_support.rb:216:3:216:3 | y : | | active_support.rb:216:34:216:34 | x : | active_support.rb:216:7:216:35 | call to new : | -| active_support.rb:222:7:222:16 | call to source : | active_support.rb:223:21:223:21 | b : | -| active_support.rb:223:7:223:22 | call to safe_concat : | active_support.rb:224:8:224:8 | y | +| active_support.rb:222:3:222:3 | b : | active_support.rb:223:21:223:21 | b : | +| active_support.rb:222:7:222:16 | call to source : | active_support.rb:222:3:222:3 | b : | +| active_support.rb:223:3:223:3 | y : | active_support.rb:224:8:224:8 | y | +| active_support.rb:223:7:223:22 | call to safe_concat : | active_support.rb:223:3:223:3 | y : | | active_support.rb:223:21:223:21 | b : | active_support.rb:223:7:223:22 | call to safe_concat : | -| active_support.rb:229:7:229:16 | call to source : | active_support.rb:230:17:230:17 | b : | +| active_support.rb:229:3:229:3 | b : | active_support.rb:230:17:230:17 | b : | +| active_support.rb:229:7:229:16 | call to source : | active_support.rb:229:3:229:3 | b : | | active_support.rb:230:3:230:3 | [post] x : | active_support.rb:231:8:231:8 | x | | active_support.rb:230:17:230:17 | b : | active_support.rb:230:3:230:3 | [post] x : | -| active_support.rb:235:7:235:16 | call to source : | active_support.rb:237:34:237:34 | a : | -| active_support.rb:237:7:237:35 | call to new : | active_support.rb:238:7:238:7 | x : | +| active_support.rb:235:3:235:3 | a : | active_support.rb:237:34:237:34 | a : | +| active_support.rb:235:7:235:16 | call to source : | active_support.rb:235:3:235:3 | a : | +| active_support.rb:237:3:237:3 | x : | active_support.rb:238:7:238:7 | x : | +| active_support.rb:237:7:237:35 | call to new : | active_support.rb:237:3:237:3 | x : | | active_support.rb:237:34:237:34 | a : | active_support.rb:237:7:237:35 | call to new : | +| active_support.rb:238:3:238:3 | y : | active_support.rb:239:8:239:8 | y | | active_support.rb:238:7:238:7 | x : | active_support.rb:238:7:238:17 | call to concat : | -| active_support.rb:238:7:238:17 | call to concat : | active_support.rb:239:8:239:8 | y | -| active_support.rb:243:7:243:16 | call to source : | active_support.rb:245:34:245:34 | a : | -| active_support.rb:245:7:245:35 | call to new : | active_support.rb:246:7:246:7 | x : | +| active_support.rb:238:7:238:17 | call to concat : | active_support.rb:238:3:238:3 | y : | +| active_support.rb:243:3:243:3 | a : | active_support.rb:245:34:245:34 | a : | +| active_support.rb:243:7:243:16 | call to source : | active_support.rb:243:3:243:3 | a : | +| active_support.rb:245:3:245:3 | x : | active_support.rb:246:7:246:7 | x : | +| active_support.rb:245:7:245:35 | call to new : | active_support.rb:245:3:245:3 | x : | | active_support.rb:245:34:245:34 | a : | active_support.rb:245:7:245:35 | call to new : | +| active_support.rb:246:3:246:3 | y : | active_support.rb:247:8:247:8 | y | | active_support.rb:246:7:246:7 | x : | active_support.rb:246:7:246:20 | call to insert : | -| active_support.rb:246:7:246:20 | call to insert : | active_support.rb:247:8:247:8 | y | -| active_support.rb:251:7:251:16 | call to source : | active_support.rb:253:34:253:34 | a : | -| active_support.rb:253:7:253:35 | call to new : | active_support.rb:254:7:254:7 | x : | +| active_support.rb:246:7:246:20 | call to insert : | active_support.rb:246:3:246:3 | y : | +| active_support.rb:251:3:251:3 | a : | active_support.rb:253:34:253:34 | a : | +| active_support.rb:251:7:251:16 | call to source : | active_support.rb:251:3:251:3 | a : | +| active_support.rb:253:3:253:3 | x : | active_support.rb:254:7:254:7 | x : | +| active_support.rb:253:7:253:35 | call to new : | active_support.rb:253:3:253:3 | x : | | active_support.rb:253:34:253:34 | a : | active_support.rb:253:7:253:35 | call to new : | +| active_support.rb:254:3:254:3 | y : | active_support.rb:255:8:255:8 | y | | active_support.rb:254:7:254:7 | x : | active_support.rb:254:7:254:18 | call to prepend : | -| active_support.rb:254:7:254:18 | call to prepend : | active_support.rb:255:8:255:8 | y | -| active_support.rb:259:7:259:16 | call to source : | active_support.rb:260:34:260:34 | a : | -| active_support.rb:260:7:260:35 | call to new : | active_support.rb:261:7:261:7 | x : | +| active_support.rb:254:7:254:18 | call to prepend : | active_support.rb:254:3:254:3 | y : | +| active_support.rb:259:3:259:3 | a : | active_support.rb:260:34:260:34 | a : | +| active_support.rb:259:7:259:16 | call to source : | active_support.rb:259:3:259:3 | a : | +| active_support.rb:260:3:260:3 | x : | active_support.rb:261:7:261:7 | x : | +| active_support.rb:260:7:260:35 | call to new : | active_support.rb:260:3:260:3 | x : | | active_support.rb:260:34:260:34 | a : | active_support.rb:260:7:260:35 | call to new : | +| active_support.rb:261:3:261:3 | y : | active_support.rb:262:8:262:8 | y | | active_support.rb:261:7:261:7 | x : | active_support.rb:261:7:261:12 | call to to_s : | -| active_support.rb:261:7:261:12 | call to to_s : | active_support.rb:262:8:262:8 | y | -| active_support.rb:266:7:266:16 | call to source : | active_support.rb:267:34:267:34 | a : | -| active_support.rb:267:7:267:35 | call to new : | active_support.rb:268:7:268:7 | x : | +| active_support.rb:261:7:261:12 | call to to_s : | active_support.rb:261:3:261:3 | y : | +| active_support.rb:266:3:266:3 | a : | active_support.rb:267:34:267:34 | a : | +| active_support.rb:266:7:266:16 | call to source : | active_support.rb:266:3:266:3 | a : | +| active_support.rb:267:3:267:3 | x : | active_support.rb:268:7:268:7 | x : | +| active_support.rb:267:7:267:35 | call to new : | active_support.rb:267:3:267:3 | x : | | active_support.rb:267:34:267:34 | a : | active_support.rb:267:7:267:35 | call to new : | +| active_support.rb:268:3:268:3 | y : | active_support.rb:269:8:269:8 | y | | active_support.rb:268:7:268:7 | x : | active_support.rb:268:7:268:16 | call to to_param : | -| active_support.rb:268:7:268:16 | call to to_param : | active_support.rb:269:8:269:8 | y | -| active_support.rb:273:7:273:16 | call to source : | active_support.rb:274:20:274:20 | a : | -| active_support.rb:274:7:274:21 | call to new : | active_support.rb:275:7:275:7 | x : | +| active_support.rb:268:7:268:16 | call to to_param : | active_support.rb:268:3:268:3 | y : | +| active_support.rb:273:3:273:3 | a : | active_support.rb:274:20:274:20 | a : | +| active_support.rb:273:7:273:16 | call to source : | active_support.rb:273:3:273:3 | a : | +| active_support.rb:274:3:274:3 | x : | active_support.rb:275:7:275:7 | x : | +| active_support.rb:274:7:274:21 | call to new : | active_support.rb:274:3:274:3 | x : | | active_support.rb:274:20:274:20 | a : | active_support.rb:274:7:274:21 | call to new : | +| active_support.rb:275:3:275:3 | y : | active_support.rb:276:8:276:8 | y | +| active_support.rb:275:3:275:3 | y : | active_support.rb:277:7:277:7 | y : | | active_support.rb:275:7:275:7 | x : | active_support.rb:275:7:275:17 | call to existence : | -| active_support.rb:275:7:275:17 | call to existence : | active_support.rb:276:8:276:8 | y | -| active_support.rb:275:7:275:17 | call to existence : | active_support.rb:277:7:277:7 | y : | +| active_support.rb:275:7:275:17 | call to existence : | active_support.rb:275:3:275:3 | y : | +| active_support.rb:277:3:277:3 | z : | active_support.rb:278:8:278:8 | z | | active_support.rb:277:7:277:7 | y : | active_support.rb:277:7:277:17 | call to existence : | -| active_support.rb:277:7:277:17 | call to existence : | active_support.rb:278:8:278:8 | z | -| active_support.rb:282:7:282:16 | call to source : | active_support.rb:283:8:283:8 | x : | -| active_support.rb:282:7:282:16 | call to source : | active_support.rb:283:8:283:8 | x : | +| active_support.rb:277:7:277:17 | call to existence : | active_support.rb:277:3:277:3 | z : | +| active_support.rb:282:3:282:3 | x : | active_support.rb:283:8:283:8 | x : | +| active_support.rb:282:3:282:3 | x : | active_support.rb:283:8:283:8 | x : | +| active_support.rb:282:7:282:16 | call to source : | active_support.rb:282:3:282:3 | x : | +| active_support.rb:282:7:282:16 | call to source : | active_support.rb:282:3:282:3 | x : | | active_support.rb:283:8:283:8 | x : | active_support.rb:283:8:283:17 | call to presence | | active_support.rb:283:8:283:8 | x : | active_support.rb:283:8:283:17 | call to presence | -| active_support.rb:285:7:285:16 | call to source : | active_support.rb:286:8:286:8 | y : | -| active_support.rb:285:7:285:16 | call to source : | active_support.rb:286:8:286:8 | y : | +| active_support.rb:285:3:285:3 | y : | active_support.rb:286:8:286:8 | y : | +| active_support.rb:285:3:285:3 | y : | active_support.rb:286:8:286:8 | y : | +| active_support.rb:285:7:285:16 | call to source : | active_support.rb:285:3:285:3 | y : | +| active_support.rb:285:7:285:16 | call to source : | active_support.rb:285:3:285:3 | y : | | active_support.rb:286:8:286:8 | y : | active_support.rb:286:8:286:17 | call to presence | | active_support.rb:286:8:286:8 | y : | active_support.rb:286:8:286:17 | call to presence | -| active_support.rb:290:7:290:16 | call to source : | active_support.rb:291:8:291:8 | x : | -| active_support.rb:290:7:290:16 | call to source : | active_support.rb:291:8:291:8 | x : | +| active_support.rb:290:3:290:3 | x : | active_support.rb:291:8:291:8 | x : | +| active_support.rb:290:3:290:3 | x : | active_support.rb:291:8:291:8 | x : | +| active_support.rb:290:7:290:16 | call to source : | active_support.rb:290:3:290:3 | x : | +| active_support.rb:290:7:290:16 | call to source : | active_support.rb:290:3:290:3 | x : | | active_support.rb:291:8:291:8 | x : | active_support.rb:291:8:291:17 | call to deep_dup | | active_support.rb:291:8:291:8 | x : | active_support.rb:291:8:291:17 | call to deep_dup | -| active_support.rb:303:7:303:16 | call to source : | active_support.rb:304:19:304:19 | a : | -| active_support.rb:304:7:304:19 | call to json_escape : | active_support.rb:305:8:305:8 | b | +| active_support.rb:303:3:303:3 | a : | active_support.rb:304:19:304:19 | a : | +| active_support.rb:303:7:303:16 | call to source : | active_support.rb:303:3:303:3 | a : | +| active_support.rb:304:3:304:3 | b : | active_support.rb:305:8:305:8 | b | +| active_support.rb:304:7:304:19 | call to json_escape : | active_support.rb:304:3:304:3 | b : | | active_support.rb:304:19:304:19 | a : | active_support.rb:304:7:304:19 | call to json_escape : | -| active_support.rb:309:9:309:18 | call to source : | active_support.rb:310:37:310:37 | x : | +| active_support.rb:309:5:309:5 | x : | active_support.rb:310:37:310:37 | x : | +| active_support.rb:309:9:309:18 | call to source : | active_support.rb:309:5:309:5 | x : | | active_support.rb:310:37:310:37 | x : | active_support.rb:310:10:310:38 | call to encode | -| active_support.rb:314:9:314:18 | call to source : | active_support.rb:315:37:315:37 | x : | +| active_support.rb:314:5:314:5 | x : | active_support.rb:315:37:315:37 | x : | +| active_support.rb:314:9:314:18 | call to source : | active_support.rb:314:5:314:5 | x : | | active_support.rb:315:37:315:37 | x : | active_support.rb:315:10:315:38 | call to decode | -| active_support.rb:319:9:319:18 | call to source : | active_support.rb:320:35:320:35 | x : | +| active_support.rb:319:5:319:5 | x : | active_support.rb:320:35:320:35 | x : | +| active_support.rb:319:9:319:18 | call to source : | active_support.rb:319:5:319:5 | x : | | active_support.rb:320:35:320:35 | x : | active_support.rb:320:10:320:36 | call to dump | -| active_support.rb:324:9:324:18 | call to source : | active_support.rb:325:35:325:35 | x : | +| active_support.rb:324:5:324:5 | x : | active_support.rb:325:35:325:35 | x : | +| active_support.rb:324:9:324:18 | call to source : | active_support.rb:324:5:324:5 | x : | | active_support.rb:325:35:325:35 | x : | active_support.rb:325:10:325:36 | call to load | -| active_support.rb:329:9:329:18 | call to source : | active_support.rb:330:10:330:10 | x : | -| active_support.rb:329:9:329:18 | call to source : | active_support.rb:331:10:331:10 | x : | -| active_support.rb:330:10:330:10 | x : | active_support.rb:332:10:332:10 | y [element 0] : | +| active_support.rb:329:5:329:5 | x : | active_support.rb:330:10:330:10 | x : | +| active_support.rb:329:5:329:5 | x : | active_support.rb:331:10:331:10 | x : | +| active_support.rb:329:9:329:18 | call to source : | active_support.rb:329:5:329:5 | x : | +| active_support.rb:330:5:330:5 | y [element 0] : | active_support.rb:332:10:332:10 | y [element 0] : | +| active_support.rb:330:10:330:10 | x : | active_support.rb:330:5:330:5 | y [element 0] : | | active_support.rb:331:10:331:10 | x : | active_support.rb:331:10:331:18 | call to to_json | | active_support.rb:332:10:332:10 | y [element 0] : | active_support.rb:332:10:332:18 | call to to_json | -| hash_extensions.rb:2:14:2:24 | call to source : | hash_extensions.rb:3:9:3:9 | h [element :a] : | -| hash_extensions.rb:2:14:2:24 | call to source : | hash_extensions.rb:3:9:3:9 | h [element :a] : | +| hash_extensions.rb:2:5:2:5 | h [element :a] : | hash_extensions.rb:3:9:3:9 | h [element :a] : | +| hash_extensions.rb:2:5:2:5 | h [element :a] : | hash_extensions.rb:3:9:3:9 | h [element :a] : | +| hash_extensions.rb:2:14:2:24 | call to source : | hash_extensions.rb:2:5:2:5 | h [element :a] : | +| hash_extensions.rb:2:14:2:24 | call to source : | hash_extensions.rb:2:5:2:5 | h [element :a] : | +| hash_extensions.rb:3:5:3:5 | x [element] : | hash_extensions.rb:4:10:4:10 | x [element] : | +| hash_extensions.rb:3:5:3:5 | x [element] : | hash_extensions.rb:4:10:4:10 | x [element] : | | hash_extensions.rb:3:9:3:9 | h [element :a] : | hash_extensions.rb:3:9:3:24 | call to stringify_keys [element] : | | hash_extensions.rb:3:9:3:9 | h [element :a] : | hash_extensions.rb:3:9:3:24 | call to stringify_keys [element] : | -| hash_extensions.rb:3:9:3:24 | call to stringify_keys [element] : | hash_extensions.rb:4:10:4:10 | x [element] : | -| hash_extensions.rb:3:9:3:24 | call to stringify_keys [element] : | hash_extensions.rb:4:10:4:10 | x [element] : | +| hash_extensions.rb:3:9:3:24 | call to stringify_keys [element] : | hash_extensions.rb:3:5:3:5 | x [element] : | +| hash_extensions.rb:3:9:3:24 | call to stringify_keys [element] : | hash_extensions.rb:3:5:3:5 | x [element] : | | hash_extensions.rb:4:10:4:10 | x [element] : | hash_extensions.rb:4:10:4:14 | ...[...] | | hash_extensions.rb:4:10:4:10 | x [element] : | hash_extensions.rb:4:10:4:14 | ...[...] | -| hash_extensions.rb:10:14:10:24 | call to source : | hash_extensions.rb:11:9:11:9 | h [element :a] : | -| hash_extensions.rb:10:14:10:24 | call to source : | hash_extensions.rb:11:9:11:9 | h [element :a] : | +| hash_extensions.rb:10:5:10:5 | h [element :a] : | hash_extensions.rb:11:9:11:9 | h [element :a] : | +| hash_extensions.rb:10:5:10:5 | h [element :a] : | hash_extensions.rb:11:9:11:9 | h [element :a] : | +| hash_extensions.rb:10:14:10:24 | call to source : | hash_extensions.rb:10:5:10:5 | h [element :a] : | +| hash_extensions.rb:10:14:10:24 | call to source : | hash_extensions.rb:10:5:10:5 | h [element :a] : | +| hash_extensions.rb:11:5:11:5 | x [element] : | hash_extensions.rb:12:10:12:10 | x [element] : | +| hash_extensions.rb:11:5:11:5 | x [element] : | hash_extensions.rb:12:10:12:10 | x [element] : | | hash_extensions.rb:11:9:11:9 | h [element :a] : | hash_extensions.rb:11:9:11:20 | call to to_options [element] : | | hash_extensions.rb:11:9:11:9 | h [element :a] : | hash_extensions.rb:11:9:11:20 | call to to_options [element] : | -| hash_extensions.rb:11:9:11:20 | call to to_options [element] : | hash_extensions.rb:12:10:12:10 | x [element] : | -| hash_extensions.rb:11:9:11:20 | call to to_options [element] : | hash_extensions.rb:12:10:12:10 | x [element] : | +| hash_extensions.rb:11:9:11:20 | call to to_options [element] : | hash_extensions.rb:11:5:11:5 | x [element] : | +| hash_extensions.rb:11:9:11:20 | call to to_options [element] : | hash_extensions.rb:11:5:11:5 | x [element] : | | hash_extensions.rb:12:10:12:10 | x [element] : | hash_extensions.rb:12:10:12:14 | ...[...] | | hash_extensions.rb:12:10:12:10 | x [element] : | hash_extensions.rb:12:10:12:14 | ...[...] | -| hash_extensions.rb:18:14:18:24 | call to source : | hash_extensions.rb:19:9:19:9 | h [element :a] : | -| hash_extensions.rb:18:14:18:24 | call to source : | hash_extensions.rb:19:9:19:9 | h [element :a] : | +| hash_extensions.rb:18:5:18:5 | h [element :a] : | hash_extensions.rb:19:9:19:9 | h [element :a] : | +| hash_extensions.rb:18:5:18:5 | h [element :a] : | hash_extensions.rb:19:9:19:9 | h [element :a] : | +| hash_extensions.rb:18:14:18:24 | call to source : | hash_extensions.rb:18:5:18:5 | h [element :a] : | +| hash_extensions.rb:18:14:18:24 | call to source : | hash_extensions.rb:18:5:18:5 | h [element :a] : | +| hash_extensions.rb:19:5:19:5 | x [element] : | hash_extensions.rb:20:10:20:10 | x [element] : | +| hash_extensions.rb:19:5:19:5 | x [element] : | hash_extensions.rb:20:10:20:10 | x [element] : | | hash_extensions.rb:19:9:19:9 | h [element :a] : | hash_extensions.rb:19:9:19:24 | call to symbolize_keys [element] : | | hash_extensions.rb:19:9:19:9 | h [element :a] : | hash_extensions.rb:19:9:19:24 | call to symbolize_keys [element] : | -| hash_extensions.rb:19:9:19:24 | call to symbolize_keys [element] : | hash_extensions.rb:20:10:20:10 | x [element] : | -| hash_extensions.rb:19:9:19:24 | call to symbolize_keys [element] : | hash_extensions.rb:20:10:20:10 | x [element] : | +| hash_extensions.rb:19:9:19:24 | call to symbolize_keys [element] : | hash_extensions.rb:19:5:19:5 | x [element] : | +| hash_extensions.rb:19:9:19:24 | call to symbolize_keys [element] : | hash_extensions.rb:19:5:19:5 | x [element] : | | hash_extensions.rb:20:10:20:10 | x [element] : | hash_extensions.rb:20:10:20:14 | ...[...] | | hash_extensions.rb:20:10:20:10 | x [element] : | hash_extensions.rb:20:10:20:14 | ...[...] | -| hash_extensions.rb:26:14:26:24 | call to source : | hash_extensions.rb:27:9:27:9 | h [element :a] : | -| hash_extensions.rb:26:14:26:24 | call to source : | hash_extensions.rb:27:9:27:9 | h [element :a] : | +| hash_extensions.rb:26:5:26:5 | h [element :a] : | hash_extensions.rb:27:9:27:9 | h [element :a] : | +| hash_extensions.rb:26:5:26:5 | h [element :a] : | hash_extensions.rb:27:9:27:9 | h [element :a] : | +| hash_extensions.rb:26:14:26:24 | call to source : | hash_extensions.rb:26:5:26:5 | h [element :a] : | +| hash_extensions.rb:26:14:26:24 | call to source : | hash_extensions.rb:26:5:26:5 | h [element :a] : | +| hash_extensions.rb:27:5:27:5 | x [element] : | hash_extensions.rb:28:10:28:10 | x [element] : | +| hash_extensions.rb:27:5:27:5 | x [element] : | hash_extensions.rb:28:10:28:10 | x [element] : | | hash_extensions.rb:27:9:27:9 | h [element :a] : | hash_extensions.rb:27:9:27:29 | call to deep_stringify_keys [element] : | | hash_extensions.rb:27:9:27:9 | h [element :a] : | hash_extensions.rb:27:9:27:29 | call to deep_stringify_keys [element] : | -| hash_extensions.rb:27:9:27:29 | call to deep_stringify_keys [element] : | hash_extensions.rb:28:10:28:10 | x [element] : | -| hash_extensions.rb:27:9:27:29 | call to deep_stringify_keys [element] : | hash_extensions.rb:28:10:28:10 | x [element] : | +| hash_extensions.rb:27:9:27:29 | call to deep_stringify_keys [element] : | hash_extensions.rb:27:5:27:5 | x [element] : | +| hash_extensions.rb:27:9:27:29 | call to deep_stringify_keys [element] : | hash_extensions.rb:27:5:27:5 | x [element] : | | hash_extensions.rb:28:10:28:10 | x [element] : | hash_extensions.rb:28:10:28:14 | ...[...] | | hash_extensions.rb:28:10:28:10 | x [element] : | hash_extensions.rb:28:10:28:14 | ...[...] | -| hash_extensions.rb:34:14:34:24 | call to source : | hash_extensions.rb:35:9:35:9 | h [element :a] : | -| hash_extensions.rb:34:14:34:24 | call to source : | hash_extensions.rb:35:9:35:9 | h [element :a] : | +| hash_extensions.rb:34:5:34:5 | h [element :a] : | hash_extensions.rb:35:9:35:9 | h [element :a] : | +| hash_extensions.rb:34:5:34:5 | h [element :a] : | hash_extensions.rb:35:9:35:9 | h [element :a] : | +| hash_extensions.rb:34:14:34:24 | call to source : | hash_extensions.rb:34:5:34:5 | h [element :a] : | +| hash_extensions.rb:34:14:34:24 | call to source : | hash_extensions.rb:34:5:34:5 | h [element :a] : | +| hash_extensions.rb:35:5:35:5 | x [element] : | hash_extensions.rb:36:10:36:10 | x [element] : | +| hash_extensions.rb:35:5:35:5 | x [element] : | hash_extensions.rb:36:10:36:10 | x [element] : | | hash_extensions.rb:35:9:35:9 | h [element :a] : | hash_extensions.rb:35:9:35:29 | call to deep_symbolize_keys [element] : | | hash_extensions.rb:35:9:35:9 | h [element :a] : | hash_extensions.rb:35:9:35:29 | call to deep_symbolize_keys [element] : | -| hash_extensions.rb:35:9:35:29 | call to deep_symbolize_keys [element] : | hash_extensions.rb:36:10:36:10 | x [element] : | -| hash_extensions.rb:35:9:35:29 | call to deep_symbolize_keys [element] : | hash_extensions.rb:36:10:36:10 | x [element] : | +| hash_extensions.rb:35:9:35:29 | call to deep_symbolize_keys [element] : | hash_extensions.rb:35:5:35:5 | x [element] : | +| hash_extensions.rb:35:9:35:29 | call to deep_symbolize_keys [element] : | hash_extensions.rb:35:5:35:5 | x [element] : | | hash_extensions.rb:36:10:36:10 | x [element] : | hash_extensions.rb:36:10:36:14 | ...[...] | | hash_extensions.rb:36:10:36:10 | x [element] : | hash_extensions.rb:36:10:36:14 | ...[...] | -| hash_extensions.rb:42:14:42:24 | call to source : | hash_extensions.rb:43:9:43:9 | h [element :a] : | -| hash_extensions.rb:42:14:42:24 | call to source : | hash_extensions.rb:43:9:43:9 | h [element :a] : | +| hash_extensions.rb:42:5:42:5 | h [element :a] : | hash_extensions.rb:43:9:43:9 | h [element :a] : | +| hash_extensions.rb:42:5:42:5 | h [element :a] : | hash_extensions.rb:43:9:43:9 | h [element :a] : | +| hash_extensions.rb:42:14:42:24 | call to source : | hash_extensions.rb:42:5:42:5 | h [element :a] : | +| hash_extensions.rb:42:14:42:24 | call to source : | hash_extensions.rb:42:5:42:5 | h [element :a] : | +| hash_extensions.rb:43:5:43:5 | x [element] : | hash_extensions.rb:44:10:44:10 | x [element] : | +| hash_extensions.rb:43:5:43:5 | x [element] : | hash_extensions.rb:44:10:44:10 | x [element] : | | hash_extensions.rb:43:9:43:9 | h [element :a] : | hash_extensions.rb:43:9:43:33 | call to with_indifferent_access [element] : | | hash_extensions.rb:43:9:43:9 | h [element :a] : | hash_extensions.rb:43:9:43:33 | call to with_indifferent_access [element] : | -| hash_extensions.rb:43:9:43:33 | call to with_indifferent_access [element] : | hash_extensions.rb:44:10:44:10 | x [element] : | -| hash_extensions.rb:43:9:43:33 | call to with_indifferent_access [element] : | hash_extensions.rb:44:10:44:10 | x [element] : | +| hash_extensions.rb:43:9:43:33 | call to with_indifferent_access [element] : | hash_extensions.rb:43:5:43:5 | x [element] : | +| hash_extensions.rb:43:9:43:33 | call to with_indifferent_access [element] : | hash_extensions.rb:43:5:43:5 | x [element] : | | hash_extensions.rb:44:10:44:10 | x [element] : | hash_extensions.rb:44:10:44:14 | ...[...] | | hash_extensions.rb:44:10:44:10 | x [element] : | hash_extensions.rb:44:10:44:14 | ...[...] | -| hash_extensions.rb:50:14:50:23 | call to taint : | hash_extensions.rb:51:9:51:9 | h [element :a] : | -| hash_extensions.rb:50:14:50:23 | call to taint : | hash_extensions.rb:51:9:51:9 | h [element :a] : | -| hash_extensions.rb:50:29:50:38 | call to taint : | hash_extensions.rb:51:9:51:9 | h [element :b] : | -| hash_extensions.rb:50:29:50:38 | call to taint : | hash_extensions.rb:51:9:51:9 | h [element :b] : | -| hash_extensions.rb:50:52:50:61 | call to taint : | hash_extensions.rb:51:9:51:9 | h [element :d] : | -| hash_extensions.rb:50:52:50:61 | call to taint : | hash_extensions.rb:51:9:51:9 | h [element :d] : | +| hash_extensions.rb:50:5:50:5 | h [element :a] : | hash_extensions.rb:51:9:51:9 | h [element :a] : | +| hash_extensions.rb:50:5:50:5 | h [element :a] : | hash_extensions.rb:51:9:51:9 | h [element :a] : | +| hash_extensions.rb:50:5:50:5 | h [element :b] : | hash_extensions.rb:51:9:51:9 | h [element :b] : | +| hash_extensions.rb:50:5:50:5 | h [element :b] : | hash_extensions.rb:51:9:51:9 | h [element :b] : | +| hash_extensions.rb:50:5:50:5 | h [element :d] : | hash_extensions.rb:51:9:51:9 | h [element :d] : | +| hash_extensions.rb:50:5:50:5 | h [element :d] : | hash_extensions.rb:51:9:51:9 | h [element :d] : | +| hash_extensions.rb:50:14:50:23 | call to taint : | hash_extensions.rb:50:5:50:5 | h [element :a] : | +| hash_extensions.rb:50:14:50:23 | call to taint : | hash_extensions.rb:50:5:50:5 | h [element :a] : | +| hash_extensions.rb:50:29:50:38 | call to taint : | hash_extensions.rb:50:5:50:5 | h [element :b] : | +| hash_extensions.rb:50:29:50:38 | call to taint : | hash_extensions.rb:50:5:50:5 | h [element :b] : | +| hash_extensions.rb:50:52:50:61 | call to taint : | hash_extensions.rb:50:5:50:5 | h [element :d] : | +| hash_extensions.rb:50:52:50:61 | call to taint : | hash_extensions.rb:50:5:50:5 | h [element :d] : | +| hash_extensions.rb:51:5:51:5 | x [element :a] : | hash_extensions.rb:58:10:58:10 | x [element :a] : | +| hash_extensions.rb:51:5:51:5 | x [element :a] : | hash_extensions.rb:58:10:58:10 | x [element :a] : | +| hash_extensions.rb:51:5:51:5 | x [element :b] : | hash_extensions.rb:59:10:59:10 | x [element :b] : | +| hash_extensions.rb:51:5:51:5 | x [element :b] : | hash_extensions.rb:59:10:59:10 | x [element :b] : | | hash_extensions.rb:51:9:51:9 | [post] h [element :d] : | hash_extensions.rb:56:10:56:10 | h [element :d] : | | hash_extensions.rb:51:9:51:9 | [post] h [element :d] : | hash_extensions.rb:56:10:56:10 | h [element :d] : | | hash_extensions.rb:51:9:51:9 | h [element :a] : | hash_extensions.rb:51:9:51:29 | call to extract! [element :a] : | @@ -265,22 +393,32 @@ edges | hash_extensions.rb:51:9:51:9 | h [element :b] : | hash_extensions.rb:51:9:51:29 | call to extract! [element :b] : | | hash_extensions.rb:51:9:51:9 | h [element :d] : | hash_extensions.rb:51:9:51:9 | [post] h [element :d] : | | hash_extensions.rb:51:9:51:9 | h [element :d] : | hash_extensions.rb:51:9:51:9 | [post] h [element :d] : | -| hash_extensions.rb:51:9:51:29 | call to extract! [element :a] : | hash_extensions.rb:58:10:58:10 | x [element :a] : | -| hash_extensions.rb:51:9:51:29 | call to extract! [element :a] : | hash_extensions.rb:58:10:58:10 | x [element :a] : | -| hash_extensions.rb:51:9:51:29 | call to extract! [element :b] : | hash_extensions.rb:59:10:59:10 | x [element :b] : | -| hash_extensions.rb:51:9:51:29 | call to extract! [element :b] : | hash_extensions.rb:59:10:59:10 | x [element :b] : | +| hash_extensions.rb:51:9:51:29 | call to extract! [element :a] : | hash_extensions.rb:51:5:51:5 | x [element :a] : | +| hash_extensions.rb:51:9:51:29 | call to extract! [element :a] : | hash_extensions.rb:51:5:51:5 | x [element :a] : | +| hash_extensions.rb:51:9:51:29 | call to extract! [element :b] : | hash_extensions.rb:51:5:51:5 | x [element :b] : | +| hash_extensions.rb:51:9:51:29 | call to extract! [element :b] : | hash_extensions.rb:51:5:51:5 | x [element :b] : | | hash_extensions.rb:56:10:56:10 | h [element :d] : | hash_extensions.rb:56:10:56:14 | ...[...] | | hash_extensions.rb:56:10:56:10 | h [element :d] : | hash_extensions.rb:56:10:56:14 | ...[...] | | hash_extensions.rb:58:10:58:10 | x [element :a] : | hash_extensions.rb:58:10:58:14 | ...[...] | | hash_extensions.rb:58:10:58:10 | x [element :a] : | hash_extensions.rb:58:10:58:14 | ...[...] | | hash_extensions.rb:59:10:59:10 | x [element :b] : | hash_extensions.rb:59:10:59:14 | ...[...] | | hash_extensions.rb:59:10:59:10 | x [element :b] : | hash_extensions.rb:59:10:59:14 | ...[...] | -| hash_extensions.rb:67:15:67:25 | call to source : | hash_extensions.rb:68:9:68:14 | values [element 0] : | -| hash_extensions.rb:67:15:67:25 | call to source : | hash_extensions.rb:68:9:68:14 | values [element 0] : | -| hash_extensions.rb:67:28:67:38 | call to source : | hash_extensions.rb:68:9:68:14 | values [element 1] : | -| hash_extensions.rb:67:28:67:38 | call to source : | hash_extensions.rb:68:9:68:14 | values [element 1] : | -| hash_extensions.rb:67:41:67:51 | call to source : | hash_extensions.rb:68:9:68:14 | values [element 2] : | -| hash_extensions.rb:67:41:67:51 | call to source : | hash_extensions.rb:68:9:68:14 | values [element 2] : | +| hash_extensions.rb:67:5:67:10 | values [element 0] : | hash_extensions.rb:68:9:68:14 | values [element 0] : | +| hash_extensions.rb:67:5:67:10 | values [element 0] : | hash_extensions.rb:68:9:68:14 | values [element 0] : | +| hash_extensions.rb:67:5:67:10 | values [element 1] : | hash_extensions.rb:68:9:68:14 | values [element 1] : | +| hash_extensions.rb:67:5:67:10 | values [element 1] : | hash_extensions.rb:68:9:68:14 | values [element 1] : | +| hash_extensions.rb:67:5:67:10 | values [element 2] : | hash_extensions.rb:68:9:68:14 | values [element 2] : | +| hash_extensions.rb:67:5:67:10 | values [element 2] : | hash_extensions.rb:68:9:68:14 | values [element 2] : | +| hash_extensions.rb:67:15:67:25 | call to source : | hash_extensions.rb:67:5:67:10 | values [element 0] : | +| hash_extensions.rb:67:15:67:25 | call to source : | hash_extensions.rb:67:5:67:10 | values [element 0] : | +| hash_extensions.rb:67:28:67:38 | call to source : | hash_extensions.rb:67:5:67:10 | values [element 1] : | +| hash_extensions.rb:67:28:67:38 | call to source : | hash_extensions.rb:67:5:67:10 | values [element 1] : | +| hash_extensions.rb:67:41:67:51 | call to source : | hash_extensions.rb:67:5:67:10 | values [element 2] : | +| hash_extensions.rb:67:41:67:51 | call to source : | hash_extensions.rb:67:5:67:10 | values [element 2] : | +| hash_extensions.rb:68:5:68:5 | h [element] : | hash_extensions.rb:73:10:73:10 | h [element] : | +| hash_extensions.rb:68:5:68:5 | h [element] : | hash_extensions.rb:73:10:73:10 | h [element] : | +| hash_extensions.rb:68:5:68:5 | h [element] : | hash_extensions.rb:74:10:74:10 | h [element] : | +| hash_extensions.rb:68:5:68:5 | h [element] : | hash_extensions.rb:74:10:74:10 | h [element] : | | hash_extensions.rb:68:9:68:14 | values [element 0] : | hash_extensions.rb:68:9:71:7 | call to index_by [element] : | | hash_extensions.rb:68:9:68:14 | values [element 0] : | hash_extensions.rb:68:9:71:7 | call to index_by [element] : | | hash_extensions.rb:68:9:68:14 | values [element 0] : | hash_extensions.rb:68:29:68:33 | value : | @@ -293,32 +431,38 @@ edges | hash_extensions.rb:68:9:68:14 | values [element 2] : | hash_extensions.rb:68:9:71:7 | call to index_by [element] : | | hash_extensions.rb:68:9:68:14 | values [element 2] : | hash_extensions.rb:68:29:68:33 | value : | | hash_extensions.rb:68:9:68:14 | values [element 2] : | hash_extensions.rb:68:29:68:33 | value : | -| hash_extensions.rb:68:9:71:7 | call to index_by [element] : | hash_extensions.rb:73:10:73:10 | h [element] : | -| hash_extensions.rb:68:9:71:7 | call to index_by [element] : | hash_extensions.rb:73:10:73:10 | h [element] : | -| hash_extensions.rb:68:9:71:7 | call to index_by [element] : | hash_extensions.rb:74:10:74:10 | h [element] : | -| hash_extensions.rb:68:9:71:7 | call to index_by [element] : | hash_extensions.rb:74:10:74:10 | h [element] : | +| hash_extensions.rb:68:9:71:7 | call to index_by [element] : | hash_extensions.rb:68:5:68:5 | h [element] : | +| hash_extensions.rb:68:9:71:7 | call to index_by [element] : | hash_extensions.rb:68:5:68:5 | h [element] : | | hash_extensions.rb:68:29:68:33 | value : | hash_extensions.rb:69:14:69:18 | value | | hash_extensions.rb:68:29:68:33 | value : | hash_extensions.rb:69:14:69:18 | value | | hash_extensions.rb:73:10:73:10 | h [element] : | hash_extensions.rb:73:10:73:16 | ...[...] | | hash_extensions.rb:73:10:73:10 | h [element] : | hash_extensions.rb:73:10:73:16 | ...[...] | | hash_extensions.rb:74:10:74:10 | h [element] : | hash_extensions.rb:74:10:74:16 | ...[...] | | hash_extensions.rb:74:10:74:10 | h [element] : | hash_extensions.rb:74:10:74:16 | ...[...] | -| hash_extensions.rb:80:15:80:25 | call to source : | hash_extensions.rb:81:9:81:14 | values [element 0] : | -| hash_extensions.rb:80:15:80:25 | call to source : | hash_extensions.rb:81:9:81:14 | values [element 0] : | -| hash_extensions.rb:80:28:80:38 | call to source : | hash_extensions.rb:81:9:81:14 | values [element 1] : | -| hash_extensions.rb:80:28:80:38 | call to source : | hash_extensions.rb:81:9:81:14 | values [element 1] : | -| hash_extensions.rb:80:41:80:51 | call to source : | hash_extensions.rb:81:9:81:14 | values [element 2] : | -| hash_extensions.rb:80:41:80:51 | call to source : | hash_extensions.rb:81:9:81:14 | values [element 2] : | +| hash_extensions.rb:80:5:80:10 | values [element 0] : | hash_extensions.rb:81:9:81:14 | values [element 0] : | +| hash_extensions.rb:80:5:80:10 | values [element 0] : | hash_extensions.rb:81:9:81:14 | values [element 0] : | +| hash_extensions.rb:80:5:80:10 | values [element 1] : | hash_extensions.rb:81:9:81:14 | values [element 1] : | +| hash_extensions.rb:80:5:80:10 | values [element 1] : | hash_extensions.rb:81:9:81:14 | values [element 1] : | +| hash_extensions.rb:80:5:80:10 | values [element 2] : | hash_extensions.rb:81:9:81:14 | values [element 2] : | +| hash_extensions.rb:80:5:80:10 | values [element 2] : | hash_extensions.rb:81:9:81:14 | values [element 2] : | +| hash_extensions.rb:80:15:80:25 | call to source : | hash_extensions.rb:80:5:80:10 | values [element 0] : | +| hash_extensions.rb:80:15:80:25 | call to source : | hash_extensions.rb:80:5:80:10 | values [element 0] : | +| hash_extensions.rb:80:28:80:38 | call to source : | hash_extensions.rb:80:5:80:10 | values [element 1] : | +| hash_extensions.rb:80:28:80:38 | call to source : | hash_extensions.rb:80:5:80:10 | values [element 1] : | +| hash_extensions.rb:80:41:80:51 | call to source : | hash_extensions.rb:80:5:80:10 | values [element 2] : | +| hash_extensions.rb:80:41:80:51 | call to source : | hash_extensions.rb:80:5:80:10 | values [element 2] : | +| hash_extensions.rb:81:5:81:5 | h [element] : | hash_extensions.rb:86:10:86:10 | h [element] : | +| hash_extensions.rb:81:5:81:5 | h [element] : | hash_extensions.rb:86:10:86:10 | h [element] : | +| hash_extensions.rb:81:5:81:5 | h [element] : | hash_extensions.rb:87:10:87:10 | h [element] : | +| hash_extensions.rb:81:5:81:5 | h [element] : | hash_extensions.rb:87:10:87:10 | h [element] : | | hash_extensions.rb:81:9:81:14 | values [element 0] : | hash_extensions.rb:81:31:81:33 | key : | | hash_extensions.rb:81:9:81:14 | values [element 0] : | hash_extensions.rb:81:31:81:33 | key : | | hash_extensions.rb:81:9:81:14 | values [element 1] : | hash_extensions.rb:81:31:81:33 | key : | | hash_extensions.rb:81:9:81:14 | values [element 1] : | hash_extensions.rb:81:31:81:33 | key : | | hash_extensions.rb:81:9:81:14 | values [element 2] : | hash_extensions.rb:81:31:81:33 | key : | | hash_extensions.rb:81:9:81:14 | values [element 2] : | hash_extensions.rb:81:31:81:33 | key : | -| hash_extensions.rb:81:9:84:7 | call to index_with [element] : | hash_extensions.rb:86:10:86:10 | h [element] : | -| hash_extensions.rb:81:9:84:7 | call to index_with [element] : | hash_extensions.rb:86:10:86:10 | h [element] : | -| hash_extensions.rb:81:9:84:7 | call to index_with [element] : | hash_extensions.rb:87:10:87:10 | h [element] : | -| hash_extensions.rb:81:9:84:7 | call to index_with [element] : | hash_extensions.rb:87:10:87:10 | h [element] : | +| hash_extensions.rb:81:9:84:7 | call to index_with [element] : | hash_extensions.rb:81:5:81:5 | h [element] : | +| hash_extensions.rb:81:9:84:7 | call to index_with [element] : | hash_extensions.rb:81:5:81:5 | h [element] : | | hash_extensions.rb:81:31:81:33 | key : | hash_extensions.rb:82:14:82:16 | key | | hash_extensions.rb:81:31:81:33 | key : | hash_extensions.rb:82:14:82:16 | key | | hash_extensions.rb:83:9:83:19 | call to source : | hash_extensions.rb:81:9:84:7 | call to index_with [element] : | @@ -327,28 +471,34 @@ edges | hash_extensions.rb:86:10:86:10 | h [element] : | hash_extensions.rb:86:10:86:16 | ...[...] | | hash_extensions.rb:87:10:87:10 | h [element] : | hash_extensions.rb:87:10:87:16 | ...[...] | | hash_extensions.rb:87:10:87:10 | h [element] : | hash_extensions.rb:87:10:87:16 | ...[...] | -| hash_extensions.rb:89:9:89:38 | call to index_with [element] : | hash_extensions.rb:91:10:91:10 | j [element] : | -| hash_extensions.rb:89:9:89:38 | call to index_with [element] : | hash_extensions.rb:91:10:91:10 | j [element] : | -| hash_extensions.rb:89:9:89:38 | call to index_with [element] : | hash_extensions.rb:92:10:92:10 | j [element] : | -| hash_extensions.rb:89:9:89:38 | call to index_with [element] : | hash_extensions.rb:92:10:92:10 | j [element] : | +| hash_extensions.rb:89:5:89:5 | j [element] : | hash_extensions.rb:91:10:91:10 | j [element] : | +| hash_extensions.rb:89:5:89:5 | j [element] : | hash_extensions.rb:91:10:91:10 | j [element] : | +| hash_extensions.rb:89:5:89:5 | j [element] : | hash_extensions.rb:92:10:92:10 | j [element] : | +| hash_extensions.rb:89:5:89:5 | j [element] : | hash_extensions.rb:92:10:92:10 | j [element] : | +| hash_extensions.rb:89:9:89:38 | call to index_with [element] : | hash_extensions.rb:89:5:89:5 | j [element] : | +| hash_extensions.rb:89:9:89:38 | call to index_with [element] : | hash_extensions.rb:89:5:89:5 | j [element] : | | hash_extensions.rb:89:27:89:37 | call to source : | hash_extensions.rb:89:9:89:38 | call to index_with [element] : | | hash_extensions.rb:89:27:89:37 | call to source : | hash_extensions.rb:89:9:89:38 | call to index_with [element] : | | hash_extensions.rb:91:10:91:10 | j [element] : | hash_extensions.rb:91:10:91:16 | ...[...] | | hash_extensions.rb:91:10:91:10 | j [element] : | hash_extensions.rb:91:10:91:16 | ...[...] | | hash_extensions.rb:92:10:92:10 | j [element] : | hash_extensions.rb:92:10:92:16 | ...[...] | | hash_extensions.rb:92:10:92:10 | j [element] : | hash_extensions.rb:92:10:92:16 | ...[...] | -| hash_extensions.rb:98:21:98:31 | call to source : | hash_extensions.rb:99:10:99:15 | values [element 0, element :id] : | -| hash_extensions.rb:98:21:98:31 | call to source : | hash_extensions.rb:99:10:99:15 | values [element 0, element :id] : | -| hash_extensions.rb:98:21:98:31 | call to source : | hash_extensions.rb:101:10:101:15 | values [element 0, element :id] : | -| hash_extensions.rb:98:21:98:31 | call to source : | hash_extensions.rb:101:10:101:15 | values [element 0, element :id] : | -| hash_extensions.rb:98:21:98:31 | call to source : | hash_extensions.rb:104:10:104:15 | values [element 0, element :id] : | -| hash_extensions.rb:98:21:98:31 | call to source : | hash_extensions.rb:104:10:104:15 | values [element 0, element :id] : | -| hash_extensions.rb:98:40:98:54 | call to source : | hash_extensions.rb:100:10:100:15 | values [element 0, element :name] : | -| hash_extensions.rb:98:40:98:54 | call to source : | hash_extensions.rb:100:10:100:15 | values [element 0, element :name] : | -| hash_extensions.rb:98:40:98:54 | call to source : | hash_extensions.rb:102:10:102:15 | values [element 0, element :name] : | -| hash_extensions.rb:98:40:98:54 | call to source : | hash_extensions.rb:102:10:102:15 | values [element 0, element :name] : | -| hash_extensions.rb:98:40:98:54 | call to source : | hash_extensions.rb:103:10:103:15 | values [element 0, element :name] : | -| hash_extensions.rb:98:40:98:54 | call to source : | hash_extensions.rb:103:10:103:15 | values [element 0, element :name] : | +| hash_extensions.rb:98:5:98:10 | values [element 0, element :id] : | hash_extensions.rb:99:10:99:15 | values [element 0, element :id] : | +| hash_extensions.rb:98:5:98:10 | values [element 0, element :id] : | hash_extensions.rb:99:10:99:15 | values [element 0, element :id] : | +| hash_extensions.rb:98:5:98:10 | values [element 0, element :id] : | hash_extensions.rb:101:10:101:15 | values [element 0, element :id] : | +| hash_extensions.rb:98:5:98:10 | values [element 0, element :id] : | hash_extensions.rb:101:10:101:15 | values [element 0, element :id] : | +| hash_extensions.rb:98:5:98:10 | values [element 0, element :id] : | hash_extensions.rb:104:10:104:15 | values [element 0, element :id] : | +| hash_extensions.rb:98:5:98:10 | values [element 0, element :id] : | hash_extensions.rb:104:10:104:15 | values [element 0, element :id] : | +| hash_extensions.rb:98:5:98:10 | values [element 0, element :name] : | hash_extensions.rb:100:10:100:15 | values [element 0, element :name] : | +| hash_extensions.rb:98:5:98:10 | values [element 0, element :name] : | hash_extensions.rb:100:10:100:15 | values [element 0, element :name] : | +| hash_extensions.rb:98:5:98:10 | values [element 0, element :name] : | hash_extensions.rb:102:10:102:15 | values [element 0, element :name] : | +| hash_extensions.rb:98:5:98:10 | values [element 0, element :name] : | hash_extensions.rb:102:10:102:15 | values [element 0, element :name] : | +| hash_extensions.rb:98:5:98:10 | values [element 0, element :name] : | hash_extensions.rb:103:10:103:15 | values [element 0, element :name] : | +| hash_extensions.rb:98:5:98:10 | values [element 0, element :name] : | hash_extensions.rb:103:10:103:15 | values [element 0, element :name] : | +| hash_extensions.rb:98:21:98:31 | call to source : | hash_extensions.rb:98:5:98:10 | values [element 0, element :id] : | +| hash_extensions.rb:98:21:98:31 | call to source : | hash_extensions.rb:98:5:98:10 | values [element 0, element :id] : | +| hash_extensions.rb:98:40:98:54 | call to source : | hash_extensions.rb:98:5:98:10 | values [element 0, element :name] : | +| hash_extensions.rb:98:40:98:54 | call to source : | hash_extensions.rb:98:5:98:10 | values [element 0, element :name] : | | hash_extensions.rb:99:10:99:15 | values [element 0, element :id] : | hash_extensions.rb:99:10:99:25 | call to pick | | hash_extensions.rb:99:10:99:15 | values [element 0, element :id] : | hash_extensions.rb:99:10:99:25 | call to pick | | hash_extensions.rb:100:10:100:15 | values [element 0, element :name] : | hash_extensions.rb:100:10:100:27 | call to pick | @@ -369,26 +519,34 @@ edges | hash_extensions.rb:104:10:104:15 | values [element 0, element :id] : | hash_extensions.rb:104:10:104:32 | call to pick [element 1] : | | hash_extensions.rb:104:10:104:32 | call to pick [element 1] : | hash_extensions.rb:104:10:104:35 | ...[...] | | hash_extensions.rb:104:10:104:32 | call to pick [element 1] : | hash_extensions.rb:104:10:104:35 | ...[...] | -| hash_extensions.rb:110:21:110:31 | call to source : | hash_extensions.rb:112:10:112:15 | values [element 0, element :id] : | -| hash_extensions.rb:110:21:110:31 | call to source : | hash_extensions.rb:112:10:112:15 | values [element 0, element :id] : | -| hash_extensions.rb:110:21:110:31 | call to source : | hash_extensions.rb:115:10:115:15 | values [element 0, element :id] : | -| hash_extensions.rb:110:21:110:31 | call to source : | hash_extensions.rb:115:10:115:15 | values [element 0, element :id] : | -| hash_extensions.rb:110:40:110:54 | call to source : | hash_extensions.rb:111:10:111:15 | values [element 0, element :name] : | -| hash_extensions.rb:110:40:110:54 | call to source : | hash_extensions.rb:111:10:111:15 | values [element 0, element :name] : | -| hash_extensions.rb:110:40:110:54 | call to source : | hash_extensions.rb:113:10:113:15 | values [element 0, element :name] : | -| hash_extensions.rb:110:40:110:54 | call to source : | hash_extensions.rb:113:10:113:15 | values [element 0, element :name] : | -| hash_extensions.rb:110:40:110:54 | call to source : | hash_extensions.rb:114:10:114:15 | values [element 0, element :name] : | -| hash_extensions.rb:110:40:110:54 | call to source : | hash_extensions.rb:114:10:114:15 | values [element 0, element :name] : | -| hash_extensions.rb:110:65:110:75 | call to source : | hash_extensions.rb:112:10:112:15 | values [element 1, element :id] : | -| hash_extensions.rb:110:65:110:75 | call to source : | hash_extensions.rb:112:10:112:15 | values [element 1, element :id] : | -| hash_extensions.rb:110:65:110:75 | call to source : | hash_extensions.rb:115:10:115:15 | values [element 1, element :id] : | -| hash_extensions.rb:110:65:110:75 | call to source : | hash_extensions.rb:115:10:115:15 | values [element 1, element :id] : | -| hash_extensions.rb:110:84:110:99 | call to source : | hash_extensions.rb:111:10:111:15 | values [element 1, element :name] : | -| hash_extensions.rb:110:84:110:99 | call to source : | hash_extensions.rb:111:10:111:15 | values [element 1, element :name] : | -| hash_extensions.rb:110:84:110:99 | call to source : | hash_extensions.rb:113:10:113:15 | values [element 1, element :name] : | -| hash_extensions.rb:110:84:110:99 | call to source : | hash_extensions.rb:113:10:113:15 | values [element 1, element :name] : | -| hash_extensions.rb:110:84:110:99 | call to source : | hash_extensions.rb:114:10:114:15 | values [element 1, element :name] : | -| hash_extensions.rb:110:84:110:99 | call to source : | hash_extensions.rb:114:10:114:15 | values [element 1, element :name] : | +| hash_extensions.rb:110:5:110:10 | values [element 0, element :id] : | hash_extensions.rb:112:10:112:15 | values [element 0, element :id] : | +| hash_extensions.rb:110:5:110:10 | values [element 0, element :id] : | hash_extensions.rb:112:10:112:15 | values [element 0, element :id] : | +| hash_extensions.rb:110:5:110:10 | values [element 0, element :id] : | hash_extensions.rb:115:10:115:15 | values [element 0, element :id] : | +| hash_extensions.rb:110:5:110:10 | values [element 0, element :id] : | hash_extensions.rb:115:10:115:15 | values [element 0, element :id] : | +| hash_extensions.rb:110:5:110:10 | values [element 0, element :name] : | hash_extensions.rb:111:10:111:15 | values [element 0, element :name] : | +| hash_extensions.rb:110:5:110:10 | values [element 0, element :name] : | hash_extensions.rb:111:10:111:15 | values [element 0, element :name] : | +| hash_extensions.rb:110:5:110:10 | values [element 0, element :name] : | hash_extensions.rb:113:10:113:15 | values [element 0, element :name] : | +| hash_extensions.rb:110:5:110:10 | values [element 0, element :name] : | hash_extensions.rb:113:10:113:15 | values [element 0, element :name] : | +| hash_extensions.rb:110:5:110:10 | values [element 0, element :name] : | hash_extensions.rb:114:10:114:15 | values [element 0, element :name] : | +| hash_extensions.rb:110:5:110:10 | values [element 0, element :name] : | hash_extensions.rb:114:10:114:15 | values [element 0, element :name] : | +| hash_extensions.rb:110:5:110:10 | values [element 1, element :id] : | hash_extensions.rb:112:10:112:15 | values [element 1, element :id] : | +| hash_extensions.rb:110:5:110:10 | values [element 1, element :id] : | hash_extensions.rb:112:10:112:15 | values [element 1, element :id] : | +| hash_extensions.rb:110:5:110:10 | values [element 1, element :id] : | hash_extensions.rb:115:10:115:15 | values [element 1, element :id] : | +| hash_extensions.rb:110:5:110:10 | values [element 1, element :id] : | hash_extensions.rb:115:10:115:15 | values [element 1, element :id] : | +| hash_extensions.rb:110:5:110:10 | values [element 1, element :name] : | hash_extensions.rb:111:10:111:15 | values [element 1, element :name] : | +| hash_extensions.rb:110:5:110:10 | values [element 1, element :name] : | hash_extensions.rb:111:10:111:15 | values [element 1, element :name] : | +| hash_extensions.rb:110:5:110:10 | values [element 1, element :name] : | hash_extensions.rb:113:10:113:15 | values [element 1, element :name] : | +| hash_extensions.rb:110:5:110:10 | values [element 1, element :name] : | hash_extensions.rb:113:10:113:15 | values [element 1, element :name] : | +| hash_extensions.rb:110:5:110:10 | values [element 1, element :name] : | hash_extensions.rb:114:10:114:15 | values [element 1, element :name] : | +| hash_extensions.rb:110:5:110:10 | values [element 1, element :name] : | hash_extensions.rb:114:10:114:15 | values [element 1, element :name] : | +| hash_extensions.rb:110:21:110:31 | call to source : | hash_extensions.rb:110:5:110:10 | values [element 0, element :id] : | +| hash_extensions.rb:110:21:110:31 | call to source : | hash_extensions.rb:110:5:110:10 | values [element 0, element :id] : | +| hash_extensions.rb:110:40:110:54 | call to source : | hash_extensions.rb:110:5:110:10 | values [element 0, element :name] : | +| hash_extensions.rb:110:40:110:54 | call to source : | hash_extensions.rb:110:5:110:10 | values [element 0, element :name] : | +| hash_extensions.rb:110:65:110:75 | call to source : | hash_extensions.rb:110:5:110:10 | values [element 1, element :id] : | +| hash_extensions.rb:110:65:110:75 | call to source : | hash_extensions.rb:110:5:110:10 | values [element 1, element :id] : | +| hash_extensions.rb:110:84:110:99 | call to source : | hash_extensions.rb:110:5:110:10 | values [element 1, element :name] : | +| hash_extensions.rb:110:84:110:99 | call to source : | hash_extensions.rb:110:5:110:10 | values [element 1, element :name] : | | hash_extensions.rb:111:10:111:15 | values [element 0, element :name] : | hash_extensions.rb:111:10:111:28 | call to pluck [element] : | | hash_extensions.rb:111:10:111:15 | values [element 0, element :name] : | hash_extensions.rb:111:10:111:28 | call to pluck [element] : | | hash_extensions.rb:111:10:111:15 | values [element 1, element :name] : | hash_extensions.rb:111:10:111:28 | call to pluck [element] : | @@ -427,119 +585,161 @@ edges | hash_extensions.rb:115:10:115:33 | call to pluck [element, element 1] : | hash_extensions.rb:115:10:115:36 | ...[...] [element 1] : | | hash_extensions.rb:115:10:115:36 | ...[...] [element 1] : | hash_extensions.rb:115:10:115:39 | ...[...] | | hash_extensions.rb:115:10:115:36 | ...[...] [element 1] : | hash_extensions.rb:115:10:115:39 | ...[...] | -| hash_extensions.rb:122:15:122:25 | call to source : | hash_extensions.rb:125:10:125:15 | single [element 0] : | -| hash_extensions.rb:122:15:122:25 | call to source : | hash_extensions.rb:125:10:125:15 | single [element 0] : | -| hash_extensions.rb:123:14:123:24 | call to source : | hash_extensions.rb:126:10:126:14 | multi [element 0] : | -| hash_extensions.rb:123:14:123:24 | call to source : | hash_extensions.rb:126:10:126:14 | multi [element 0] : | +| hash_extensions.rb:122:5:122:10 | single [element 0] : | hash_extensions.rb:125:10:125:15 | single [element 0] : | +| hash_extensions.rb:122:5:122:10 | single [element 0] : | hash_extensions.rb:125:10:125:15 | single [element 0] : | +| hash_extensions.rb:122:15:122:25 | call to source : | hash_extensions.rb:122:5:122:10 | single [element 0] : | +| hash_extensions.rb:122:15:122:25 | call to source : | hash_extensions.rb:122:5:122:10 | single [element 0] : | +| hash_extensions.rb:123:5:123:9 | multi [element 0] : | hash_extensions.rb:126:10:126:14 | multi [element 0] : | +| hash_extensions.rb:123:5:123:9 | multi [element 0] : | hash_extensions.rb:126:10:126:14 | multi [element 0] : | +| hash_extensions.rb:123:14:123:24 | call to source : | hash_extensions.rb:123:5:123:9 | multi [element 0] : | +| hash_extensions.rb:123:14:123:24 | call to source : | hash_extensions.rb:123:5:123:9 | multi [element 0] : | | hash_extensions.rb:125:10:125:15 | single [element 0] : | hash_extensions.rb:125:10:125:20 | call to sole | | hash_extensions.rb:125:10:125:15 | single [element 0] : | hash_extensions.rb:125:10:125:20 | call to sole | | hash_extensions.rb:126:10:126:14 | multi [element 0] : | hash_extensions.rb:126:10:126:19 | call to sole | | hash_extensions.rb:126:10:126:14 | multi [element 0] : | hash_extensions.rb:126:10:126:19 | call to sole | nodes +| active_support.rb:10:5:10:5 | x : | semmle.label | x : | | active_support.rb:10:9:10:18 | call to source : | semmle.label | call to source : | | active_support.rb:11:10:11:10 | x : | semmle.label | x : | | active_support.rb:11:10:11:19 | call to at | semmle.label | call to at | +| active_support.rb:15:5:15:5 | x : | semmle.label | x : | | active_support.rb:15:9:15:18 | call to source : | semmle.label | call to source : | | active_support.rb:16:10:16:10 | x : | semmle.label | x : | | active_support.rb:16:10:16:19 | call to camelize | semmle.label | call to camelize | +| active_support.rb:20:5:20:5 | x : | semmle.label | x : | | active_support.rb:20:9:20:18 | call to source : | semmle.label | call to source : | | active_support.rb:21:10:21:10 | x : | semmle.label | x : | | active_support.rb:21:10:21:20 | call to camelcase | semmle.label | call to camelcase | +| active_support.rb:25:5:25:5 | x : | semmle.label | x : | | active_support.rb:25:9:25:18 | call to source : | semmle.label | call to source : | | active_support.rb:26:10:26:10 | x : | semmle.label | x : | | active_support.rb:26:10:26:19 | call to classify | semmle.label | call to classify | +| active_support.rb:30:5:30:5 | x : | semmle.label | x : | | active_support.rb:30:9:30:18 | call to source : | semmle.label | call to source : | | active_support.rb:31:10:31:10 | x : | semmle.label | x : | | active_support.rb:31:10:31:20 | call to dasherize | semmle.label | call to dasherize | +| active_support.rb:35:5:35:5 | x : | semmle.label | x : | | active_support.rb:35:9:35:18 | call to source : | semmle.label | call to source : | | active_support.rb:36:10:36:10 | x : | semmle.label | x : | | active_support.rb:36:10:36:24 | call to deconstantize | semmle.label | call to deconstantize | +| active_support.rb:40:5:40:5 | x : | semmle.label | x : | | active_support.rb:40:9:40:18 | call to source : | semmle.label | call to source : | | active_support.rb:41:10:41:10 | x : | semmle.label | x : | | active_support.rb:41:10:41:21 | call to demodulize | semmle.label | call to demodulize | +| active_support.rb:45:5:45:5 | x : | semmle.label | x : | | active_support.rb:45:9:45:18 | call to source : | semmle.label | call to source : | | active_support.rb:46:10:46:10 | x : | semmle.label | x : | | active_support.rb:46:10:46:19 | call to first | semmle.label | call to first | +| active_support.rb:50:5:50:5 | x : | semmle.label | x : | | active_support.rb:50:9:50:18 | call to source : | semmle.label | call to source : | | active_support.rb:51:10:51:10 | x : | semmle.label | x : | | active_support.rb:51:10:51:22 | call to foreign_key | semmle.label | call to foreign_key | +| active_support.rb:55:5:55:5 | x : | semmle.label | x : | | active_support.rb:55:9:55:18 | call to source : | semmle.label | call to source : | | active_support.rb:56:10:56:10 | x : | semmle.label | x : | | active_support.rb:56:10:56:18 | call to from | semmle.label | call to from | +| active_support.rb:60:5:60:5 | x : | semmle.label | x : | | active_support.rb:60:9:60:18 | call to source : | semmle.label | call to source : | | active_support.rb:61:10:61:10 | x : | semmle.label | x : | | active_support.rb:61:10:61:20 | call to html_safe | semmle.label | call to html_safe | +| active_support.rb:65:5:65:5 | x : | semmle.label | x : | | active_support.rb:65:9:65:18 | call to source : | semmle.label | call to source : | | active_support.rb:66:10:66:10 | x : | semmle.label | x : | | active_support.rb:66:10:66:19 | call to humanize | semmle.label | call to humanize | +| active_support.rb:70:5:70:5 | x : | semmle.label | x : | | active_support.rb:70:9:70:18 | call to source : | semmle.label | call to source : | | active_support.rb:71:10:71:10 | x : | semmle.label | x : | | active_support.rb:71:10:71:20 | call to indent | semmle.label | call to indent | +| active_support.rb:75:5:75:5 | x : | semmle.label | x : | | active_support.rb:75:9:75:18 | call to source : | semmle.label | call to source : | | active_support.rb:76:10:76:10 | x : | semmle.label | x : | | active_support.rb:76:10:76:21 | call to indent! | semmle.label | call to indent! | +| active_support.rb:80:5:80:5 | x : | semmle.label | x : | | active_support.rb:80:9:80:18 | call to source : | semmle.label | call to source : | | active_support.rb:81:10:81:10 | x : | semmle.label | x : | | active_support.rb:81:10:81:18 | call to inquiry | semmle.label | call to inquiry | +| active_support.rb:85:5:85:5 | x : | semmle.label | x : | | active_support.rb:85:9:85:18 | call to source : | semmle.label | call to source : | | active_support.rb:86:10:86:10 | x : | semmle.label | x : | | active_support.rb:86:10:86:18 | call to last | semmle.label | call to last | +| active_support.rb:90:5:90:5 | x : | semmle.label | x : | | active_support.rb:90:9:90:18 | call to source : | semmle.label | call to source : | | active_support.rb:91:10:91:10 | x : | semmle.label | x : | | active_support.rb:91:10:91:19 | call to mb_chars | semmle.label | call to mb_chars | +| active_support.rb:95:5:95:5 | x : | semmle.label | x : | | active_support.rb:95:9:95:18 | call to source : | semmle.label | call to source : | | active_support.rb:96:10:96:10 | x : | semmle.label | x : | | active_support.rb:96:10:96:23 | call to parameterize | semmle.label | call to parameterize | +| active_support.rb:100:5:100:5 | x : | semmle.label | x : | | active_support.rb:100:9:100:18 | call to source : | semmle.label | call to source : | | active_support.rb:101:10:101:10 | x : | semmle.label | x : | | active_support.rb:101:10:101:20 | call to pluralize | semmle.label | call to pluralize | +| active_support.rb:105:5:105:5 | x : | semmle.label | x : | | active_support.rb:105:9:105:18 | call to source : | semmle.label | call to source : | | active_support.rb:106:10:106:10 | x : | semmle.label | x : | | active_support.rb:106:10:106:24 | call to remove | semmle.label | call to remove | +| active_support.rb:110:5:110:5 | x : | semmle.label | x : | | active_support.rb:110:9:110:18 | call to source : | semmle.label | call to source : | | active_support.rb:111:10:111:10 | x : | semmle.label | x : | | active_support.rb:111:10:111:25 | call to remove! | semmle.label | call to remove! | +| active_support.rb:115:5:115:5 | x : | semmle.label | x : | | active_support.rb:115:9:115:18 | call to source : | semmle.label | call to source : | | active_support.rb:116:10:116:10 | x : | semmle.label | x : | | active_support.rb:116:10:116:22 | call to singularize | semmle.label | call to singularize | +| active_support.rb:120:5:120:5 | x : | semmle.label | x : | | active_support.rb:120:9:120:18 | call to source : | semmle.label | call to source : | | active_support.rb:121:10:121:10 | x : | semmle.label | x : | | active_support.rb:121:10:121:17 | call to squish | semmle.label | call to squish | +| active_support.rb:125:5:125:5 | x : | semmle.label | x : | | active_support.rb:125:9:125:18 | call to source : | semmle.label | call to source : | | active_support.rb:126:10:126:10 | x : | semmle.label | x : | | active_support.rb:126:10:126:18 | call to squish! | semmle.label | call to squish! | +| active_support.rb:130:5:130:5 | x : | semmle.label | x : | | active_support.rb:130:9:130:18 | call to source : | semmle.label | call to source : | | active_support.rb:131:10:131:10 | x : | semmle.label | x : | | active_support.rb:131:10:131:24 | call to strip_heredoc | semmle.label | call to strip_heredoc | +| active_support.rb:135:5:135:5 | x : | semmle.label | x : | | active_support.rb:135:9:135:18 | call to source : | semmle.label | call to source : | | active_support.rb:136:10:136:10 | x : | semmle.label | x : | | active_support.rb:136:10:136:19 | call to tableize | semmle.label | call to tableize | +| active_support.rb:140:5:140:5 | x : | semmle.label | x : | | active_support.rb:140:9:140:18 | call to source : | semmle.label | call to source : | | active_support.rb:141:10:141:10 | x : | semmle.label | x : | | active_support.rb:141:10:141:20 | call to titlecase | semmle.label | call to titlecase | +| active_support.rb:145:5:145:5 | x : | semmle.label | x : | | active_support.rb:145:9:145:18 | call to source : | semmle.label | call to source : | | active_support.rb:146:10:146:10 | x : | semmle.label | x : | | active_support.rb:146:10:146:19 | call to titleize | semmle.label | call to titleize | +| active_support.rb:150:5:150:5 | x : | semmle.label | x : | | active_support.rb:150:9:150:18 | call to source : | semmle.label | call to source : | | active_support.rb:151:10:151:10 | x : | semmle.label | x : | | active_support.rb:151:10:151:16 | call to to | semmle.label | call to to | +| active_support.rb:155:5:155:5 | x : | semmle.label | x : | | active_support.rb:155:9:155:18 | call to source : | semmle.label | call to source : | | active_support.rb:156:10:156:10 | x : | semmle.label | x : | | active_support.rb:156:10:156:22 | call to truncate | semmle.label | call to truncate | +| active_support.rb:160:5:160:5 | x : | semmle.label | x : | | active_support.rb:160:9:160:18 | call to source : | semmle.label | call to source : | | active_support.rb:161:10:161:10 | x : | semmle.label | x : | | active_support.rb:161:10:161:28 | call to truncate_bytes | semmle.label | call to truncate_bytes | +| active_support.rb:165:5:165:5 | x : | semmle.label | x : | | active_support.rb:165:9:165:18 | call to source : | semmle.label | call to source : | | active_support.rb:166:10:166:10 | x : | semmle.label | x : | | active_support.rb:166:10:166:28 | call to truncate_words | semmle.label | call to truncate_words | +| active_support.rb:170:5:170:5 | x : | semmle.label | x : | | active_support.rb:170:9:170:18 | call to source : | semmle.label | call to source : | | active_support.rb:171:10:171:10 | x : | semmle.label | x : | | active_support.rb:171:10:171:21 | call to underscore | semmle.label | call to underscore | +| active_support.rb:175:5:175:5 | x : | semmle.label | x : | | active_support.rb:175:9:175:18 | call to source : | semmle.label | call to source : | | active_support.rb:176:10:176:10 | x : | semmle.label | x : | | active_support.rb:176:10:176:23 | call to upcase_first | semmle.label | call to upcase_first | +| active_support.rb:180:5:180:5 | x [element 0] : | semmle.label | x [element 0] : | +| active_support.rb:180:5:180:5 | x [element 0] : | semmle.label | x [element 0] : | | active_support.rb:180:10:180:17 | call to source : | semmle.label | call to source : | | active_support.rb:180:10:180:17 | call to source : | semmle.label | call to source : | +| active_support.rb:181:5:181:5 | y [element] : | semmle.label | y [element] : | +| active_support.rb:181:5:181:5 | y [element] : | semmle.label | y [element] : | | active_support.rb:181:9:181:9 | x [element 0] : | semmle.label | x [element 0] : | | active_support.rb:181:9:181:9 | x [element 0] : | semmle.label | x [element 0] : | | active_support.rb:181:9:181:23 | call to compact_blank [element] : | semmle.label | call to compact_blank [element] : | @@ -548,8 +748,12 @@ nodes | active_support.rb:182:10:182:10 | y [element] : | semmle.label | y [element] : | | active_support.rb:182:10:182:13 | ...[...] | semmle.label | ...[...] | | active_support.rb:182:10:182:13 | ...[...] | semmle.label | ...[...] | +| active_support.rb:186:5:186:5 | x [element 0] : | semmle.label | x [element 0] : | +| active_support.rb:186:5:186:5 | x [element 0] : | semmle.label | x [element 0] : | | active_support.rb:186:10:186:18 | call to source : | semmle.label | call to source : | | active_support.rb:186:10:186:18 | call to source : | semmle.label | call to source : | +| active_support.rb:187:5:187:5 | y [element] : | semmle.label | y [element] : | +| active_support.rb:187:5:187:5 | y [element] : | semmle.label | y [element] : | | active_support.rb:187:9:187:9 | x [element 0] : | semmle.label | x [element 0] : | | active_support.rb:187:9:187:9 | x [element 0] : | semmle.label | x [element 0] : | | active_support.rb:187:9:187:21 | call to excluding [element] : | semmle.label | call to excluding [element] : | @@ -558,8 +762,12 @@ nodes | active_support.rb:188:10:188:10 | y [element] : | semmle.label | y [element] : | | active_support.rb:188:10:188:13 | ...[...] | semmle.label | ...[...] | | active_support.rb:188:10:188:13 | ...[...] | semmle.label | ...[...] | +| active_support.rb:192:5:192:5 | x [element 0] : | semmle.label | x [element 0] : | +| active_support.rb:192:5:192:5 | x [element 0] : | semmle.label | x [element 0] : | | active_support.rb:192:10:192:18 | call to source : | semmle.label | call to source : | | active_support.rb:192:10:192:18 | call to source : | semmle.label | call to source : | +| active_support.rb:193:5:193:5 | y [element] : | semmle.label | y [element] : | +| active_support.rb:193:5:193:5 | y [element] : | semmle.label | y [element] : | | active_support.rb:193:9:193:9 | x [element 0] : | semmle.label | x [element 0] : | | active_support.rb:193:9:193:9 | x [element 0] : | semmle.label | x [element 0] : | | active_support.rb:193:9:193:19 | call to without [element] : | semmle.label | call to without [element] : | @@ -568,8 +776,12 @@ nodes | active_support.rb:194:10:194:10 | y [element] : | semmle.label | y [element] : | | active_support.rb:194:10:194:13 | ...[...] | semmle.label | ...[...] | | active_support.rb:194:10:194:13 | ...[...] | semmle.label | ...[...] | +| active_support.rb:198:5:198:5 | x [element 0] : | semmle.label | x [element 0] : | +| active_support.rb:198:5:198:5 | x [element 0] : | semmle.label | x [element 0] : | | active_support.rb:198:10:198:18 | call to source : | semmle.label | call to source : | | active_support.rb:198:10:198:18 | call to source : | semmle.label | call to source : | +| active_support.rb:199:5:199:5 | y [element] : | semmle.label | y [element] : | +| active_support.rb:199:5:199:5 | y [element] : | semmle.label | y [element] : | | active_support.rb:199:9:199:9 | x [element 0] : | semmle.label | x [element 0] : | | active_support.rb:199:9:199:9 | x [element 0] : | semmle.label | x [element 0] : | | active_support.rb:199:9:199:37 | call to in_order_of [element] : | semmle.label | call to in_order_of [element] : | @@ -578,8 +790,14 @@ nodes | active_support.rb:200:10:200:10 | y [element] : | semmle.label | y [element] : | | active_support.rb:200:10:200:13 | ...[...] | semmle.label | ...[...] | | active_support.rb:200:10:200:13 | ...[...] | semmle.label | ...[...] | +| active_support.rb:204:5:204:5 | a [element 0] : | semmle.label | a [element 0] : | +| active_support.rb:204:5:204:5 | a [element 0] : | semmle.label | a [element 0] : | | active_support.rb:204:10:204:18 | call to source : | semmle.label | call to source : | | active_support.rb:204:10:204:18 | call to source : | semmle.label | call to source : | +| active_support.rb:205:5:205:5 | b [element 0] : | semmle.label | b [element 0] : | +| active_support.rb:205:5:205:5 | b [element 0] : | semmle.label | b [element 0] : | +| active_support.rb:205:5:205:5 | b [element] : | semmle.label | b [element] : | +| active_support.rb:205:5:205:5 | b [element] : | semmle.label | b [element] : | | active_support.rb:205:9:205:9 | a [element 0] : | semmle.label | a [element 0] : | | active_support.rb:205:9:205:9 | a [element 0] : | semmle.label | a [element 0] : | | active_support.rb:205:9:205:41 | call to including [element 0] : | semmle.label | call to including [element 0] : | @@ -612,99 +830,141 @@ nodes | active_support.rb:211:10:211:10 | b [element] : | semmle.label | b [element] : | | active_support.rb:211:10:211:13 | ...[...] | semmle.label | ...[...] | | active_support.rb:211:10:211:13 | ...[...] | semmle.label | ...[...] | +| active_support.rb:215:3:215:3 | x : | semmle.label | x : | | active_support.rb:215:7:215:16 | call to source : | semmle.label | call to source : | +| active_support.rb:216:3:216:3 | y : | semmle.label | y : | | active_support.rb:216:7:216:35 | call to new : | semmle.label | call to new : | | active_support.rb:216:34:216:34 | x : | semmle.label | x : | | active_support.rb:217:8:217:8 | y | semmle.label | y | +| active_support.rb:222:3:222:3 | b : | semmle.label | b : | | active_support.rb:222:7:222:16 | call to source : | semmle.label | call to source : | +| active_support.rb:223:3:223:3 | y : | semmle.label | y : | | active_support.rb:223:7:223:22 | call to safe_concat : | semmle.label | call to safe_concat : | | active_support.rb:223:21:223:21 | b : | semmle.label | b : | | active_support.rb:224:8:224:8 | y | semmle.label | y | +| active_support.rb:229:3:229:3 | b : | semmle.label | b : | | active_support.rb:229:7:229:16 | call to source : | semmle.label | call to source : | | active_support.rb:230:3:230:3 | [post] x : | semmle.label | [post] x : | | active_support.rb:230:17:230:17 | b : | semmle.label | b : | | active_support.rb:231:8:231:8 | x | semmle.label | x | +| active_support.rb:235:3:235:3 | a : | semmle.label | a : | | active_support.rb:235:7:235:16 | call to source : | semmle.label | call to source : | +| active_support.rb:237:3:237:3 | x : | semmle.label | x : | | active_support.rb:237:7:237:35 | call to new : | semmle.label | call to new : | | active_support.rb:237:34:237:34 | a : | semmle.label | a : | +| active_support.rb:238:3:238:3 | y : | semmle.label | y : | | active_support.rb:238:7:238:7 | x : | semmle.label | x : | | active_support.rb:238:7:238:17 | call to concat : | semmle.label | call to concat : | | active_support.rb:239:8:239:8 | y | semmle.label | y | +| active_support.rb:243:3:243:3 | a : | semmle.label | a : | | active_support.rb:243:7:243:16 | call to source : | semmle.label | call to source : | +| active_support.rb:245:3:245:3 | x : | semmle.label | x : | | active_support.rb:245:7:245:35 | call to new : | semmle.label | call to new : | | active_support.rb:245:34:245:34 | a : | semmle.label | a : | +| active_support.rb:246:3:246:3 | y : | semmle.label | y : | | active_support.rb:246:7:246:7 | x : | semmle.label | x : | | active_support.rb:246:7:246:20 | call to insert : | semmle.label | call to insert : | | active_support.rb:247:8:247:8 | y | semmle.label | y | +| active_support.rb:251:3:251:3 | a : | semmle.label | a : | | active_support.rb:251:7:251:16 | call to source : | semmle.label | call to source : | +| active_support.rb:253:3:253:3 | x : | semmle.label | x : | | active_support.rb:253:7:253:35 | call to new : | semmle.label | call to new : | | active_support.rb:253:34:253:34 | a : | semmle.label | a : | +| active_support.rb:254:3:254:3 | y : | semmle.label | y : | | active_support.rb:254:7:254:7 | x : | semmle.label | x : | | active_support.rb:254:7:254:18 | call to prepend : | semmle.label | call to prepend : | | active_support.rb:255:8:255:8 | y | semmle.label | y | +| active_support.rb:259:3:259:3 | a : | semmle.label | a : | | active_support.rb:259:7:259:16 | call to source : | semmle.label | call to source : | +| active_support.rb:260:3:260:3 | x : | semmle.label | x : | | active_support.rb:260:7:260:35 | call to new : | semmle.label | call to new : | | active_support.rb:260:34:260:34 | a : | semmle.label | a : | +| active_support.rb:261:3:261:3 | y : | semmle.label | y : | | active_support.rb:261:7:261:7 | x : | semmle.label | x : | | active_support.rb:261:7:261:12 | call to to_s : | semmle.label | call to to_s : | | active_support.rb:262:8:262:8 | y | semmle.label | y | +| active_support.rb:266:3:266:3 | a : | semmle.label | a : | | active_support.rb:266:7:266:16 | call to source : | semmle.label | call to source : | +| active_support.rb:267:3:267:3 | x : | semmle.label | x : | | active_support.rb:267:7:267:35 | call to new : | semmle.label | call to new : | | active_support.rb:267:34:267:34 | a : | semmle.label | a : | +| active_support.rb:268:3:268:3 | y : | semmle.label | y : | | active_support.rb:268:7:268:7 | x : | semmle.label | x : | | active_support.rb:268:7:268:16 | call to to_param : | semmle.label | call to to_param : | | active_support.rb:269:8:269:8 | y | semmle.label | y | +| active_support.rb:273:3:273:3 | a : | semmle.label | a : | | active_support.rb:273:7:273:16 | call to source : | semmle.label | call to source : | +| active_support.rb:274:3:274:3 | x : | semmle.label | x : | | active_support.rb:274:7:274:21 | call to new : | semmle.label | call to new : | | active_support.rb:274:20:274:20 | a : | semmle.label | a : | +| active_support.rb:275:3:275:3 | y : | semmle.label | y : | | active_support.rb:275:7:275:7 | x : | semmle.label | x : | | active_support.rb:275:7:275:17 | call to existence : | semmle.label | call to existence : | | active_support.rb:276:8:276:8 | y | semmle.label | y | +| active_support.rb:277:3:277:3 | z : | semmle.label | z : | | active_support.rb:277:7:277:7 | y : | semmle.label | y : | | active_support.rb:277:7:277:17 | call to existence : | semmle.label | call to existence : | | active_support.rb:278:8:278:8 | z | semmle.label | z | +| active_support.rb:282:3:282:3 | x : | semmle.label | x : | +| active_support.rb:282:3:282:3 | x : | semmle.label | x : | | active_support.rb:282:7:282:16 | call to source : | semmle.label | call to source : | | active_support.rb:282:7:282:16 | call to source : | semmle.label | call to source : | | active_support.rb:283:8:283:8 | x : | semmle.label | x : | | active_support.rb:283:8:283:8 | x : | semmle.label | x : | | active_support.rb:283:8:283:17 | call to presence | semmle.label | call to presence | | active_support.rb:283:8:283:17 | call to presence | semmle.label | call to presence | +| active_support.rb:285:3:285:3 | y : | semmle.label | y : | +| active_support.rb:285:3:285:3 | y : | semmle.label | y : | | active_support.rb:285:7:285:16 | call to source : | semmle.label | call to source : | | active_support.rb:285:7:285:16 | call to source : | semmle.label | call to source : | | active_support.rb:286:8:286:8 | y : | semmle.label | y : | | active_support.rb:286:8:286:8 | y : | semmle.label | y : | | active_support.rb:286:8:286:17 | call to presence | semmle.label | call to presence | | active_support.rb:286:8:286:17 | call to presence | semmle.label | call to presence | +| active_support.rb:290:3:290:3 | x : | semmle.label | x : | +| active_support.rb:290:3:290:3 | x : | semmle.label | x : | | active_support.rb:290:7:290:16 | call to source : | semmle.label | call to source : | | active_support.rb:290:7:290:16 | call to source : | semmle.label | call to source : | | active_support.rb:291:8:291:8 | x : | semmle.label | x : | | active_support.rb:291:8:291:8 | x : | semmle.label | x : | | active_support.rb:291:8:291:17 | call to deep_dup | semmle.label | call to deep_dup | | active_support.rb:291:8:291:17 | call to deep_dup | semmle.label | call to deep_dup | +| active_support.rb:303:3:303:3 | a : | semmle.label | a : | | active_support.rb:303:7:303:16 | call to source : | semmle.label | call to source : | +| active_support.rb:304:3:304:3 | b : | semmle.label | b : | | active_support.rb:304:7:304:19 | call to json_escape : | semmle.label | call to json_escape : | | active_support.rb:304:19:304:19 | a : | semmle.label | a : | | active_support.rb:305:8:305:8 | b | semmle.label | b | +| active_support.rb:309:5:309:5 | x : | semmle.label | x : | | active_support.rb:309:9:309:18 | call to source : | semmle.label | call to source : | | active_support.rb:310:10:310:38 | call to encode | semmle.label | call to encode | | active_support.rb:310:37:310:37 | x : | semmle.label | x : | +| active_support.rb:314:5:314:5 | x : | semmle.label | x : | | active_support.rb:314:9:314:18 | call to source : | semmle.label | call to source : | | active_support.rb:315:10:315:38 | call to decode | semmle.label | call to decode | | active_support.rb:315:37:315:37 | x : | semmle.label | x : | +| active_support.rb:319:5:319:5 | x : | semmle.label | x : | | active_support.rb:319:9:319:18 | call to source : | semmle.label | call to source : | | active_support.rb:320:10:320:36 | call to dump | semmle.label | call to dump | | active_support.rb:320:35:320:35 | x : | semmle.label | x : | +| active_support.rb:324:5:324:5 | x : | semmle.label | x : | | active_support.rb:324:9:324:18 | call to source : | semmle.label | call to source : | | active_support.rb:325:10:325:36 | call to load | semmle.label | call to load | | active_support.rb:325:35:325:35 | x : | semmle.label | x : | +| active_support.rb:329:5:329:5 | x : | semmle.label | x : | | active_support.rb:329:9:329:18 | call to source : | semmle.label | call to source : | +| active_support.rb:330:5:330:5 | y [element 0] : | semmle.label | y [element 0] : | | active_support.rb:330:10:330:10 | x : | semmle.label | x : | | active_support.rb:331:10:331:10 | x : | semmle.label | x : | | active_support.rb:331:10:331:18 | call to to_json | semmle.label | call to to_json | | active_support.rb:332:10:332:10 | y [element 0] : | semmle.label | y [element 0] : | | active_support.rb:332:10:332:18 | call to to_json | semmle.label | call to to_json | +| hash_extensions.rb:2:5:2:5 | h [element :a] : | semmle.label | h [element :a] : | +| hash_extensions.rb:2:5:2:5 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:2:14:2:24 | call to source : | semmle.label | call to source : | | hash_extensions.rb:2:14:2:24 | call to source : | semmle.label | call to source : | +| hash_extensions.rb:3:5:3:5 | x [element] : | semmle.label | x [element] : | +| hash_extensions.rb:3:5:3:5 | x [element] : | semmle.label | x [element] : | | hash_extensions.rb:3:9:3:9 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:3:9:3:9 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:3:9:3:24 | call to stringify_keys [element] : | semmle.label | call to stringify_keys [element] : | @@ -713,8 +973,12 @@ nodes | hash_extensions.rb:4:10:4:10 | x [element] : | semmle.label | x [element] : | | hash_extensions.rb:4:10:4:14 | ...[...] | semmle.label | ...[...] | | hash_extensions.rb:4:10:4:14 | ...[...] | semmle.label | ...[...] | +| hash_extensions.rb:10:5:10:5 | h [element :a] : | semmle.label | h [element :a] : | +| hash_extensions.rb:10:5:10:5 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:10:14:10:24 | call to source : | semmle.label | call to source : | | hash_extensions.rb:10:14:10:24 | call to source : | semmle.label | call to source : | +| hash_extensions.rb:11:5:11:5 | x [element] : | semmle.label | x [element] : | +| hash_extensions.rb:11:5:11:5 | x [element] : | semmle.label | x [element] : | | hash_extensions.rb:11:9:11:9 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:11:9:11:9 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:11:9:11:20 | call to to_options [element] : | semmle.label | call to to_options [element] : | @@ -723,8 +987,12 @@ nodes | hash_extensions.rb:12:10:12:10 | x [element] : | semmle.label | x [element] : | | hash_extensions.rb:12:10:12:14 | ...[...] | semmle.label | ...[...] | | hash_extensions.rb:12:10:12:14 | ...[...] | semmle.label | ...[...] | +| hash_extensions.rb:18:5:18:5 | h [element :a] : | semmle.label | h [element :a] : | +| hash_extensions.rb:18:5:18:5 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:18:14:18:24 | call to source : | semmle.label | call to source : | | hash_extensions.rb:18:14:18:24 | call to source : | semmle.label | call to source : | +| hash_extensions.rb:19:5:19:5 | x [element] : | semmle.label | x [element] : | +| hash_extensions.rb:19:5:19:5 | x [element] : | semmle.label | x [element] : | | hash_extensions.rb:19:9:19:9 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:19:9:19:9 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:19:9:19:24 | call to symbolize_keys [element] : | semmle.label | call to symbolize_keys [element] : | @@ -733,8 +1001,12 @@ nodes | hash_extensions.rb:20:10:20:10 | x [element] : | semmle.label | x [element] : | | hash_extensions.rb:20:10:20:14 | ...[...] | semmle.label | ...[...] | | hash_extensions.rb:20:10:20:14 | ...[...] | semmle.label | ...[...] | +| hash_extensions.rb:26:5:26:5 | h [element :a] : | semmle.label | h [element :a] : | +| hash_extensions.rb:26:5:26:5 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:26:14:26:24 | call to source : | semmle.label | call to source : | | hash_extensions.rb:26:14:26:24 | call to source : | semmle.label | call to source : | +| hash_extensions.rb:27:5:27:5 | x [element] : | semmle.label | x [element] : | +| hash_extensions.rb:27:5:27:5 | x [element] : | semmle.label | x [element] : | | hash_extensions.rb:27:9:27:9 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:27:9:27:9 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:27:9:27:29 | call to deep_stringify_keys [element] : | semmle.label | call to deep_stringify_keys [element] : | @@ -743,8 +1015,12 @@ nodes | hash_extensions.rb:28:10:28:10 | x [element] : | semmle.label | x [element] : | | hash_extensions.rb:28:10:28:14 | ...[...] | semmle.label | ...[...] | | hash_extensions.rb:28:10:28:14 | ...[...] | semmle.label | ...[...] | +| hash_extensions.rb:34:5:34:5 | h [element :a] : | semmle.label | h [element :a] : | +| hash_extensions.rb:34:5:34:5 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:34:14:34:24 | call to source : | semmle.label | call to source : | | hash_extensions.rb:34:14:34:24 | call to source : | semmle.label | call to source : | +| hash_extensions.rb:35:5:35:5 | x [element] : | semmle.label | x [element] : | +| hash_extensions.rb:35:5:35:5 | x [element] : | semmle.label | x [element] : | | hash_extensions.rb:35:9:35:9 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:35:9:35:9 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:35:9:35:29 | call to deep_symbolize_keys [element] : | semmle.label | call to deep_symbolize_keys [element] : | @@ -753,8 +1029,12 @@ nodes | hash_extensions.rb:36:10:36:10 | x [element] : | semmle.label | x [element] : | | hash_extensions.rb:36:10:36:14 | ...[...] | semmle.label | ...[...] | | hash_extensions.rb:36:10:36:14 | ...[...] | semmle.label | ...[...] | +| hash_extensions.rb:42:5:42:5 | h [element :a] : | semmle.label | h [element :a] : | +| hash_extensions.rb:42:5:42:5 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:42:14:42:24 | call to source : | semmle.label | call to source : | | hash_extensions.rb:42:14:42:24 | call to source : | semmle.label | call to source : | +| hash_extensions.rb:43:5:43:5 | x [element] : | semmle.label | x [element] : | +| hash_extensions.rb:43:5:43:5 | x [element] : | semmle.label | x [element] : | | hash_extensions.rb:43:9:43:9 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:43:9:43:9 | h [element :a] : | semmle.label | h [element :a] : | | hash_extensions.rb:43:9:43:33 | call to with_indifferent_access [element] : | semmle.label | call to with_indifferent_access [element] : | @@ -763,12 +1043,22 @@ nodes | hash_extensions.rb:44:10:44:10 | x [element] : | semmle.label | x [element] : | | hash_extensions.rb:44:10:44:14 | ...[...] | semmle.label | ...[...] | | hash_extensions.rb:44:10:44:14 | ...[...] | semmle.label | ...[...] | +| hash_extensions.rb:50:5:50:5 | h [element :a] : | semmle.label | h [element :a] : | +| hash_extensions.rb:50:5:50:5 | h [element :a] : | semmle.label | h [element :a] : | +| hash_extensions.rb:50:5:50:5 | h [element :b] : | semmle.label | h [element :b] : | +| hash_extensions.rb:50:5:50:5 | h [element :b] : | semmle.label | h [element :b] : | +| hash_extensions.rb:50:5:50:5 | h [element :d] : | semmle.label | h [element :d] : | +| hash_extensions.rb:50:5:50:5 | h [element :d] : | semmle.label | h [element :d] : | | hash_extensions.rb:50:14:50:23 | call to taint : | semmle.label | call to taint : | | hash_extensions.rb:50:14:50:23 | call to taint : | semmle.label | call to taint : | | hash_extensions.rb:50:29:50:38 | call to taint : | semmle.label | call to taint : | | hash_extensions.rb:50:29:50:38 | call to taint : | semmle.label | call to taint : | | hash_extensions.rb:50:52:50:61 | call to taint : | semmle.label | call to taint : | | hash_extensions.rb:50:52:50:61 | call to taint : | semmle.label | call to taint : | +| hash_extensions.rb:51:5:51:5 | x [element :a] : | semmle.label | x [element :a] : | +| hash_extensions.rb:51:5:51:5 | x [element :a] : | semmle.label | x [element :a] : | +| hash_extensions.rb:51:5:51:5 | x [element :b] : | semmle.label | x [element :b] : | +| hash_extensions.rb:51:5:51:5 | x [element :b] : | semmle.label | x [element :b] : | | hash_extensions.rb:51:9:51:9 | [post] h [element :d] : | semmle.label | [post] h [element :d] : | | hash_extensions.rb:51:9:51:9 | [post] h [element :d] : | semmle.label | [post] h [element :d] : | | hash_extensions.rb:51:9:51:9 | h [element :a] : | semmle.label | h [element :a] : | @@ -793,12 +1083,20 @@ nodes | hash_extensions.rb:59:10:59:10 | x [element :b] : | semmle.label | x [element :b] : | | hash_extensions.rb:59:10:59:14 | ...[...] | semmle.label | ...[...] | | hash_extensions.rb:59:10:59:14 | ...[...] | semmle.label | ...[...] | +| hash_extensions.rb:67:5:67:10 | values [element 0] : | semmle.label | values [element 0] : | +| hash_extensions.rb:67:5:67:10 | values [element 0] : | semmle.label | values [element 0] : | +| hash_extensions.rb:67:5:67:10 | values [element 1] : | semmle.label | values [element 1] : | +| hash_extensions.rb:67:5:67:10 | values [element 1] : | semmle.label | values [element 1] : | +| hash_extensions.rb:67:5:67:10 | values [element 2] : | semmle.label | values [element 2] : | +| hash_extensions.rb:67:5:67:10 | values [element 2] : | semmle.label | values [element 2] : | | hash_extensions.rb:67:15:67:25 | call to source : | semmle.label | call to source : | | hash_extensions.rb:67:15:67:25 | call to source : | semmle.label | call to source : | | hash_extensions.rb:67:28:67:38 | call to source : | semmle.label | call to source : | | hash_extensions.rb:67:28:67:38 | call to source : | semmle.label | call to source : | | hash_extensions.rb:67:41:67:51 | call to source : | semmle.label | call to source : | | hash_extensions.rb:67:41:67:51 | call to source : | semmle.label | call to source : | +| hash_extensions.rb:68:5:68:5 | h [element] : | semmle.label | h [element] : | +| hash_extensions.rb:68:5:68:5 | h [element] : | semmle.label | h [element] : | | hash_extensions.rb:68:9:68:14 | values [element 0] : | semmle.label | values [element 0] : | | hash_extensions.rb:68:9:68:14 | values [element 0] : | semmle.label | values [element 0] : | | hash_extensions.rb:68:9:68:14 | values [element 1] : | semmle.label | values [element 1] : | @@ -819,12 +1117,20 @@ nodes | hash_extensions.rb:74:10:74:10 | h [element] : | semmle.label | h [element] : | | hash_extensions.rb:74:10:74:16 | ...[...] | semmle.label | ...[...] | | hash_extensions.rb:74:10:74:16 | ...[...] | semmle.label | ...[...] | +| hash_extensions.rb:80:5:80:10 | values [element 0] : | semmle.label | values [element 0] : | +| hash_extensions.rb:80:5:80:10 | values [element 0] : | semmle.label | values [element 0] : | +| hash_extensions.rb:80:5:80:10 | values [element 1] : | semmle.label | values [element 1] : | +| hash_extensions.rb:80:5:80:10 | values [element 1] : | semmle.label | values [element 1] : | +| hash_extensions.rb:80:5:80:10 | values [element 2] : | semmle.label | values [element 2] : | +| hash_extensions.rb:80:5:80:10 | values [element 2] : | semmle.label | values [element 2] : | | hash_extensions.rb:80:15:80:25 | call to source : | semmle.label | call to source : | | hash_extensions.rb:80:15:80:25 | call to source : | semmle.label | call to source : | | hash_extensions.rb:80:28:80:38 | call to source : | semmle.label | call to source : | | hash_extensions.rb:80:28:80:38 | call to source : | semmle.label | call to source : | | hash_extensions.rb:80:41:80:51 | call to source : | semmle.label | call to source : | | hash_extensions.rb:80:41:80:51 | call to source : | semmle.label | call to source : | +| hash_extensions.rb:81:5:81:5 | h [element] : | semmle.label | h [element] : | +| hash_extensions.rb:81:5:81:5 | h [element] : | semmle.label | h [element] : | | hash_extensions.rb:81:9:81:14 | values [element 0] : | semmle.label | values [element 0] : | | hash_extensions.rb:81:9:81:14 | values [element 0] : | semmle.label | values [element 0] : | | hash_extensions.rb:81:9:81:14 | values [element 1] : | semmle.label | values [element 1] : | @@ -847,6 +1153,8 @@ nodes | hash_extensions.rb:87:10:87:10 | h [element] : | semmle.label | h [element] : | | hash_extensions.rb:87:10:87:16 | ...[...] | semmle.label | ...[...] | | hash_extensions.rb:87:10:87:16 | ...[...] | semmle.label | ...[...] | +| hash_extensions.rb:89:5:89:5 | j [element] : | semmle.label | j [element] : | +| hash_extensions.rb:89:5:89:5 | j [element] : | semmle.label | j [element] : | | hash_extensions.rb:89:9:89:38 | call to index_with [element] : | semmle.label | call to index_with [element] : | | hash_extensions.rb:89:9:89:38 | call to index_with [element] : | semmle.label | call to index_with [element] : | | hash_extensions.rb:89:27:89:37 | call to source : | semmle.label | call to source : | @@ -859,6 +1167,10 @@ nodes | hash_extensions.rb:92:10:92:10 | j [element] : | semmle.label | j [element] : | | hash_extensions.rb:92:10:92:16 | ...[...] | semmle.label | ...[...] | | hash_extensions.rb:92:10:92:16 | ...[...] | semmle.label | ...[...] | +| hash_extensions.rb:98:5:98:10 | values [element 0, element :id] : | semmle.label | values [element 0, element :id] : | +| hash_extensions.rb:98:5:98:10 | values [element 0, element :id] : | semmle.label | values [element 0, element :id] : | +| hash_extensions.rb:98:5:98:10 | values [element 0, element :name] : | semmle.label | values [element 0, element :name] : | +| hash_extensions.rb:98:5:98:10 | values [element 0, element :name] : | semmle.label | values [element 0, element :name] : | | hash_extensions.rb:98:21:98:31 | call to source : | semmle.label | call to source : | | hash_extensions.rb:98:21:98:31 | call to source : | semmle.label | call to source : | | hash_extensions.rb:98:40:98:54 | call to source : | semmle.label | call to source : | @@ -895,6 +1207,14 @@ nodes | hash_extensions.rb:104:10:104:32 | call to pick [element 1] : | semmle.label | call to pick [element 1] : | | hash_extensions.rb:104:10:104:35 | ...[...] | semmle.label | ...[...] | | hash_extensions.rb:104:10:104:35 | ...[...] | semmle.label | ...[...] | +| hash_extensions.rb:110:5:110:10 | values [element 0, element :id] : | semmle.label | values [element 0, element :id] : | +| hash_extensions.rb:110:5:110:10 | values [element 0, element :id] : | semmle.label | values [element 0, element :id] : | +| hash_extensions.rb:110:5:110:10 | values [element 0, element :name] : | semmle.label | values [element 0, element :name] : | +| hash_extensions.rb:110:5:110:10 | values [element 0, element :name] : | semmle.label | values [element 0, element :name] : | +| hash_extensions.rb:110:5:110:10 | values [element 1, element :id] : | semmle.label | values [element 1, element :id] : | +| hash_extensions.rb:110:5:110:10 | values [element 1, element :id] : | semmle.label | values [element 1, element :id] : | +| hash_extensions.rb:110:5:110:10 | values [element 1, element :name] : | semmle.label | values [element 1, element :name] : | +| hash_extensions.rb:110:5:110:10 | values [element 1, element :name] : | semmle.label | values [element 1, element :name] : | | hash_extensions.rb:110:21:110:31 | call to source : | semmle.label | call to source : | | hash_extensions.rb:110:21:110:31 | call to source : | semmle.label | call to source : | | hash_extensions.rb:110:40:110:54 | call to source : | semmle.label | call to source : | @@ -951,8 +1271,12 @@ nodes | hash_extensions.rb:115:10:115:36 | ...[...] [element 1] : | semmle.label | ...[...] [element 1] : | | hash_extensions.rb:115:10:115:39 | ...[...] | semmle.label | ...[...] | | hash_extensions.rb:115:10:115:39 | ...[...] | semmle.label | ...[...] | +| hash_extensions.rb:122:5:122:10 | single [element 0] : | semmle.label | single [element 0] : | +| hash_extensions.rb:122:5:122:10 | single [element 0] : | semmle.label | single [element 0] : | | hash_extensions.rb:122:15:122:25 | call to source : | semmle.label | call to source : | | hash_extensions.rb:122:15:122:25 | call to source : | semmle.label | call to source : | +| hash_extensions.rb:123:5:123:9 | multi [element 0] : | semmle.label | multi [element 0] : | +| hash_extensions.rb:123:5:123:9 | multi [element 0] : | semmle.label | multi [element 0] : | | hash_extensions.rb:123:14:123:24 | call to source : | semmle.label | call to source : | | hash_extensions.rb:123:14:123:24 | call to source : | semmle.label | call to source : | | hash_extensions.rb:125:10:125:15 | single [element 0] : | semmle.label | single [element 0] : | diff --git a/ruby/ql/test/library-tests/frameworks/files/Files.expected b/ruby/ql/test/library-tests/frameworks/files/Files.expected index bebb93ef371..b75acc54c5b 100644 --- a/ruby/ql/test/library-tests/frameworks/files/Files.expected +++ b/ruby/ql/test/library-tests/frameworks/files/Files.expected @@ -1,8 +1,8 @@ fileInstances -| Files.rb:2:1:2:36 | ... = ... | +| Files.rb:2:1:2:8 | foo_file | | Files.rb:2:1:2:36 | ... = ... | | Files.rb:2:12:2:36 | call to new | -| Files.rb:3:1:3:21 | ... = ... | +| Files.rb:3:1:3:10 | foo_file_2 | | Files.rb:3:1:3:21 | ... = ... | | Files.rb:3:14:3:21 | foo_file | | Files.rb:4:1:4:8 | foo_file | @@ -18,17 +18,17 @@ fileInstances | Files.rb:40:1:40:8 | foo_file | | Files.rb:41:1:41:26 | call to open | ioInstances -| Files.rb:2:1:2:36 | ... = ... | +| Files.rb:2:1:2:8 | foo_file | | Files.rb:2:1:2:36 | ... = ... | | Files.rb:2:12:2:36 | call to new | -| Files.rb:3:1:3:21 | ... = ... | +| Files.rb:3:1:3:10 | foo_file_2 | | Files.rb:3:1:3:21 | ... = ... | | Files.rb:3:14:3:21 | foo_file | | Files.rb:4:1:4:8 | foo_file | | Files.rb:7:13:7:22 | foo_file_2 | | Files.rb:10:6:10:13 | foo_file | | Files.rb:11:6:11:13 | foo_file | -| Files.rb:17:1:17:50 | ... = ... | +| Files.rb:17:1:17:4 | rand | | Files.rb:17:1:17:50 | ... = ... | | Files.rb:17:8:17:50 | call to new | | Files.rb:18:1:18:13 | ... = ... | @@ -44,7 +44,7 @@ ioInstances | Files.rb:37:14:37:33 | call to open | | Files.rb:40:1:40:8 | foo_file | | Files.rb:41:1:41:26 | call to open | -| Files.rb:44:1:44:45 | ... = ... | +| Files.rb:44:1:44:7 | io_file | | Files.rb:44:1:44:45 | ... = ... | | Files.rb:44:11:44:45 | call to open | | Files.rb:48:1:48:7 | io_file | diff --git a/ruby/ql/test/library-tests/frameworks/pathname/Pathname.expected b/ruby/ql/test/library-tests/frameworks/pathname/Pathname.expected index c69247ae5f8..d082076be69 100644 --- a/ruby/ql/test/library-tests/frameworks/pathname/Pathname.expected +++ b/ruby/ql/test/library-tests/frameworks/pathname/Pathname.expected @@ -1,21 +1,21 @@ pathnameInstances -| Pathname.rb:2:1:2:33 | ... = ... | +| Pathname.rb:2:1:2:8 | foo_path | | Pathname.rb:2:1:2:33 | ... = ... | | Pathname.rb:2:12:2:33 | call to new | | Pathname.rb:3:1:3:20 | ... = ... | | Pathname.rb:3:13:3:20 | foo_path | | Pathname.rb:4:1:4:8 | foo_path | -| Pathname.rb:6:1:6:29 | ... = ... | +| Pathname.rb:6:1:6:8 | bar_path | | Pathname.rb:6:1:6:29 | ... = ... | | Pathname.rb:6:12:6:29 | call to new | -| Pathname.rb:9:1:9:21 | ... = ... | +| Pathname.rb:9:1:9:4 | pwd1 | | Pathname.rb:9:1:9:21 | ... = ... | | Pathname.rb:9:8:9:21 | call to getwd | | Pathname.rb:10:1:10:21 | ... = ... | | Pathname.rb:10:7:10:10 | pwd1 | | Pathname.rb:10:7:10:21 | ... + ... | | Pathname.rb:10:14:10:21 | foo_path | -| Pathname.rb:11:1:11:21 | ... = ... | +| Pathname.rb:11:1:11:3 | p01 | | Pathname.rb:11:1:11:21 | ... = ... | | Pathname.rb:11:7:11:10 | pwd1 | | Pathname.rb:11:7:11:21 | ... / ... | @@ -38,7 +38,7 @@ pathnameInstances | Pathname.rb:17:1:17:59 | ... = ... | | Pathname.rb:17:7:17:33 | call to new | | Pathname.rb:17:7:17:59 | call to relative_path_from | -| Pathname.rb:18:1:18:33 | ... = ... | +| Pathname.rb:18:1:18:3 | p08 | | Pathname.rb:18:1:18:33 | ... = ... | | Pathname.rb:18:7:18:10 | pwd1 | | Pathname.rb:18:7:18:33 | call to sub | @@ -75,23 +75,23 @@ fileSystemAccesses | Pathname.rb:35:1:35:23 | call to write | Pathname.rb:35:1:35:8 | foo_path | | Pathname.rb:39:12:39:34 | call to open | Pathname.rb:39:12:39:19 | foo_path | fileNameSources -| Pathname.rb:2:1:2:33 | ... = ... | +| Pathname.rb:2:1:2:8 | foo_path | | Pathname.rb:2:1:2:33 | ... = ... | | Pathname.rb:2:12:2:33 | call to new | | Pathname.rb:3:1:3:20 | ... = ... | | Pathname.rb:3:13:3:20 | foo_path | | Pathname.rb:4:1:4:8 | foo_path | -| Pathname.rb:6:1:6:29 | ... = ... | +| Pathname.rb:6:1:6:8 | bar_path | | Pathname.rb:6:1:6:29 | ... = ... | | Pathname.rb:6:12:6:29 | call to new | -| Pathname.rb:9:1:9:21 | ... = ... | +| Pathname.rb:9:1:9:4 | pwd1 | | Pathname.rb:9:1:9:21 | ... = ... | | Pathname.rb:9:8:9:21 | call to getwd | | Pathname.rb:10:1:10:21 | ... = ... | | Pathname.rb:10:7:10:10 | pwd1 | | Pathname.rb:10:7:10:21 | ... + ... | | Pathname.rb:10:14:10:21 | foo_path | -| Pathname.rb:11:1:11:21 | ... = ... | +| Pathname.rb:11:1:11:3 | p01 | | Pathname.rb:11:1:11:21 | ... = ... | | Pathname.rb:11:7:11:10 | pwd1 | | Pathname.rb:11:7:11:21 | ... / ... | @@ -114,7 +114,7 @@ fileNameSources | Pathname.rb:17:1:17:59 | ... = ... | | Pathname.rb:17:7:17:33 | call to new | | Pathname.rb:17:7:17:59 | call to relative_path_from | -| Pathname.rb:18:1:18:33 | ... = ... | +| Pathname.rb:18:1:18:3 | p08 | | Pathname.rb:18:1:18:33 | ... = ... | | Pathname.rb:18:7:18:10 | pwd1 | | Pathname.rb:18:7:18:33 | call to sub | diff --git a/ruby/ql/test/library-tests/modules/ancestors.expected b/ruby/ql/test/library-tests/modules/ancestors.expected index 9e2c70f6f1c..2ebc068459f 100644 --- a/ruby/ql/test/library-tests/modules/ancestors.expected +++ b/ruby/ql/test/library-tests/modules/ancestors.expected @@ -36,6 +36,12 @@ #-----| TrueClass #-----| super -> Object +#-----| UnresolvedNamespace::X1 + +#-----| UnresolvedNamespace::X1::X2 + +#-----| UnresolvedNamespace::X1::X2::X3 + calls.rb: # 21| M @@ -272,3 +278,12 @@ unresolved_subclass.rb: # 11| UnresolvedNamespace::A #-----| super -> Object + +# 14| UnresolvedNamespace::X1::X2::X3::Subclass1 +#-----| super -> ResolvableBaseClass + +# 17| UnresolvedNamespace::X1::X2::X3::Subclass2 +#-----| super -> UnresolvedNamespace::X1::X2::X3::Subclass1 + +# 21| UnresolvedNamespace::X1::X2::X3::A +#-----| super -> Object diff --git a/ruby/ql/test/library-tests/modules/methods.expected b/ruby/ql/test/library-tests/modules/methods.expected index ae688090be5..cb936f30778 100644 --- a/ruby/ql/test/library-tests/modules/methods.expected +++ b/ruby/ql/test/library-tests/modules/methods.expected @@ -660,6 +660,15 @@ lookupMethod | unresolved_subclass.rb:11:1:12:3 | UnresolvedNamespace::A | new | calls.rb:117:5:117:16 | new | | unresolved_subclass.rb:11:1:12:3 | UnresolvedNamespace::A | puts | calls.rb:102:5:102:30 | puts | | unresolved_subclass.rb:11:1:12:3 | UnresolvedNamespace::A | to_s | calls.rb:172:5:173:7 | to_s | +| unresolved_subclass.rb:14:1:15:3 | UnresolvedNamespace::X1::X2::X3::Subclass1 | new | calls.rb:117:5:117:16 | new | +| unresolved_subclass.rb:14:1:15:3 | UnresolvedNamespace::X1::X2::X3::Subclass1 | puts | calls.rb:102:5:102:30 | puts | +| unresolved_subclass.rb:14:1:15:3 | UnresolvedNamespace::X1::X2::X3::Subclass1 | to_s | calls.rb:172:5:173:7 | to_s | +| unresolved_subclass.rb:17:1:18:3 | UnresolvedNamespace::X1::X2::X3::Subclass2 | new | calls.rb:117:5:117:16 | new | +| unresolved_subclass.rb:17:1:18:3 | UnresolvedNamespace::X1::X2::X3::Subclass2 | puts | calls.rb:102:5:102:30 | puts | +| unresolved_subclass.rb:17:1:18:3 | UnresolvedNamespace::X1::X2::X3::Subclass2 | to_s | calls.rb:172:5:173:7 | to_s | +| unresolved_subclass.rb:21:1:22:3 | UnresolvedNamespace::X1::X2::X3::A | new | calls.rb:117:5:117:16 | new | +| unresolved_subclass.rb:21:1:22:3 | UnresolvedNamespace::X1::X2::X3::A | puts | calls.rb:102:5:102:30 | puts | +| unresolved_subclass.rb:21:1:22:3 | UnresolvedNamespace::X1::X2::X3::A | to_s | calls.rb:172:5:173:7 | to_s | enclosingMethod | calls.rb:2:5:2:14 | call to puts | calls.rb:1:1:3:3 | foo | | calls.rb:2:5:2:14 | self | calls.rb:1:1:3:3 | foo | diff --git a/ruby/ql/test/library-tests/modules/modules.expected b/ruby/ql/test/library-tests/modules/modules.expected index 21a4d6ba195..e138f5ce4c3 100644 --- a/ruby/ql/test/library-tests/modules/modules.expected +++ b/ruby/ql/test/library-tests/modules/modules.expected @@ -51,6 +51,9 @@ getModule | file://:0:0:0:0 | Symbol | | file://:0:0:0:0 | TrueClass | | file://:0:0:0:0 | UnresolvedNamespace | +| file://:0:0:0:0 | UnresolvedNamespace::X1 | +| file://:0:0:0:0 | UnresolvedNamespace::X1::X2 | +| file://:0:0:0:0 | UnresolvedNamespace::X1::X2::X3 | | hello.rb:1:1:8:3 | EnglishWords | | hello.rb:11:1:16:3 | Greeting | | hello.rb:18:1:22:3 | HelloWorld | @@ -97,6 +100,9 @@ getModule | unresolved_subclass.rb:4:1:5:3 | UnresolvedNamespace::Subclass1 | | unresolved_subclass.rb:7:1:8:3 | UnresolvedNamespace::Subclass2 | | unresolved_subclass.rb:11:1:12:3 | UnresolvedNamespace::A | +| unresolved_subclass.rb:14:1:15:3 | UnresolvedNamespace::X1::X2::X3::Subclass1 | +| unresolved_subclass.rb:17:1:18:3 | UnresolvedNamespace::X1::X2::X3::Subclass2 | +| unresolved_subclass.rb:21:1:22:3 | UnresolvedNamespace::X1::X2::X3::A | getADeclaration | calls.rb:21:1:34:3 | M | calls.rb:21:1:34:3 | M | | calls.rb:43:1:58:3 | C | calls.rb:43:1:58:3 | C | @@ -113,7 +119,7 @@ getADeclaration | calls.rb:115:1:118:3 | Object | modules_rec.rb:1:1:11:26 | modules_rec.rb | | calls.rb:115:1:118:3 | Object | private.rb:1:1:105:40 | private.rb | | calls.rb:115:1:118:3 | Object | toplevel_self_singleton.rb:1:1:34:4 | toplevel_self_singleton.rb | -| calls.rb:115:1:118:3 | Object | unresolved_subclass.rb:1:1:12:4 | unresolved_subclass.rb | +| calls.rb:115:1:118:3 | Object | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | | calls.rb:120:1:123:3 | Hash | calls.rb:120:1:123:3 | Hash | | calls.rb:125:1:138:3 | Array | calls.rb:125:1:138:3 | Array | | calls.rb:165:1:169:3 | S | calls.rb:165:1:169:3 | S | @@ -197,6 +203,9 @@ getADeclaration | unresolved_subclass.rb:4:1:5:3 | UnresolvedNamespace::Subclass1 | unresolved_subclass.rb:4:1:5:3 | Subclass1 | | unresolved_subclass.rb:7:1:8:3 | UnresolvedNamespace::Subclass2 | unresolved_subclass.rb:7:1:8:3 | Subclass2 | | unresolved_subclass.rb:11:1:12:3 | UnresolvedNamespace::A | unresolved_subclass.rb:11:1:12:3 | A | +| unresolved_subclass.rb:14:1:15:3 | UnresolvedNamespace::X1::X2::X3::Subclass1 | unresolved_subclass.rb:14:1:15:3 | Subclass1 | +| unresolved_subclass.rb:17:1:18:3 | UnresolvedNamespace::X1::X2::X3::Subclass2 | unresolved_subclass.rb:17:1:18:3 | Subclass2 | +| unresolved_subclass.rb:21:1:22:3 | UnresolvedNamespace::X1::X2::X3::A | unresolved_subclass.rb:21:1:22:3 | A | getSuperClass | calls.rb:43:1:58:3 | C | calls.rb:115:1:118:3 | Object | | calls.rb:65:1:69:3 | D | calls.rb:43:1:58:3 | C | @@ -259,6 +268,9 @@ getSuperClass | unresolved_subclass.rb:4:1:5:3 | UnresolvedNamespace::Subclass1 | unresolved_subclass.rb:1:1:2:3 | ResolvableBaseClass | | unresolved_subclass.rb:7:1:8:3 | UnresolvedNamespace::Subclass2 | unresolved_subclass.rb:4:1:5:3 | UnresolvedNamespace::Subclass1 | | unresolved_subclass.rb:11:1:12:3 | UnresolvedNamespace::A | calls.rb:115:1:118:3 | Object | +| unresolved_subclass.rb:14:1:15:3 | UnresolvedNamespace::X1::X2::X3::Subclass1 | unresolved_subclass.rb:1:1:2:3 | ResolvableBaseClass | +| unresolved_subclass.rb:17:1:18:3 | UnresolvedNamespace::X1::X2::X3::Subclass2 | unresolved_subclass.rb:14:1:15:3 | UnresolvedNamespace::X1::X2::X3::Subclass1 | +| unresolved_subclass.rb:21:1:22:3 | UnresolvedNamespace::X1::X2::X3::A | calls.rb:115:1:118:3 | Object | getAPrependedModule | calls.rb:115:1:118:3 | Object | calls.rb:171:1:174:3 | A | | calls.rb:171:1:174:3 | A | toplevel_self_singleton.rb:2:5:5:7 | A::B | @@ -419,6 +431,28 @@ resolveConstantReadAccess | unresolved_subclass.rb:7:40:7:69 | Subclass1 | UnresolvedNamespace::Subclass1 | | unresolved_subclass.rb:11:7:11:25 | UnresolvedNamespace | UnresolvedNamespace | | unresolved_subclass.rb:11:32:11:50 | UnresolvedNamespace | UnresolvedNamespace | +| unresolved_subclass.rb:14:7:14:25 | UnresolvedNamespace | UnresolvedNamespace | +| unresolved_subclass.rb:14:7:14:29 | X1 | UnresolvedNamespace::X1 | +| unresolved_subclass.rb:14:7:14:33 | X2 | UnresolvedNamespace::X1::X2 | +| unresolved_subclass.rb:14:7:14:37 | X3 | UnresolvedNamespace::X1::X2::X3 | +| unresolved_subclass.rb:14:52:14:70 | ResolvableBaseClass | ResolvableBaseClass | +| unresolved_subclass.rb:17:7:17:25 | UnresolvedNamespace | UnresolvedNamespace | +| unresolved_subclass.rb:17:7:17:29 | X1 | UnresolvedNamespace::X1 | +| unresolved_subclass.rb:17:7:17:33 | X2 | UnresolvedNamespace::X1::X2 | +| unresolved_subclass.rb:17:7:17:37 | X3 | UnresolvedNamespace::X1::X2::X3 | +| unresolved_subclass.rb:17:52:17:70 | UnresolvedNamespace | UnresolvedNamespace | +| unresolved_subclass.rb:17:52:17:74 | X1 | UnresolvedNamespace::X1 | +| unresolved_subclass.rb:17:52:17:78 | X2 | UnresolvedNamespace::X1::X2 | +| unresolved_subclass.rb:17:52:17:82 | X3 | UnresolvedNamespace::X1::X2::X3 | +| unresolved_subclass.rb:17:52:17:93 | Subclass1 | UnresolvedNamespace::X1::X2::X3::Subclass1 | +| unresolved_subclass.rb:21:7:21:25 | UnresolvedNamespace | UnresolvedNamespace | +| unresolved_subclass.rb:21:7:21:29 | X1 | UnresolvedNamespace::X1 | +| unresolved_subclass.rb:21:7:21:33 | X2 | UnresolvedNamespace::X1::X2 | +| unresolved_subclass.rb:21:7:21:37 | X3 | UnresolvedNamespace::X1::X2::X3 | +| unresolved_subclass.rb:21:44:21:62 | UnresolvedNamespace | UnresolvedNamespace | +| unresolved_subclass.rb:21:44:21:66 | X1 | UnresolvedNamespace::X1 | +| unresolved_subclass.rb:21:44:21:70 | X2 | UnresolvedNamespace::X1::X2 | +| unresolved_subclass.rb:21:44:21:74 | X3 | UnresolvedNamespace::X1::X2::X3 | resolveConstantWriteAccess | calls.rb:21:1:34:3 | M | M | | calls.rb:43:1:58:3 | C | C | @@ -523,6 +557,9 @@ resolveConstantWriteAccess | unresolved_subclass.rb:4:1:5:3 | Subclass1 | UnresolvedNamespace::Subclass1 | | unresolved_subclass.rb:7:1:8:3 | Subclass2 | UnresolvedNamespace::Subclass2 | | unresolved_subclass.rb:11:1:12:3 | A | UnresolvedNamespace::A | +| unresolved_subclass.rb:14:1:15:3 | Subclass1 | UnresolvedNamespace::X1::X2::X3::Subclass1 | +| unresolved_subclass.rb:17:1:18:3 | Subclass2 | UnresolvedNamespace::X1::X2::X3::Subclass2 | +| unresolved_subclass.rb:21:1:22:3 | A | UnresolvedNamespace::X1::X2::X3::A | enclosingModule | calls.rb:1:1:3:3 | foo | calls.rb:1:1:651:24 | calls.rb | | calls.rb:2:5:2:14 | call to puts | calls.rb:1:1:651:24 | calls.rb | @@ -1878,15 +1915,41 @@ enclosingModule | toplevel_self_singleton.rb:30:13:30:19 | self | toplevel_self_singleton.rb:25:5:33:7 | class << ... | | toplevel_self_singleton.rb:31:13:31:20 | call to call_you | toplevel_self_singleton.rb:25:5:33:7 | class << ... | | toplevel_self_singleton.rb:31:13:31:20 | self | toplevel_self_singleton.rb:25:5:33:7 | class << ... | -| unresolved_subclass.rb:1:1:2:3 | ResolvableBaseClass | unresolved_subclass.rb:1:1:12:4 | unresolved_subclass.rb | -| unresolved_subclass.rb:4:1:5:3 | Subclass1 | unresolved_subclass.rb:1:1:12:4 | unresolved_subclass.rb | -| unresolved_subclass.rb:4:7:4:25 | UnresolvedNamespace | unresolved_subclass.rb:1:1:12:4 | unresolved_subclass.rb | -| unresolved_subclass.rb:4:40:4:58 | ResolvableBaseClass | unresolved_subclass.rb:1:1:12:4 | unresolved_subclass.rb | -| unresolved_subclass.rb:7:1:8:3 | Subclass2 | unresolved_subclass.rb:1:1:12:4 | unresolved_subclass.rb | -| unresolved_subclass.rb:7:7:7:25 | UnresolvedNamespace | unresolved_subclass.rb:1:1:12:4 | unresolved_subclass.rb | -| unresolved_subclass.rb:7:40:7:58 | UnresolvedNamespace | unresolved_subclass.rb:1:1:12:4 | unresolved_subclass.rb | -| unresolved_subclass.rb:7:40:7:69 | Subclass1 | unresolved_subclass.rb:1:1:12:4 | unresolved_subclass.rb | -| unresolved_subclass.rb:11:1:12:3 | A | unresolved_subclass.rb:1:1:12:4 | unresolved_subclass.rb | -| unresolved_subclass.rb:11:7:11:25 | UnresolvedNamespace | unresolved_subclass.rb:1:1:12:4 | unresolved_subclass.rb | -| unresolved_subclass.rb:11:32:11:50 | UnresolvedNamespace | unresolved_subclass.rb:1:1:12:4 | unresolved_subclass.rb | -| unresolved_subclass.rb:11:32:11:53 | B | unresolved_subclass.rb:1:1:12:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:1:1:2:3 | ResolvableBaseClass | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:4:1:5:3 | Subclass1 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:4:7:4:25 | UnresolvedNamespace | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:4:40:4:58 | ResolvableBaseClass | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:7:1:8:3 | Subclass2 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:7:7:7:25 | UnresolvedNamespace | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:7:40:7:58 | UnresolvedNamespace | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:7:40:7:69 | Subclass1 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:11:1:12:3 | A | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:11:7:11:25 | UnresolvedNamespace | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:11:32:11:50 | UnresolvedNamespace | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:11:32:11:53 | B | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:14:1:15:3 | Subclass1 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:14:7:14:25 | UnresolvedNamespace | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:14:7:14:29 | X1 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:14:7:14:33 | X2 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:14:7:14:37 | X3 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:14:52:14:70 | ResolvableBaseClass | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:17:1:18:3 | Subclass2 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:17:7:17:25 | UnresolvedNamespace | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:17:7:17:29 | X1 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:17:7:17:33 | X2 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:17:7:17:37 | X3 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:17:52:17:70 | UnresolvedNamespace | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:17:52:17:74 | X1 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:17:52:17:78 | X2 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:17:52:17:82 | X3 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:17:52:17:93 | Subclass1 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:21:1:22:3 | A | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:21:7:21:25 | UnresolvedNamespace | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:21:7:21:29 | X1 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:21:7:21:33 | X2 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:21:7:21:37 | X3 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:21:44:21:62 | UnresolvedNamespace | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:21:44:21:66 | X1 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:21:44:21:70 | X2 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:21:44:21:74 | X3 | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | +| unresolved_subclass.rb:21:44:21:77 | B | unresolved_subclass.rb:1:1:22:4 | unresolved_subclass.rb | diff --git a/ruby/ql/test/library-tests/modules/superclasses.expected b/ruby/ql/test/library-tests/modules/superclasses.expected index 14121b1da31..a2c3473098b 100644 --- a/ruby/ql/test/library-tests/modules/superclasses.expected +++ b/ruby/ql/test/library-tests/modules/superclasses.expected @@ -36,6 +36,12 @@ #-----| TrueClass #-----| -> Object +#-----| UnresolvedNamespace::X1 + +#-----| UnresolvedNamespace::X1::X2 + +#-----| UnresolvedNamespace::X1::X2::X3 + calls.rb: # 21| M @@ -262,3 +268,12 @@ unresolved_subclass.rb: # 11| UnresolvedNamespace::A #-----| -> Object + +# 14| UnresolvedNamespace::X1::X2::X3::Subclass1 +#-----| -> ResolvableBaseClass + +# 17| UnresolvedNamespace::X1::X2::X3::Subclass2 +#-----| -> UnresolvedNamespace::X1::X2::X3::Subclass1 + +# 21| UnresolvedNamespace::X1::X2::X3::A +#-----| -> Object diff --git a/ruby/ql/test/library-tests/modules/unresolved_subclass.rb b/ruby/ql/test/library-tests/modules/unresolved_subclass.rb index 309330c6af1..2dad594a2a5 100644 --- a/ruby/ql/test/library-tests/modules/unresolved_subclass.rb +++ b/ruby/ql/test/library-tests/modules/unresolved_subclass.rb @@ -10,3 +10,13 @@ end # Ensure Object is a transitive superclass of this class UnresolvedNamespace::A < UnresolvedNamespace::B end + +class UnresolvedNamespace::X1::X2::X3::Subclass1 < ResolvableBaseClass +end + +class UnresolvedNamespace::X1::X2::X3::Subclass2 < UnresolvedNamespace::X1::X2::X3::Subclass1 +end + +# Ensure Object is a transitive superclass of this +class UnresolvedNamespace::X1::X2::X3::A < UnresolvedNamespace::X1::X2::X3::B +end diff --git a/ruby/ql/test/library-tests/variables/ssa.expected b/ruby/ql/test/library-tests/variables/ssa.expected index 2f6d07b9915..962cd733a08 100644 --- a/ruby/ql/test/library-tests/variables/ssa.expected +++ b/ruby/ql/test/library-tests/variables/ssa.expected @@ -22,29 +22,29 @@ definition | instance_variables.rb:38:4:40:6 | self (y) | instance_variables.rb:38:4:40:6 | self | | nested_scopes.rb:1:1:3:3 | self (a) | nested_scopes.rb:1:1:3:3 | self | | nested_scopes.rb:4:1:39:3 | self (C) | nested_scopes.rb:4:1:39:3 | self | -| nested_scopes.rb:5:3:5:7 | ... = ... | nested_scopes.rb:5:3:5:3 | a | +| nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:5:3:5:3 | a | | nested_scopes.rb:6:3:37:5 | self (M) | nested_scopes.rb:6:3:37:5 | self | -| nested_scopes.rb:7:5:7:9 | ... = ... | nested_scopes.rb:7:5:7:5 | a | +| nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:7:5:7:5 | a | | nested_scopes.rb:8:5:35:7 | self (N) | nested_scopes.rb:8:5:35:7 | self | -| nested_scopes.rb:9:7:9:11 | ... = ... | nested_scopes.rb:9:7:9:7 | a | +| nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:9:7:9:7 | a | | nested_scopes.rb:10:7:26:9 | self (D) | nested_scopes.rb:10:7:26:9 | self | -| nested_scopes.rb:11:9:11:13 | ... = ... | nested_scopes.rb:11:9:11:9 | a | +| nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:11:9:11:9 | a | | nested_scopes.rb:12:9:21:11 | self (show_a) | nested_scopes.rb:12:9:21:11 | self | -| nested_scopes.rb:13:11:13:15 | ... = ... | nested_scopes.rb:13:11:13:11 | a | +| nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:13:11:13:11 | a | | nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:23:15:23 | a | -| nested_scopes.rb:17:15:17:19 | ... = ... | nested_scopes.rb:16:29:16:29 | a | +| nested_scopes.rb:17:15:17:15 | a | nested_scopes.rb:16:29:16:29 | a | | nested_scopes.rb:18:23:18:36 | <captured entry> a | nested_scopes.rb:16:29:16:29 | a | | nested_scopes.rb:18:23:18:36 | <captured entry> self | nested_scopes.rb:12:9:21:11 | self | | nested_scopes.rb:22:9:24:11 | self (show_a2) | nested_scopes.rb:22:9:24:11 | self | | nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:21:22:21 | a | | nested_scopes.rb:27:7:29:9 | self (show) | nested_scopes.rb:27:7:29:9 | self | | nested_scopes.rb:30:16:30:19 | self (class << ...) | nested_scopes.rb:30:7:33:9 | self | -| nested_scopes.rb:31:11:31:16 | ... = ... | nested_scopes.rb:31:11:31:11 | a | -| nested_scopes.rb:40:1:40:18 | ... = ... | nested_scopes.rb:40:1:40:1 | d | +| nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:31:11:31:11 | a | +| nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:40:1:40:1 | d | | parameters.rb:1:1:62:1 | self (parameters.rb) | parameters.rb:1:1:62:1 | self | | parameters.rb:1:9:5:3 | <captured entry> self | parameters.rb:1:1:62:1 | self | | parameters.rb:1:14:1:14 | x | parameters.rb:1:14:1:14 | x | -| parameters.rb:2:4:2:8 | ... = ... | parameters.rb:1:18:1:18 | y | +| parameters.rb:2:4:2:4 | y | parameters.rb:1:18:1:18 | y | | parameters.rb:7:1:13:3 | self (order_pizza) | parameters.rb:7:1:13:3 | self | | parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | @@ -64,23 +64,23 @@ definition | parameters.rb:35:1:38:3 | <uninitialized> | parameters.rb:35:16:35:16 | b | | parameters.rb:35:1:38:3 | self (multi) | parameters.rb:35:1:38:3 | self | | parameters.rb:35:11:35:11 | a | parameters.rb:35:11:35:11 | a | -| parameters.rb:35:16:35:20 | ... = ... | parameters.rb:35:16:35:16 | b | +| parameters.rb:35:16:35:16 | b | parameters.rb:35:16:35:16 | b | | parameters.rb:37:3:37:18 | phi | parameters.rb:35:16:35:16 | b | | parameters.rb:40:1:43:3 | <uninitialized> | parameters.rb:40:15:40:15 | e | | parameters.rb:40:1:43:3 | self (multi2) | parameters.rb:40:1:43:3 | self | | parameters.rb:40:12:40:12 | d | parameters.rb:40:12:40:12 | d | -| parameters.rb:40:15:40:19 | ... = ... | parameters.rb:40:15:40:15 | e | +| parameters.rb:40:15:40:15 | e | parameters.rb:40:15:40:15 | e | | parameters.rb:42:3:42:18 | phi | parameters.rb:40:15:40:15 | e | | parameters.rb:45:1:47:3 | self (dup_underscore) | parameters.rb:45:1:47:3 | self | | parameters.rb:45:20:45:20 | _ | parameters.rb:45:20:45:20 | _ | | parameters.rb:49:1:51:3 | self (tuples) | parameters.rb:49:1:51:3 | self | | parameters.rb:49:13:49:13 | a | parameters.rb:49:13:49:13 | a | | parameters.rb:49:15:49:15 | b | parameters.rb:49:15:49:15 | b | -| parameters.rb:53:1:53:6 | ... = ... | parameters.rb:53:1:53:1 | x | +| parameters.rb:53:1:53:1 | x | parameters.rb:53:1:53:1 | x | | parameters.rb:54:9:57:3 | <captured entry> self | parameters.rb:1:1:62:1 | self | | parameters.rb:54:9:57:3 | <captured entry> x | parameters.rb:53:1:53:1 | x | | parameters.rb:54:14:54:14 | y | parameters.rb:54:14:54:14 | y | -| parameters.rb:54:19:54:23 | ... = ... | parameters.rb:53:1:53:1 | x | +| parameters.rb:54:19:54:19 | x | parameters.rb:53:1:53:1 | x | | parameters.rb:55:4:55:9 | phi | parameters.rb:53:1:53:1 | x | | parameters.rb:59:1:61:3 | self (tuples_nested) | parameters.rb:59:1:61:3 | self | | parameters.rb:59:20:59:20 | a | parameters.rb:59:20:59:20 | a | @@ -88,80 +88,80 @@ definition | parameters.rb:59:25:59:25 | c | parameters.rb:59:25:59:25 | c | | scopes.rb:1:1:49:4 | self (scopes.rb) | scopes.rb:1:1:49:4 | self | | scopes.rb:2:9:6:3 | <captured entry> self | scopes.rb:1:1:49:4 | self | -| scopes.rb:4:4:4:8 | ... = ... | scopes.rb:4:4:4:4 | a | -| scopes.rb:7:1:7:5 | ... = ... | scopes.rb:7:1:7:1 | a | +| scopes.rb:4:4:4:4 | a | scopes.rb:4:4:4:4 | a | +| scopes.rb:7:1:7:1 | a | scopes.rb:7:1:7:1 | a | | scopes.rb:9:1:18:3 | <captured exit> a | scopes.rb:7:1:7:1 | a | | scopes.rb:9:9:18:3 | <captured entry> a | scopes.rb:7:1:7:1 | a | | scopes.rb:9:9:18:3 | <captured entry> self | scopes.rb:1:1:49:4 | self | -| scopes.rb:11:4:11:9 | ... = ... | scopes.rb:7:1:7:1 | a | -| scopes.rb:13:4:13:4 | ... = ... | scopes.rb:7:1:7:1 | a | -| scopes.rb:13:7:13:7 | ... = ... | scopes.rb:13:7:13:7 | b | -| scopes.rb:13:10:13:15 | ... = ... | scopes.rb:13:10:13:15 | __synth__0__1 | -| scopes.rb:13:11:13:11 | ... = ... | scopes.rb:13:11:13:11 | c | -| scopes.rb:13:14:13:14 | ... = ... | scopes.rb:13:14:13:14 | d | -| scopes.rb:13:19:13:32 | ... = ... | scopes.rb:13:4:13:32 | __synth__0 | +| scopes.rb:11:4:11:4 | a | scopes.rb:7:1:7:1 | a | +| scopes.rb:13:4:13:4 | a | scopes.rb:7:1:7:1 | a | +| scopes.rb:13:7:13:7 | b | scopes.rb:13:7:13:7 | b | +| scopes.rb:13:10:13:15 | __synth__2__1 | scopes.rb:13:10:13:15 | __synth__2__1 | +| scopes.rb:13:11:13:11 | c | scopes.rb:13:11:13:11 | c | +| scopes.rb:13:14:13:14 | d | scopes.rb:13:14:13:14 | d | +| scopes.rb:13:19:13:32 | __synth__3 | scopes.rb:13:4:13:32 | __synth__3 | | scopes.rb:26:1:26:12 | self (A) | scopes.rb:26:1:26:12 | self | -| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | +| scopes.rb:27:1:27:1 | x | scopes.rb:27:1:27:1 | x | | scopes.rb:28:1:30:3 | self (B) | scopes.rb:28:1:30:3 | self | -| scopes.rb:29:3:29:7 | ... = ... | scopes.rb:29:3:29:3 | x | -| scopes.rb:32:3:32:7 | ... = ... | scopes.rb:32:3:32:3 | x | +| scopes.rb:29:3:29:3 | x | scopes.rb:29:3:29:3 | x | +| scopes.rb:32:3:32:3 | x | scopes.rb:32:3:32:3 | x | | scopes.rb:34:1:36:3 | self (C) | scopes.rb:34:1:36:3 | self | -| scopes.rb:35:3:35:7 | ... = ... | scopes.rb:35:3:35:3 | x | +| scopes.rb:35:3:35:3 | x | scopes.rb:35:3:35:3 | x | | scopes.rb:41:1:49:3 | self (M) | scopes.rb:41:1:49:3 | self | -| scopes.rb:42:2:42:9 | ... = ... | scopes.rb:42:2:42:4 | var | -| scopes.rb:43:2:43:13 | ... = ... | scopes.rb:43:2:43:4 | foo | -| scopes.rb:46:5:46:13 | ... = ... | scopes.rb:46:5:46:8 | var2 | +| scopes.rb:42:2:42:4 | var | scopes.rb:42:2:42:4 | var | +| scopes.rb:43:2:43:4 | foo | scopes.rb:43:2:43:4 | foo | +| scopes.rb:46:5:46:8 | var2 | scopes.rb:46:5:46:8 | var2 | | ssa.rb:1:1:16:3 | self (m) | ssa.rb:1:1:16:3 | self | | ssa.rb:1:7:1:7 | b | ssa.rb:1:7:1:7 | b | -| ssa.rb:2:3:2:7 | ... = ... | ssa.rb:2:3:2:3 | i | +| ssa.rb:2:3:2:3 | i | ssa.rb:2:3:2:3 | i | | ssa.rb:5:3:13:5 | phi | ssa.rb:2:3:2:3 | i | -| ssa.rb:6:5:6:9 | ... = ... | ssa.rb:2:3:2:3 | i | -| ssa.rb:10:5:10:9 | ... = ... | ssa.rb:2:3:2:3 | i | +| ssa.rb:6:5:6:5 | i | ssa.rb:2:3:2:3 | i | +| ssa.rb:10:5:10:5 | i | ssa.rb:2:3:2:3 | i | | ssa.rb:18:1:23:3 | self (m1) | ssa.rb:18:1:23:3 | self | | ssa.rb:18:8:18:8 | x | ssa.rb:18:8:18:8 | x | | ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | -| ssa.rb:21:5:21:10 | ... = ... | ssa.rb:18:8:18:8 | x | +| ssa.rb:21:5:21:5 | x | ssa.rb:18:8:18:8 | x | | ssa.rb:25:1:30:3 | <uninitialized> | ssa.rb:26:7:26:10 | elem | | ssa.rb:25:1:30:3 | self (m2) | ssa.rb:25:1:30:3 | self | | ssa.rb:25:8:25:15 | elements | ssa.rb:25:8:25:15 | elements | -| ssa.rb:26:3:28:5 | ... = ... | ssa.rb:26:7:26:10 | elem | | ssa.rb:26:3:28:5 | <captured entry> self | ssa.rb:25:1:30:3 | self | | ssa.rb:26:3:28:5 | <captured exit> elem | ssa.rb:26:7:26:10 | elem | | ssa.rb:26:3:28:5 | __synth__0__1 | ssa.rb:26:3:28:5 | __synth__0__1 | +| ssa.rb:26:7:26:10 | elem | ssa.rb:26:7:26:10 | elem | | ssa.rb:32:1:36:3 | self (m3) | ssa.rb:32:1:36:3 | self | | ssa.rb:33:16:35:5 | <captured entry> self | ssa.rb:32:1:36:3 | self | | ssa.rb:33:20:33:20 | x | ssa.rb:33:20:33:20 | x | | ssa.rb:38:1:42:3 | self (m4) | ssa.rb:38:1:42:3 | self | -| ssa.rb:40:3:40:9 | ... = ... | ssa.rb:40:3:40:4 | m3 | +| ssa.rb:40:3:40:4 | m3 | ssa.rb:40:3:40:4 | m3 | | ssa.rb:44:1:47:3 | <uninitialized> | ssa.rb:45:3:45:3 | x | | ssa.rb:44:1:47:3 | self (m5) | ssa.rb:44:1:47:3 | self | | ssa.rb:44:8:44:8 | b | ssa.rb:44:8:44:8 | b | -| ssa.rb:45:3:45:7 | ... = ... | ssa.rb:45:3:45:3 | x | +| ssa.rb:45:3:45:3 | x | ssa.rb:45:3:45:3 | x | | ssa.rb:45:3:45:12 | phi | ssa.rb:45:3:45:3 | x | | ssa.rb:49:1:51:3 | <uninitialized> | ssa.rb:49:14:49:14 | y | | ssa.rb:49:1:51:3 | self (m6) | ssa.rb:49:1:51:3 | self | -| ssa.rb:49:14:49:19 | ... = ... | ssa.rb:49:14:49:14 | y | +| ssa.rb:49:14:49:14 | y | ssa.rb:49:14:49:14 | y | | ssa.rb:50:3:50:8 | phi | ssa.rb:49:14:49:14 | y | | ssa.rb:53:1:56:3 | self (m7) | ssa.rb:53:1:56:3 | self | | ssa.rb:53:8:53:10 | foo | ssa.rb:53:8:53:10 | foo | -| ssa.rb:54:3:54:11 | ... = ... | ssa.rb:54:3:54:3 | x | +| ssa.rb:54:3:54:3 | x | ssa.rb:54:3:54:3 | x | | ssa.rb:58:1:62:3 | self (m8) | ssa.rb:58:1:62:3 | self | -| ssa.rb:59:3:59:8 | ... = ... | ssa.rb:59:3:59:3 | x | -| ssa.rb:60:3:60:9 | ... = ... | ssa.rb:59:3:59:3 | x | +| ssa.rb:59:3:59:3 | x | ssa.rb:59:3:59:3 | x | +| ssa.rb:60:3:60:3 | x | ssa.rb:59:3:59:3 | x | | ssa.rb:64:1:72:3 | self (m9) | ssa.rb:64:1:72:3 | self | | ssa.rb:64:8:64:8 | a | ssa.rb:64:8:64:8 | a | -| ssa.rb:65:3:65:15 | ... = ... | ssa.rb:65:3:65:10 | captured | +| ssa.rb:65:3:65:10 | captured | ssa.rb:65:3:65:10 | captured | | ssa.rb:66:3:70:5 | <captured exit> captured | ssa.rb:65:3:65:10 | captured | | ssa.rb:66:11:70:5 | <captured entry> captured | ssa.rb:65:3:65:10 | captured | | ssa.rb:66:11:70:5 | <captured entry> self | ssa.rb:64:1:72:3 | self | | ssa.rb:66:15:66:15 | a | ssa.rb:66:15:66:15 | a | -| ssa.rb:69:5:69:17 | ... = ... | ssa.rb:65:3:65:10 | captured | +| ssa.rb:69:5:69:12 | captured | ssa.rb:65:3:65:10 | captured | | ssa.rb:74:1:79:3 | self (m10) | ssa.rb:74:1:79:3 | self | -| ssa.rb:75:3:75:14 | ... = ... | ssa.rb:75:3:75:10 | captured | +| ssa.rb:75:3:75:10 | captured | ssa.rb:75:3:75:10 | captured | | ssa.rb:76:7:78:5 | <captured entry> captured | ssa.rb:75:3:75:10 | captured | | ssa.rb:76:7:78:5 | <captured entry> self | ssa.rb:74:1:79:3 | self | | ssa.rb:81:1:88:3 | self (m11) | ssa.rb:81:1:88:3 | self | -| ssa.rb:82:3:82:14 | ... = ... | ssa.rb:82:3:82:10 | captured | +| ssa.rb:82:3:82:10 | captured | ssa.rb:82:3:82:10 | captured | | ssa.rb:83:7:87:5 | <captured entry> self | ssa.rb:81:1:88:3 | self | | ssa.rb:84:10:86:8 | <captured entry> captured | ssa.rb:82:3:82:10 | captured | | ssa.rb:84:10:86:8 | <captured entry> self | ssa.rb:81:1:88:3 | self | @@ -170,7 +170,7 @@ definition | ssa.rb:90:13:90:14 | b2 | ssa.rb:90:13:90:14 | b2 | | ssa.rb:90:17:90:18 | b3 | ssa.rb:90:17:90:18 | b3 | | ssa.rb:90:21:90:22 | b4 | ssa.rb:90:21:90:22 | b4 | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | read | class_variables.rb:1:1:29:4 | self (class_variables.rb) | class_variables.rb:1:1:29:4 | self | class_variables.rb:3:1:3:5 | self | | class_variables.rb:5:1:7:3 | self (print) | class_variables.rb:5:1:7:3 | self | class_variables.rb:6:2:6:6 | self | @@ -199,20 +199,20 @@ read | instance_variables.rb:38:4:40:6 | self (y) | instance_variables.rb:38:4:40:6 | self | instance_variables.rb:39:6:39:7 | self | | nested_scopes.rb:1:1:3:3 | self (a) | nested_scopes.rb:1:1:3:3 | self | nested_scopes.rb:2:3:2:17 | self | | nested_scopes.rb:4:1:39:3 | self (C) | nested_scopes.rb:4:1:39:3 | self | nested_scopes.rb:38:3:38:8 | self | -| nested_scopes.rb:5:3:5:7 | ... = ... | nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:38:8:38:8 | a | +| nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:38:8:38:8 | a | | nested_scopes.rb:6:3:37:5 | self (M) | nested_scopes.rb:6:3:37:5 | self | nested_scopes.rb:36:5:36:10 | self | -| nested_scopes.rb:7:5:7:9 | ... = ... | nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:36:10:36:10 | a | +| nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:36:10:36:10 | a | | nested_scopes.rb:8:5:35:7 | self (N) | nested_scopes.rb:8:5:35:7 | self | nested_scopes.rb:27:11:27:14 | self | | nested_scopes.rb:8:5:35:7 | self (N) | nested_scopes.rb:8:5:35:7 | self | nested_scopes.rb:30:16:30:19 | self | | nested_scopes.rb:8:5:35:7 | self (N) | nested_scopes.rb:8:5:35:7 | self | nested_scopes.rb:34:7:34:12 | self | -| nested_scopes.rb:9:7:9:11 | ... = ... | nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:34:12:34:12 | a | +| nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:34:12:34:12 | a | | nested_scopes.rb:10:7:26:9 | self (D) | nested_scopes.rb:10:7:26:9 | self | nested_scopes.rb:25:9:25:14 | self | -| nested_scopes.rb:11:9:11:13 | ... = ... | nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:25:14:25:14 | a | +| nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:25:14:25:14 | a | | nested_scopes.rb:12:9:21:11 | self (show_a) | nested_scopes.rb:12:9:21:11 | self | nested_scopes.rb:14:11:14:16 | self | -| nested_scopes.rb:13:11:13:15 | ... = ... | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:14:16:14:16 | a | -| nested_scopes.rb:13:11:13:15 | ... = ... | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:15:11:15:11 | a | +| nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:14:16:14:16 | a | +| nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:15:11:15:11 | a | | nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:16:13:16:13 | a | -| nested_scopes.rb:17:15:17:19 | ... = ... | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:18:15:18:15 | a | +| nested_scopes.rb:17:15:17:15 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:18:15:18:15 | a | | nested_scopes.rb:18:23:18:36 | <captured entry> a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:18:34:18:34 | a | | nested_scopes.rb:18:23:18:36 | <captured entry> self | nested_scopes.rb:12:9:21:11 | self | nested_scopes.rb:18:29:18:34 | self | | nested_scopes.rb:22:9:24:11 | self (show_a2) | nested_scopes.rb:22:9:24:11 | self | nested_scopes.rb:23:11:23:16 | self | @@ -220,12 +220,12 @@ read | nested_scopes.rb:27:7:29:9 | self (show) | nested_scopes.rb:27:7:29:9 | self | nested_scopes.rb:28:11:28:16 | self | | nested_scopes.rb:27:7:29:9 | self (show) | nested_scopes.rb:27:7:29:9 | self | nested_scopes.rb:28:16:28:16 | self | | nested_scopes.rb:30:16:30:19 | self (class << ...) | nested_scopes.rb:30:7:33:9 | self | nested_scopes.rb:32:11:32:16 | self | -| nested_scopes.rb:31:11:31:16 | ... = ... | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:32:16:32:16 | a | -| nested_scopes.rb:40:1:40:18 | ... = ... | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:41:1:41:1 | d | +| nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:32:16:32:16 | a | +| nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:41:1:41:1 | d | | parameters.rb:1:9:5:3 | <captured entry> self | parameters.rb:1:1:62:1 | self | parameters.rb:3:4:3:9 | self | | parameters.rb:1:9:5:3 | <captured entry> self | parameters.rb:1:1:62:1 | self | parameters.rb:4:4:4:9 | self | | parameters.rb:1:14:1:14 | x | parameters.rb:1:14:1:14 | x | parameters.rb:3:9:3:9 | x | -| parameters.rb:2:4:2:8 | ... = ... | parameters.rb:1:18:1:18 | y | parameters.rb:4:9:4:9 | y | +| parameters.rb:2:4:2:4 | y | parameters.rb:1:18:1:18 | y | parameters.rb:4:9:4:9 | y | | parameters.rb:7:1:13:3 | self (order_pizza) | parameters.rb:7:1:13:3 | self | parameters.rb:9:5:9:33 | self | | parameters.rb:7:1:13:3 | self (order_pizza) | parameters.rb:7:1:13:3 | self | parameters.rb:11:5:11:49 | self | | parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | parameters.rb:9:25:9:30 | client | @@ -269,8 +269,8 @@ read | scopes.rb:2:9:6:3 | <captured entry> self | scopes.rb:1:1:49:4 | self | scopes.rb:3:4:3:9 | self | | scopes.rb:2:9:6:3 | <captured entry> self | scopes.rb:1:1:49:4 | self | scopes.rb:3:9:3:9 | self | | scopes.rb:2:9:6:3 | <captured entry> self | scopes.rb:1:1:49:4 | self | scopes.rb:5:4:5:9 | self | -| scopes.rb:4:4:4:8 | ... = ... | scopes.rb:4:4:4:4 | a | scopes.rb:5:9:5:9 | a | -| scopes.rb:7:1:7:5 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:8:6:8:6 | a | +| scopes.rb:4:4:4:4 | a | scopes.rb:4:4:4:4 | a | scopes.rb:5:9:5:9 | a | +| scopes.rb:7:1:7:1 | a | scopes.rb:7:1:7:1 | a | scopes.rb:8:6:8:6 | a | | scopes.rb:9:9:18:3 | <captured entry> a | scopes.rb:7:1:7:1 | a | scopes.rb:10:9:10:9 | a | | scopes.rb:9:9:18:3 | <captured entry> a | scopes.rb:7:1:7:1 | a | scopes.rb:11:4:11:4 | a | | scopes.rb:9:9:18:3 | <captured entry> self | scopes.rb:1:1:49:4 | self | scopes.rb:10:4:10:9 | self | @@ -279,24 +279,24 @@ read | scopes.rb:9:9:18:3 | <captured entry> self | scopes.rb:1:1:49:4 | self | scopes.rb:15:4:15:9 | self | | scopes.rb:9:9:18:3 | <captured entry> self | scopes.rb:1:1:49:4 | self | scopes.rb:16:4:16:9 | self | | scopes.rb:9:9:18:3 | <captured entry> self | scopes.rb:1:1:49:4 | self | scopes.rb:17:4:17:9 | self | -| scopes.rb:11:4:11:9 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:12:9:12:9 | a | -| scopes.rb:13:4:13:4 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:14:9:14:9 | a | -| scopes.rb:13:7:13:7 | ... = ... | scopes.rb:13:7:13:7 | b | scopes.rb:15:9:15:9 | b | -| scopes.rb:13:10:13:15 | ... = ... | scopes.rb:13:10:13:15 | __synth__0__1 | scopes.rb:13:11:13:11 | __synth__0__1 | -| scopes.rb:13:10:13:15 | ... = ... | scopes.rb:13:10:13:15 | __synth__0__1 | scopes.rb:13:14:13:14 | __synth__0__1 | -| scopes.rb:13:11:13:11 | ... = ... | scopes.rb:13:11:13:11 | c | scopes.rb:16:9:16:9 | c | -| scopes.rb:13:14:13:14 | ... = ... | scopes.rb:13:14:13:14 | d | scopes.rb:17:9:17:9 | d | -| scopes.rb:13:19:13:32 | ... = ... | scopes.rb:13:4:13:32 | __synth__0 | scopes.rb:13:4:13:4 | __synth__0 | -| scopes.rb:13:19:13:32 | ... = ... | scopes.rb:13:4:13:32 | __synth__0 | scopes.rb:13:7:13:7 | __synth__0 | -| scopes.rb:13:19:13:32 | ... = ... | scopes.rb:13:4:13:32 | __synth__0 | scopes.rb:13:10:13:15 | __synth__0 | -| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:28:8:28:8 | x | -| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:31:10:31:10 | x | -| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:34:7:34:7 | x | -| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:34:14:34:14 | x | -| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:37:5:37:5 | x | +| scopes.rb:11:4:11:4 | a | scopes.rb:7:1:7:1 | a | scopes.rb:12:9:12:9 | a | +| scopes.rb:13:4:13:4 | a | scopes.rb:7:1:7:1 | a | scopes.rb:14:9:14:9 | a | +| scopes.rb:13:7:13:7 | b | scopes.rb:13:7:13:7 | b | scopes.rb:15:9:15:9 | b | +| scopes.rb:13:10:13:15 | __synth__2__1 | scopes.rb:13:10:13:15 | __synth__2__1 | scopes.rb:13:11:13:11 | __synth__2__1 | +| scopes.rb:13:10:13:15 | __synth__2__1 | scopes.rb:13:10:13:15 | __synth__2__1 | scopes.rb:13:14:13:14 | __synth__2__1 | +| scopes.rb:13:11:13:11 | c | scopes.rb:13:11:13:11 | c | scopes.rb:16:9:16:9 | c | +| scopes.rb:13:14:13:14 | d | scopes.rb:13:14:13:14 | d | scopes.rb:17:9:17:9 | d | +| scopes.rb:13:19:13:32 | __synth__3 | scopes.rb:13:4:13:32 | __synth__3 | scopes.rb:13:4:13:4 | __synth__3 | +| scopes.rb:13:19:13:32 | __synth__3 | scopes.rb:13:4:13:32 | __synth__3 | scopes.rb:13:7:13:7 | __synth__3 | +| scopes.rb:13:19:13:32 | __synth__3 | scopes.rb:13:4:13:32 | __synth__3 | scopes.rb:13:10:13:15 | __synth__3 | +| scopes.rb:27:1:27:1 | x | scopes.rb:27:1:27:1 | x | scopes.rb:28:8:28:8 | x | +| scopes.rb:27:1:27:1 | x | scopes.rb:27:1:27:1 | x | scopes.rb:31:10:31:10 | x | +| scopes.rb:27:1:27:1 | x | scopes.rb:27:1:27:1 | x | scopes.rb:34:7:34:7 | x | +| scopes.rb:27:1:27:1 | x | scopes.rb:27:1:27:1 | x | scopes.rb:34:14:34:14 | x | +| scopes.rb:27:1:27:1 | x | scopes.rb:27:1:27:1 | x | scopes.rb:37:5:37:5 | x | | scopes.rb:41:1:49:3 | self (M) | scopes.rb:41:1:49:3 | self | scopes.rb:45:5:45:7 | self | -| scopes.rb:42:2:42:9 | ... = ... | scopes.rb:42:2:42:4 | var | scopes.rb:44:5:44:7 | var | -| scopes.rb:46:5:46:13 | ... = ... | scopes.rb:46:5:46:8 | var2 | scopes.rb:47:5:47:8 | var2 | +| scopes.rb:42:2:42:4 | var | scopes.rb:42:2:42:4 | var | scopes.rb:44:5:44:7 | var | +| scopes.rb:46:5:46:8 | var2 | scopes.rb:46:5:46:8 | var2 | scopes.rb:47:5:47:8 | var2 | | ssa.rb:1:1:16:3 | self (m) | ssa.rb:1:1:16:3 | self | ssa.rb:3:3:3:8 | self | | ssa.rb:1:1:16:3 | self (m) | ssa.rb:1:1:16:3 | self | ssa.rb:4:3:4:12 | self | | ssa.rb:1:1:16:3 | self (m) | ssa.rb:1:1:16:3 | self | ssa.rb:7:5:7:10 | self | @@ -305,29 +305,29 @@ read | ssa.rb:1:1:16:3 | self (m) | ssa.rb:1:1:16:3 | self | ssa.rb:12:5:12:14 | self | | ssa.rb:1:1:16:3 | self (m) | ssa.rb:1:1:16:3 | self | ssa.rb:15:3:15:8 | self | | ssa.rb:1:7:1:7 | b | ssa.rb:1:7:1:7 | b | ssa.rb:5:6:5:6 | b | -| ssa.rb:2:3:2:7 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:3:8:3:8 | i | -| ssa.rb:2:3:2:7 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:4:8:4:8 | i | +| ssa.rb:2:3:2:3 | i | ssa.rb:2:3:2:3 | i | ssa.rb:3:8:3:8 | i | +| ssa.rb:2:3:2:3 | i | ssa.rb:2:3:2:3 | i | ssa.rb:4:8:4:8 | i | | ssa.rb:5:3:13:5 | phi | ssa.rb:2:3:2:3 | i | ssa.rb:15:8:15:8 | i | -| ssa.rb:6:5:6:9 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:7:10:7:10 | i | -| ssa.rb:6:5:6:9 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:8:10:8:10 | i | -| ssa.rb:10:5:10:9 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:11:10:11:10 | i | -| ssa.rb:10:5:10:9 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:12:10:12:10 | i | +| ssa.rb:6:5:6:5 | i | ssa.rb:2:3:2:3 | i | ssa.rb:7:10:7:10 | i | +| ssa.rb:6:5:6:5 | i | ssa.rb:2:3:2:3 | i | ssa.rb:8:10:8:10 | i | +| ssa.rb:10:5:10:5 | i | ssa.rb:2:3:2:3 | i | ssa.rb:11:10:11:10 | i | +| ssa.rb:10:5:10:5 | i | ssa.rb:2:3:2:3 | i | ssa.rb:12:10:12:10 | i | | ssa.rb:18:1:23:3 | self (m1) | ssa.rb:18:1:23:3 | self | ssa.rb:20:5:20:10 | self | | ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:19:9:19:9 | x | | ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:20:10:20:10 | x | | ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:21:5:21:5 | x | | ssa.rb:25:1:30:3 | self (m2) | ssa.rb:25:1:30:3 | self | ssa.rb:29:3:29:11 | self | | ssa.rb:25:8:25:15 | elements | ssa.rb:25:8:25:15 | elements | ssa.rb:26:15:26:22 | elements | -| ssa.rb:26:3:28:5 | ... = ... | ssa.rb:26:7:26:10 | elem | ssa.rb:27:10:27:13 | elem | | ssa.rb:26:3:28:5 | <captured entry> self | ssa.rb:25:1:30:3 | self | ssa.rb:27:5:27:13 | self | | ssa.rb:26:3:28:5 | <captured exit> elem | ssa.rb:26:7:26:10 | elem | ssa.rb:29:8:29:11 | elem | | ssa.rb:26:3:28:5 | __synth__0__1 | ssa.rb:26:3:28:5 | __synth__0__1 | ssa.rb:26:3:28:5 | __synth__0__1 | +| ssa.rb:26:7:26:10 | elem | ssa.rb:26:7:26:10 | elem | ssa.rb:27:10:27:13 | elem | | ssa.rb:33:16:35:5 | <captured entry> self | ssa.rb:32:1:36:3 | self | ssa.rb:34:5:34:10 | self | | ssa.rb:33:20:33:20 | x | ssa.rb:33:20:33:20 | x | ssa.rb:34:10:34:10 | x | | ssa.rb:38:1:42:3 | self (m4) | ssa.rb:38:1:42:3 | self | ssa.rb:39:3:39:9 | self | | ssa.rb:38:1:42:3 | self (m4) | ssa.rb:38:1:42:3 | self | ssa.rb:39:8:39:9 | self | | ssa.rb:38:1:42:3 | self (m4) | ssa.rb:38:1:42:3 | self | ssa.rb:41:3:41:13 | self | -| ssa.rb:40:3:40:9 | ... = ... | ssa.rb:40:3:40:4 | m3 | ssa.rb:41:8:41:9 | m3 | +| ssa.rb:40:3:40:4 | m3 | ssa.rb:40:3:40:4 | m3 | ssa.rb:41:8:41:9 | m3 | | ssa.rb:44:1:47:3 | self (m5) | ssa.rb:44:1:47:3 | self | ssa.rb:46:3:46:8 | self | | ssa.rb:44:8:44:8 | b | ssa.rb:44:8:44:8 | b | ssa.rb:45:12:45:12 | b | | ssa.rb:45:3:45:12 | phi | ssa.rb:45:3:45:3 | x | ssa.rb:46:8:46:8 | x | @@ -335,10 +335,10 @@ read | ssa.rb:50:3:50:8 | phi | ssa.rb:49:14:49:14 | y | ssa.rb:50:8:50:8 | y | | ssa.rb:53:1:56:3 | self (m7) | ssa.rb:53:1:56:3 | self | ssa.rb:55:3:55:8 | self | | ssa.rb:53:8:53:10 | foo | ssa.rb:53:8:53:10 | foo | ssa.rb:54:7:54:9 | foo | -| ssa.rb:54:3:54:11 | ... = ... | ssa.rb:54:3:54:3 | x | ssa.rb:55:8:55:8 | x | +| ssa.rb:54:3:54:3 | x | ssa.rb:54:3:54:3 | x | ssa.rb:55:8:55:8 | x | | ssa.rb:58:1:62:3 | self (m8) | ssa.rb:58:1:62:3 | self | ssa.rb:61:3:61:8 | self | -| ssa.rb:59:3:59:8 | ... = ... | ssa.rb:59:3:59:3 | x | ssa.rb:60:3:60:3 | x | -| ssa.rb:60:3:60:9 | ... = ... | ssa.rb:59:3:59:3 | x | ssa.rb:61:8:61:8 | x | +| ssa.rb:59:3:59:3 | x | ssa.rb:59:3:59:3 | x | ssa.rb:60:3:60:3 | x | +| ssa.rb:60:3:60:3 | x | ssa.rb:59:3:59:3 | x | ssa.rb:61:8:61:8 | x | | ssa.rb:64:1:72:3 | self (m9) | ssa.rb:64:1:72:3 | self | ssa.rb:71:3:71:15 | self | | ssa.rb:64:8:64:8 | a | ssa.rb:64:8:64:8 | a | ssa.rb:66:3:66:3 | a | | ssa.rb:66:3:70:5 | <captured exit> captured | ssa.rb:65:3:65:10 | captured | ssa.rb:71:8:71:15 | captured | @@ -362,10 +362,10 @@ read | ssa.rb:90:13:90:14 | b2 | ssa.rb:90:13:90:14 | b2 | ssa.rb:94:10:94:11 | b2 | | ssa.rb:90:17:90:18 | b3 | ssa.rb:90:17:90:18 | b3 | ssa.rb:98:7:98:8 | b3 | | ssa.rb:90:21:90:22 | b4 | ssa.rb:90:21:90:22 | b4 | ssa.rb:100:10:100:11 | b4 | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:99:10:99:10 | x | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:101:10:101:10 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:99:10:99:10 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:101:10:101:10 | x | firstRead | class_variables.rb:1:1:29:4 | self (class_variables.rb) | class_variables.rb:1:1:29:4 | self | class_variables.rb:3:1:3:5 | self | | class_variables.rb:5:1:7:3 | self (print) | class_variables.rb:5:1:7:3 | self | class_variables.rb:6:2:6:6 | self | @@ -387,28 +387,28 @@ firstRead | instance_variables.rb:38:4:40:6 | self (y) | instance_variables.rb:38:4:40:6 | self | instance_variables.rb:39:6:39:7 | self | | nested_scopes.rb:1:1:3:3 | self (a) | nested_scopes.rb:1:1:3:3 | self | nested_scopes.rb:2:3:2:17 | self | | nested_scopes.rb:4:1:39:3 | self (C) | nested_scopes.rb:4:1:39:3 | self | nested_scopes.rb:38:3:38:8 | self | -| nested_scopes.rb:5:3:5:7 | ... = ... | nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:38:8:38:8 | a | +| nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:38:8:38:8 | a | | nested_scopes.rb:6:3:37:5 | self (M) | nested_scopes.rb:6:3:37:5 | self | nested_scopes.rb:36:5:36:10 | self | -| nested_scopes.rb:7:5:7:9 | ... = ... | nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:36:10:36:10 | a | +| nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:36:10:36:10 | a | | nested_scopes.rb:8:5:35:7 | self (N) | nested_scopes.rb:8:5:35:7 | self | nested_scopes.rb:27:11:27:14 | self | -| nested_scopes.rb:9:7:9:11 | ... = ... | nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:34:12:34:12 | a | +| nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:34:12:34:12 | a | | nested_scopes.rb:10:7:26:9 | self (D) | nested_scopes.rb:10:7:26:9 | self | nested_scopes.rb:25:9:25:14 | self | -| nested_scopes.rb:11:9:11:13 | ... = ... | nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:25:14:25:14 | a | +| nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:25:14:25:14 | a | | nested_scopes.rb:12:9:21:11 | self (show_a) | nested_scopes.rb:12:9:21:11 | self | nested_scopes.rb:14:11:14:16 | self | -| nested_scopes.rb:13:11:13:15 | ... = ... | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:14:16:14:16 | a | +| nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:14:16:14:16 | a | | nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:16:13:16:13 | a | -| nested_scopes.rb:17:15:17:19 | ... = ... | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:18:15:18:15 | a | +| nested_scopes.rb:17:15:17:15 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:18:15:18:15 | a | | nested_scopes.rb:18:23:18:36 | <captured entry> a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:18:34:18:34 | a | | nested_scopes.rb:18:23:18:36 | <captured entry> self | nested_scopes.rb:12:9:21:11 | self | nested_scopes.rb:18:29:18:34 | self | | nested_scopes.rb:22:9:24:11 | self (show_a2) | nested_scopes.rb:22:9:24:11 | self | nested_scopes.rb:23:11:23:16 | self | | nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:23:16:23:16 | a | | nested_scopes.rb:27:7:29:9 | self (show) | nested_scopes.rb:27:7:29:9 | self | nested_scopes.rb:28:11:28:16 | self | | nested_scopes.rb:30:16:30:19 | self (class << ...) | nested_scopes.rb:30:7:33:9 | self | nested_scopes.rb:32:11:32:16 | self | -| nested_scopes.rb:31:11:31:16 | ... = ... | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:32:16:32:16 | a | -| nested_scopes.rb:40:1:40:18 | ... = ... | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:41:1:41:1 | d | +| nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:32:16:32:16 | a | +| nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:41:1:41:1 | d | | parameters.rb:1:9:5:3 | <captured entry> self | parameters.rb:1:1:62:1 | self | parameters.rb:3:4:3:9 | self | | parameters.rb:1:14:1:14 | x | parameters.rb:1:14:1:14 | x | parameters.rb:3:9:3:9 | x | -| parameters.rb:2:4:2:8 | ... = ... | parameters.rb:1:18:1:18 | y | parameters.rb:4:9:4:9 | y | +| parameters.rb:2:4:2:4 | y | parameters.rb:1:18:1:18 | y | parameters.rb:4:9:4:9 | y | | parameters.rb:7:1:13:3 | self (order_pizza) | parameters.rb:7:1:13:3 | self | parameters.rb:9:5:9:33 | self | | parameters.rb:7:1:13:3 | self (order_pizza) | parameters.rb:7:1:13:3 | self | parameters.rb:11:5:11:49 | self | | parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | parameters.rb:9:25:9:30 | client | @@ -447,39 +447,39 @@ firstRead | parameters.rb:59:25:59:25 | c | parameters.rb:59:25:59:25 | c | parameters.rb:60:21:60:21 | c | | scopes.rb:1:1:49:4 | self (scopes.rb) | scopes.rb:1:1:49:4 | self | scopes.rb:8:1:8:6 | self | | scopes.rb:2:9:6:3 | <captured entry> self | scopes.rb:1:1:49:4 | self | scopes.rb:3:4:3:9 | self | -| scopes.rb:4:4:4:8 | ... = ... | scopes.rb:4:4:4:4 | a | scopes.rb:5:9:5:9 | a | -| scopes.rb:7:1:7:5 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:8:6:8:6 | a | +| scopes.rb:4:4:4:4 | a | scopes.rb:4:4:4:4 | a | scopes.rb:5:9:5:9 | a | +| scopes.rb:7:1:7:1 | a | scopes.rb:7:1:7:1 | a | scopes.rb:8:6:8:6 | a | | scopes.rb:9:9:18:3 | <captured entry> a | scopes.rb:7:1:7:1 | a | scopes.rb:10:9:10:9 | a | | scopes.rb:9:9:18:3 | <captured entry> self | scopes.rb:1:1:49:4 | self | scopes.rb:10:4:10:9 | self | -| scopes.rb:11:4:11:9 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:12:9:12:9 | a | -| scopes.rb:13:4:13:4 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:14:9:14:9 | a | -| scopes.rb:13:7:13:7 | ... = ... | scopes.rb:13:7:13:7 | b | scopes.rb:15:9:15:9 | b | -| scopes.rb:13:10:13:15 | ... = ... | scopes.rb:13:10:13:15 | __synth__0__1 | scopes.rb:13:11:13:11 | __synth__0__1 | -| scopes.rb:13:11:13:11 | ... = ... | scopes.rb:13:11:13:11 | c | scopes.rb:16:9:16:9 | c | -| scopes.rb:13:14:13:14 | ... = ... | scopes.rb:13:14:13:14 | d | scopes.rb:17:9:17:9 | d | -| scopes.rb:13:19:13:32 | ... = ... | scopes.rb:13:4:13:32 | __synth__0 | scopes.rb:13:4:13:4 | __synth__0 | -| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:28:8:28:8 | x | +| scopes.rb:11:4:11:4 | a | scopes.rb:7:1:7:1 | a | scopes.rb:12:9:12:9 | a | +| scopes.rb:13:4:13:4 | a | scopes.rb:7:1:7:1 | a | scopes.rb:14:9:14:9 | a | +| scopes.rb:13:7:13:7 | b | scopes.rb:13:7:13:7 | b | scopes.rb:15:9:15:9 | b | +| scopes.rb:13:10:13:15 | __synth__2__1 | scopes.rb:13:10:13:15 | __synth__2__1 | scopes.rb:13:11:13:11 | __synth__2__1 | +| scopes.rb:13:11:13:11 | c | scopes.rb:13:11:13:11 | c | scopes.rb:16:9:16:9 | c | +| scopes.rb:13:14:13:14 | d | scopes.rb:13:14:13:14 | d | scopes.rb:17:9:17:9 | d | +| scopes.rb:13:19:13:32 | __synth__3 | scopes.rb:13:4:13:32 | __synth__3 | scopes.rb:13:4:13:4 | __synth__3 | +| scopes.rb:27:1:27:1 | x | scopes.rb:27:1:27:1 | x | scopes.rb:28:8:28:8 | x | | scopes.rb:41:1:49:3 | self (M) | scopes.rb:41:1:49:3 | self | scopes.rb:45:5:45:7 | self | -| scopes.rb:42:2:42:9 | ... = ... | scopes.rb:42:2:42:4 | var | scopes.rb:44:5:44:7 | var | -| scopes.rb:46:5:46:13 | ... = ... | scopes.rb:46:5:46:8 | var2 | scopes.rb:47:5:47:8 | var2 | +| scopes.rb:42:2:42:4 | var | scopes.rb:42:2:42:4 | var | scopes.rb:44:5:44:7 | var | +| scopes.rb:46:5:46:8 | var2 | scopes.rb:46:5:46:8 | var2 | scopes.rb:47:5:47:8 | var2 | | ssa.rb:1:1:16:3 | self (m) | ssa.rb:1:1:16:3 | self | ssa.rb:3:3:3:8 | self | | ssa.rb:1:7:1:7 | b | ssa.rb:1:7:1:7 | b | ssa.rb:5:6:5:6 | b | -| ssa.rb:2:3:2:7 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:3:8:3:8 | i | +| ssa.rb:2:3:2:3 | i | ssa.rb:2:3:2:3 | i | ssa.rb:3:8:3:8 | i | | ssa.rb:5:3:13:5 | phi | ssa.rb:2:3:2:3 | i | ssa.rb:15:8:15:8 | i | -| ssa.rb:6:5:6:9 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:7:10:7:10 | i | -| ssa.rb:10:5:10:9 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:11:10:11:10 | i | +| ssa.rb:6:5:6:5 | i | ssa.rb:2:3:2:3 | i | ssa.rb:7:10:7:10 | i | +| ssa.rb:10:5:10:5 | i | ssa.rb:2:3:2:3 | i | ssa.rb:11:10:11:10 | i | | ssa.rb:18:1:23:3 | self (m1) | ssa.rb:18:1:23:3 | self | ssa.rb:20:5:20:10 | self | | ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:19:9:19:9 | x | | ssa.rb:25:1:30:3 | self (m2) | ssa.rb:25:1:30:3 | self | ssa.rb:29:3:29:11 | self | | ssa.rb:25:8:25:15 | elements | ssa.rb:25:8:25:15 | elements | ssa.rb:26:15:26:22 | elements | -| ssa.rb:26:3:28:5 | ... = ... | ssa.rb:26:7:26:10 | elem | ssa.rb:27:10:27:13 | elem | | ssa.rb:26:3:28:5 | <captured entry> self | ssa.rb:25:1:30:3 | self | ssa.rb:27:5:27:13 | self | | ssa.rb:26:3:28:5 | <captured exit> elem | ssa.rb:26:7:26:10 | elem | ssa.rb:29:8:29:11 | elem | | ssa.rb:26:3:28:5 | __synth__0__1 | ssa.rb:26:3:28:5 | __synth__0__1 | ssa.rb:26:3:28:5 | __synth__0__1 | +| ssa.rb:26:7:26:10 | elem | ssa.rb:26:7:26:10 | elem | ssa.rb:27:10:27:13 | elem | | ssa.rb:33:16:35:5 | <captured entry> self | ssa.rb:32:1:36:3 | self | ssa.rb:34:5:34:10 | self | | ssa.rb:33:20:33:20 | x | ssa.rb:33:20:33:20 | x | ssa.rb:34:10:34:10 | x | | ssa.rb:38:1:42:3 | self (m4) | ssa.rb:38:1:42:3 | self | ssa.rb:39:3:39:9 | self | -| ssa.rb:40:3:40:9 | ... = ... | ssa.rb:40:3:40:4 | m3 | ssa.rb:41:8:41:9 | m3 | +| ssa.rb:40:3:40:4 | m3 | ssa.rb:40:3:40:4 | m3 | ssa.rb:41:8:41:9 | m3 | | ssa.rb:44:1:47:3 | self (m5) | ssa.rb:44:1:47:3 | self | ssa.rb:46:3:46:8 | self | | ssa.rb:44:8:44:8 | b | ssa.rb:44:8:44:8 | b | ssa.rb:45:12:45:12 | b | | ssa.rb:45:3:45:12 | phi | ssa.rb:45:3:45:3 | x | ssa.rb:46:8:46:8 | x | @@ -487,10 +487,10 @@ firstRead | ssa.rb:50:3:50:8 | phi | ssa.rb:49:14:49:14 | y | ssa.rb:50:8:50:8 | y | | ssa.rb:53:1:56:3 | self (m7) | ssa.rb:53:1:56:3 | self | ssa.rb:55:3:55:8 | self | | ssa.rb:53:8:53:10 | foo | ssa.rb:53:8:53:10 | foo | ssa.rb:54:7:54:9 | foo | -| ssa.rb:54:3:54:11 | ... = ... | ssa.rb:54:3:54:3 | x | ssa.rb:55:8:55:8 | x | +| ssa.rb:54:3:54:3 | x | ssa.rb:54:3:54:3 | x | ssa.rb:55:8:55:8 | x | | ssa.rb:58:1:62:3 | self (m8) | ssa.rb:58:1:62:3 | self | ssa.rb:61:3:61:8 | self | -| ssa.rb:59:3:59:8 | ... = ... | ssa.rb:59:3:59:3 | x | ssa.rb:60:3:60:3 | x | -| ssa.rb:60:3:60:9 | ... = ... | ssa.rb:59:3:59:3 | x | ssa.rb:61:8:61:8 | x | +| ssa.rb:59:3:59:3 | x | ssa.rb:59:3:59:3 | x | ssa.rb:60:3:60:3 | x | +| ssa.rb:60:3:60:3 | x | ssa.rb:59:3:59:3 | x | ssa.rb:61:8:61:8 | x | | ssa.rb:64:1:72:3 | self (m9) | ssa.rb:64:1:72:3 | self | ssa.rb:71:3:71:15 | self | | ssa.rb:64:8:64:8 | a | ssa.rb:64:8:64:8 | a | ssa.rb:66:3:66:3 | a | | ssa.rb:66:3:70:5 | <captured exit> captured | ssa.rb:65:3:65:10 | captured | ssa.rb:71:8:71:15 | captured | @@ -512,10 +512,10 @@ firstRead | ssa.rb:90:13:90:14 | b2 | ssa.rb:90:13:90:14 | b2 | ssa.rb:94:10:94:11 | b2 | | ssa.rb:90:17:90:18 | b3 | ssa.rb:90:17:90:18 | b3 | ssa.rb:98:7:98:8 | b3 | | ssa.rb:90:21:90:22 | b4 | ssa.rb:90:21:90:22 | b4 | ssa.rb:100:10:100:11 | b4 | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:99:10:99:10 | x | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:101:10:101:10 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:99:10:99:10 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:101:10:101:10 | x | lastRead | class_variables.rb:1:1:29:4 | self (class_variables.rb) | class_variables.rb:1:1:29:4 | self | class_variables.rb:3:1:3:5 | self | | class_variables.rb:5:1:7:3 | self (print) | class_variables.rb:5:1:7:3 | self | class_variables.rb:6:2:6:6 | self | @@ -537,28 +537,28 @@ lastRead | instance_variables.rb:38:4:40:6 | self (y) | instance_variables.rb:38:4:40:6 | self | instance_variables.rb:39:6:39:7 | self | | nested_scopes.rb:1:1:3:3 | self (a) | nested_scopes.rb:1:1:3:3 | self | nested_scopes.rb:2:3:2:17 | self | | nested_scopes.rb:4:1:39:3 | self (C) | nested_scopes.rb:4:1:39:3 | self | nested_scopes.rb:38:3:38:8 | self | -| nested_scopes.rb:5:3:5:7 | ... = ... | nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:38:8:38:8 | a | +| nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:38:8:38:8 | a | | nested_scopes.rb:6:3:37:5 | self (M) | nested_scopes.rb:6:3:37:5 | self | nested_scopes.rb:36:5:36:10 | self | -| nested_scopes.rb:7:5:7:9 | ... = ... | nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:36:10:36:10 | a | +| nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:36:10:36:10 | a | | nested_scopes.rb:8:5:35:7 | self (N) | nested_scopes.rb:8:5:35:7 | self | nested_scopes.rb:34:7:34:12 | self | -| nested_scopes.rb:9:7:9:11 | ... = ... | nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:34:12:34:12 | a | +| nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:34:12:34:12 | a | | nested_scopes.rb:10:7:26:9 | self (D) | nested_scopes.rb:10:7:26:9 | self | nested_scopes.rb:25:9:25:14 | self | -| nested_scopes.rb:11:9:11:13 | ... = ... | nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:25:14:25:14 | a | +| nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:25:14:25:14 | a | | nested_scopes.rb:12:9:21:11 | self (show_a) | nested_scopes.rb:12:9:21:11 | self | nested_scopes.rb:14:11:14:16 | self | -| nested_scopes.rb:13:11:13:15 | ... = ... | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:15:11:15:11 | a | +| nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:15:11:15:11 | a | | nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:16:13:16:13 | a | -| nested_scopes.rb:17:15:17:19 | ... = ... | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:18:15:18:15 | a | +| nested_scopes.rb:17:15:17:15 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:18:15:18:15 | a | | nested_scopes.rb:18:23:18:36 | <captured entry> a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:18:34:18:34 | a | | nested_scopes.rb:18:23:18:36 | <captured entry> self | nested_scopes.rb:12:9:21:11 | self | nested_scopes.rb:18:29:18:34 | self | | nested_scopes.rb:22:9:24:11 | self (show_a2) | nested_scopes.rb:22:9:24:11 | self | nested_scopes.rb:23:11:23:16 | self | | nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:23:16:23:16 | a | | nested_scopes.rb:27:7:29:9 | self (show) | nested_scopes.rb:27:7:29:9 | self | nested_scopes.rb:28:16:28:16 | self | | nested_scopes.rb:30:16:30:19 | self (class << ...) | nested_scopes.rb:30:7:33:9 | self | nested_scopes.rb:32:11:32:16 | self | -| nested_scopes.rb:31:11:31:16 | ... = ... | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:32:16:32:16 | a | -| nested_scopes.rb:40:1:40:18 | ... = ... | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:41:1:41:1 | d | +| nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:32:16:32:16 | a | +| nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:41:1:41:1 | d | | parameters.rb:1:9:5:3 | <captured entry> self | parameters.rb:1:1:62:1 | self | parameters.rb:4:4:4:9 | self | | parameters.rb:1:14:1:14 | x | parameters.rb:1:14:1:14 | x | parameters.rb:3:9:3:9 | x | -| parameters.rb:2:4:2:8 | ... = ... | parameters.rb:1:18:1:18 | y | parameters.rb:4:9:4:9 | y | +| parameters.rb:2:4:2:4 | y | parameters.rb:1:18:1:18 | y | parameters.rb:4:9:4:9 | y | | parameters.rb:7:1:13:3 | self (order_pizza) | parameters.rb:7:1:13:3 | self | parameters.rb:9:5:9:33 | self | | parameters.rb:7:1:13:3 | self (order_pizza) | parameters.rb:7:1:13:3 | self | parameters.rb:11:5:11:49 | self | | parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | parameters.rb:9:25:9:30 | client | @@ -597,40 +597,40 @@ lastRead | parameters.rb:59:25:59:25 | c | parameters.rb:59:25:59:25 | c | parameters.rb:60:21:60:21 | c | | scopes.rb:1:1:49:4 | self (scopes.rb) | scopes.rb:1:1:49:4 | self | scopes.rb:8:1:8:6 | self | | scopes.rb:2:9:6:3 | <captured entry> self | scopes.rb:1:1:49:4 | self | scopes.rb:5:4:5:9 | self | -| scopes.rb:4:4:4:8 | ... = ... | scopes.rb:4:4:4:4 | a | scopes.rb:5:9:5:9 | a | -| scopes.rb:7:1:7:5 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:8:6:8:6 | a | +| scopes.rb:4:4:4:4 | a | scopes.rb:4:4:4:4 | a | scopes.rb:5:9:5:9 | a | +| scopes.rb:7:1:7:1 | a | scopes.rb:7:1:7:1 | a | scopes.rb:8:6:8:6 | a | | scopes.rb:9:9:18:3 | <captured entry> a | scopes.rb:7:1:7:1 | a | scopes.rb:11:4:11:4 | a | | scopes.rb:9:9:18:3 | <captured entry> self | scopes.rb:1:1:49:4 | self | scopes.rb:17:4:17:9 | self | -| scopes.rb:11:4:11:9 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:12:9:12:9 | a | -| scopes.rb:13:4:13:4 | ... = ... | scopes.rb:7:1:7:1 | a | scopes.rb:14:9:14:9 | a | -| scopes.rb:13:7:13:7 | ... = ... | scopes.rb:13:7:13:7 | b | scopes.rb:15:9:15:9 | b | -| scopes.rb:13:10:13:15 | ... = ... | scopes.rb:13:10:13:15 | __synth__0__1 | scopes.rb:13:14:13:14 | __synth__0__1 | -| scopes.rb:13:11:13:11 | ... = ... | scopes.rb:13:11:13:11 | c | scopes.rb:16:9:16:9 | c | -| scopes.rb:13:14:13:14 | ... = ... | scopes.rb:13:14:13:14 | d | scopes.rb:17:9:17:9 | d | -| scopes.rb:13:19:13:32 | ... = ... | scopes.rb:13:4:13:32 | __synth__0 | scopes.rb:13:10:13:15 | __synth__0 | -| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:37:5:37:5 | x | +| scopes.rb:11:4:11:4 | a | scopes.rb:7:1:7:1 | a | scopes.rb:12:9:12:9 | a | +| scopes.rb:13:4:13:4 | a | scopes.rb:7:1:7:1 | a | scopes.rb:14:9:14:9 | a | +| scopes.rb:13:7:13:7 | b | scopes.rb:13:7:13:7 | b | scopes.rb:15:9:15:9 | b | +| scopes.rb:13:10:13:15 | __synth__2__1 | scopes.rb:13:10:13:15 | __synth__2__1 | scopes.rb:13:14:13:14 | __synth__2__1 | +| scopes.rb:13:11:13:11 | c | scopes.rb:13:11:13:11 | c | scopes.rb:16:9:16:9 | c | +| scopes.rb:13:14:13:14 | d | scopes.rb:13:14:13:14 | d | scopes.rb:17:9:17:9 | d | +| scopes.rb:13:19:13:32 | __synth__3 | scopes.rb:13:4:13:32 | __synth__3 | scopes.rb:13:10:13:15 | __synth__3 | +| scopes.rb:27:1:27:1 | x | scopes.rb:27:1:27:1 | x | scopes.rb:37:5:37:5 | x | | scopes.rb:41:1:49:3 | self (M) | scopes.rb:41:1:49:3 | self | scopes.rb:45:5:45:7 | self | -| scopes.rb:42:2:42:9 | ... = ... | scopes.rb:42:2:42:4 | var | scopes.rb:44:5:44:7 | var | -| scopes.rb:46:5:46:13 | ... = ... | scopes.rb:46:5:46:8 | var2 | scopes.rb:47:5:47:8 | var2 | +| scopes.rb:42:2:42:4 | var | scopes.rb:42:2:42:4 | var | scopes.rb:44:5:44:7 | var | +| scopes.rb:46:5:46:8 | var2 | scopes.rb:46:5:46:8 | var2 | scopes.rb:47:5:47:8 | var2 | | ssa.rb:1:1:16:3 | self (m) | ssa.rb:1:1:16:3 | self | ssa.rb:15:3:15:8 | self | | ssa.rb:1:7:1:7 | b | ssa.rb:1:7:1:7 | b | ssa.rb:5:6:5:6 | b | -| ssa.rb:2:3:2:7 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:4:8:4:8 | i | +| ssa.rb:2:3:2:3 | i | ssa.rb:2:3:2:3 | i | ssa.rb:4:8:4:8 | i | | ssa.rb:5:3:13:5 | phi | ssa.rb:2:3:2:3 | i | ssa.rb:15:8:15:8 | i | -| ssa.rb:6:5:6:9 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:8:10:8:10 | i | -| ssa.rb:10:5:10:9 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:12:10:12:10 | i | +| ssa.rb:6:5:6:5 | i | ssa.rb:2:3:2:3 | i | ssa.rb:8:10:8:10 | i | +| ssa.rb:10:5:10:5 | i | ssa.rb:2:3:2:3 | i | ssa.rb:12:10:12:10 | i | | ssa.rb:18:1:23:3 | self (m1) | ssa.rb:18:1:23:3 | self | ssa.rb:20:5:20:10 | self | | ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:19:9:19:9 | x | | ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:21:5:21:5 | x | | ssa.rb:25:1:30:3 | self (m2) | ssa.rb:25:1:30:3 | self | ssa.rb:29:3:29:11 | self | | ssa.rb:25:8:25:15 | elements | ssa.rb:25:8:25:15 | elements | ssa.rb:26:15:26:22 | elements | -| ssa.rb:26:3:28:5 | ... = ... | ssa.rb:26:7:26:10 | elem | ssa.rb:27:10:27:13 | elem | | ssa.rb:26:3:28:5 | <captured entry> self | ssa.rb:25:1:30:3 | self | ssa.rb:27:5:27:13 | self | | ssa.rb:26:3:28:5 | <captured exit> elem | ssa.rb:26:7:26:10 | elem | ssa.rb:29:8:29:11 | elem | | ssa.rb:26:3:28:5 | __synth__0__1 | ssa.rb:26:3:28:5 | __synth__0__1 | ssa.rb:26:3:28:5 | __synth__0__1 | +| ssa.rb:26:7:26:10 | elem | ssa.rb:26:7:26:10 | elem | ssa.rb:27:10:27:13 | elem | | ssa.rb:33:16:35:5 | <captured entry> self | ssa.rb:32:1:36:3 | self | ssa.rb:34:5:34:10 | self | | ssa.rb:33:20:33:20 | x | ssa.rb:33:20:33:20 | x | ssa.rb:34:10:34:10 | x | | ssa.rb:38:1:42:3 | self (m4) | ssa.rb:38:1:42:3 | self | ssa.rb:41:3:41:13 | self | -| ssa.rb:40:3:40:9 | ... = ... | ssa.rb:40:3:40:4 | m3 | ssa.rb:41:8:41:9 | m3 | +| ssa.rb:40:3:40:4 | m3 | ssa.rb:40:3:40:4 | m3 | ssa.rb:41:8:41:9 | m3 | | ssa.rb:44:1:47:3 | self (m5) | ssa.rb:44:1:47:3 | self | ssa.rb:46:3:46:8 | self | | ssa.rb:44:8:44:8 | b | ssa.rb:44:8:44:8 | b | ssa.rb:45:12:45:12 | b | | ssa.rb:45:3:45:12 | phi | ssa.rb:45:3:45:3 | x | ssa.rb:46:8:46:8 | x | @@ -638,10 +638,10 @@ lastRead | ssa.rb:50:3:50:8 | phi | ssa.rb:49:14:49:14 | y | ssa.rb:50:8:50:8 | y | | ssa.rb:53:1:56:3 | self (m7) | ssa.rb:53:1:56:3 | self | ssa.rb:55:3:55:8 | self | | ssa.rb:53:8:53:10 | foo | ssa.rb:53:8:53:10 | foo | ssa.rb:54:7:54:9 | foo | -| ssa.rb:54:3:54:11 | ... = ... | ssa.rb:54:3:54:3 | x | ssa.rb:55:8:55:8 | x | +| ssa.rb:54:3:54:3 | x | ssa.rb:54:3:54:3 | x | ssa.rb:55:8:55:8 | x | | ssa.rb:58:1:62:3 | self (m8) | ssa.rb:58:1:62:3 | self | ssa.rb:61:3:61:8 | self | -| ssa.rb:59:3:59:8 | ... = ... | ssa.rb:59:3:59:3 | x | ssa.rb:60:3:60:3 | x | -| ssa.rb:60:3:60:9 | ... = ... | ssa.rb:59:3:59:3 | x | ssa.rb:61:8:61:8 | x | +| ssa.rb:59:3:59:3 | x | ssa.rb:59:3:59:3 | x | ssa.rb:60:3:60:3 | x | +| ssa.rb:60:3:60:3 | x | ssa.rb:59:3:59:3 | x | ssa.rb:61:8:61:8 | x | | ssa.rb:64:1:72:3 | self (m9) | ssa.rb:64:1:72:3 | self | ssa.rb:71:3:71:15 | self | | ssa.rb:64:8:64:8 | a | ssa.rb:64:8:64:8 | a | ssa.rb:66:3:66:3 | a | | ssa.rb:66:3:70:5 | <captured exit> captured | ssa.rb:65:3:65:10 | captured | ssa.rb:71:8:71:15 | captured | @@ -663,10 +663,10 @@ lastRead | ssa.rb:90:13:90:14 | b2 | ssa.rb:90:13:90:14 | b2 | ssa.rb:94:10:94:11 | b2 | | ssa.rb:90:17:90:18 | b3 | ssa.rb:90:17:90:18 | b3 | ssa.rb:98:7:98:8 | b3 | | ssa.rb:90:21:90:22 | b4 | ssa.rb:90:21:90:22 | b4 | ssa.rb:100:10:100:11 | b4 | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:99:10:99:10 | x | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:101:10:101:10 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:99:10:99:10 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:101:10:101:10 | x | adjacentReads | class_variables.rb:26:1:29:3 | self (N) | class_variables.rb:26:1:29:3 | self | class_variables.rb:27:3:27:11 | self | class_variables.rb:28:3:28:7 | self | | instance_variables.rb:1:1:44:4 | self (instance_variables.rb) | instance_variables.rb:1:1:44:4 | self | instance_variables.rb:1:1:1:4 | self | instance_variables.rb:11:1:11:9 | self | @@ -677,7 +677,7 @@ adjacentReads | instance_variables.rb:37:3:43:5 | self (x) | instance_variables.rb:37:3:43:5 | self | instance_variables.rb:42:4:42:7 | self | instance_variables.rb:42:6:42:7 | self | | nested_scopes.rb:8:5:35:7 | self (N) | nested_scopes.rb:8:5:35:7 | self | nested_scopes.rb:27:11:27:14 | self | nested_scopes.rb:30:16:30:19 | self | | nested_scopes.rb:8:5:35:7 | self (N) | nested_scopes.rb:8:5:35:7 | self | nested_scopes.rb:30:16:30:19 | self | nested_scopes.rb:34:7:34:12 | self | -| nested_scopes.rb:13:11:13:15 | ... = ... | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:14:16:14:16 | a | nested_scopes.rb:15:11:15:11 | a | +| nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:14:16:14:16 | a | nested_scopes.rb:15:11:15:11 | a | | nested_scopes.rb:27:7:29:9 | self (show) | nested_scopes.rb:27:7:29:9 | self | nested_scopes.rb:28:11:28:16 | self | nested_scopes.rb:28:16:28:16 | self | | nested_scopes.rb:30:16:30:19 | self (class << ...) | nested_scopes.rb:30:7:33:9 | self | nested_scopes.rb:30:16:30:19 | self | nested_scopes.rb:32:11:32:16 | self | | parameters.rb:1:9:5:3 | <captured entry> self | parameters.rb:1:1:62:1 | self | parameters.rb:3:4:3:9 | self | parameters.rb:4:4:4:9 | self | @@ -693,13 +693,13 @@ adjacentReads | scopes.rb:9:9:18:3 | <captured entry> self | scopes.rb:1:1:49:4 | self | scopes.rb:14:4:14:9 | self | scopes.rb:15:4:15:9 | self | | scopes.rb:9:9:18:3 | <captured entry> self | scopes.rb:1:1:49:4 | self | scopes.rb:15:4:15:9 | self | scopes.rb:16:4:16:9 | self | | scopes.rb:9:9:18:3 | <captured entry> self | scopes.rb:1:1:49:4 | self | scopes.rb:16:4:16:9 | self | scopes.rb:17:4:17:9 | self | -| scopes.rb:13:10:13:15 | ... = ... | scopes.rb:13:10:13:15 | __synth__0__1 | scopes.rb:13:11:13:11 | __synth__0__1 | scopes.rb:13:14:13:14 | __synth__0__1 | -| scopes.rb:13:19:13:32 | ... = ... | scopes.rb:13:4:13:32 | __synth__0 | scopes.rb:13:4:13:4 | __synth__0 | scopes.rb:13:7:13:7 | __synth__0 | -| scopes.rb:13:19:13:32 | ... = ... | scopes.rb:13:4:13:32 | __synth__0 | scopes.rb:13:7:13:7 | __synth__0 | scopes.rb:13:10:13:15 | __synth__0 | -| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:28:8:28:8 | x | scopes.rb:31:10:31:10 | x | -| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:31:10:31:10 | x | scopes.rb:34:7:34:7 | x | -| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:34:7:34:7 | x | scopes.rb:34:14:34:14 | x | -| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:34:14:34:14 | x | scopes.rb:37:5:37:5 | x | +| scopes.rb:13:10:13:15 | __synth__2__1 | scopes.rb:13:10:13:15 | __synth__2__1 | scopes.rb:13:11:13:11 | __synth__2__1 | scopes.rb:13:14:13:14 | __synth__2__1 | +| scopes.rb:13:19:13:32 | __synth__3 | scopes.rb:13:4:13:32 | __synth__3 | scopes.rb:13:4:13:4 | __synth__3 | scopes.rb:13:7:13:7 | __synth__3 | +| scopes.rb:13:19:13:32 | __synth__3 | scopes.rb:13:4:13:32 | __synth__3 | scopes.rb:13:7:13:7 | __synth__3 | scopes.rb:13:10:13:15 | __synth__3 | +| scopes.rb:27:1:27:1 | x | scopes.rb:27:1:27:1 | x | scopes.rb:28:8:28:8 | x | scopes.rb:31:10:31:10 | x | +| scopes.rb:27:1:27:1 | x | scopes.rb:27:1:27:1 | x | scopes.rb:31:10:31:10 | x | scopes.rb:34:7:34:7 | x | +| scopes.rb:27:1:27:1 | x | scopes.rb:27:1:27:1 | x | scopes.rb:34:7:34:7 | x | scopes.rb:34:14:34:14 | x | +| scopes.rb:27:1:27:1 | x | scopes.rb:27:1:27:1 | x | scopes.rb:34:14:34:14 | x | scopes.rb:37:5:37:5 | x | | ssa.rb:1:1:16:3 | self (m) | ssa.rb:1:1:16:3 | self | ssa.rb:3:3:3:8 | self | ssa.rb:4:3:4:12 | self | | ssa.rb:1:1:16:3 | self (m) | ssa.rb:1:1:16:3 | self | ssa.rb:4:3:4:12 | self | ssa.rb:7:5:7:10 | self | | ssa.rb:1:1:16:3 | self (m) | ssa.rb:1:1:16:3 | self | ssa.rb:4:3:4:12 | self | ssa.rb:11:5:11:10 | self | @@ -707,9 +707,9 @@ adjacentReads | ssa.rb:1:1:16:3 | self (m) | ssa.rb:1:1:16:3 | self | ssa.rb:8:5:8:14 | self | ssa.rb:15:3:15:8 | self | | ssa.rb:1:1:16:3 | self (m) | ssa.rb:1:1:16:3 | self | ssa.rb:11:5:11:10 | self | ssa.rb:12:5:12:14 | self | | ssa.rb:1:1:16:3 | self (m) | ssa.rb:1:1:16:3 | self | ssa.rb:12:5:12:14 | self | ssa.rb:15:3:15:8 | self | -| ssa.rb:2:3:2:7 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:3:8:3:8 | i | ssa.rb:4:8:4:8 | i | -| ssa.rb:6:5:6:9 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:7:10:7:10 | i | ssa.rb:8:10:8:10 | i | -| ssa.rb:10:5:10:9 | ... = ... | ssa.rb:2:3:2:3 | i | ssa.rb:11:10:11:10 | i | ssa.rb:12:10:12:10 | i | +| ssa.rb:2:3:2:3 | i | ssa.rb:2:3:2:3 | i | ssa.rb:3:8:3:8 | i | ssa.rb:4:8:4:8 | i | +| ssa.rb:6:5:6:5 | i | ssa.rb:2:3:2:3 | i | ssa.rb:7:10:7:10 | i | ssa.rb:8:10:8:10 | i | +| ssa.rb:10:5:10:5 | i | ssa.rb:2:3:2:3 | i | ssa.rb:11:10:11:10 | i | ssa.rb:12:10:12:10 | i | | ssa.rb:18:1:23:3 | self (m1) | ssa.rb:18:1:23:3 | self | ssa.rb:20:5:20:10 | self | ssa.rb:20:5:20:10 | self | | ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:19:9:19:9 | x | ssa.rb:20:10:20:10 | x | | ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:20:10:20:10 | x | ssa.rb:21:5:21:5 | x | @@ -721,25 +721,25 @@ adjacentReads | ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:93:5:93:10 | self | ssa.rb:101:5:101:10 | self | | ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:95:5:95:10 | self | ssa.rb:99:5:99:10 | self | | ssa.rb:90:1:103:3 | self (m12) | ssa.rb:90:1:103:3 | self | ssa.rb:95:5:95:10 | self | ssa.rb:101:5:101:10 | self | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x | ssa.rb:99:10:99:10 | x | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x | ssa.rb:101:10:101:10 | x | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x | ssa.rb:99:10:99:10 | x | -| ssa.rb:91:3:91:7 | ... = ... | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x | ssa.rb:101:10:101:10 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x | ssa.rb:99:10:99:10 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:93:10:93:10 | x | ssa.rb:101:10:101:10 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x | ssa.rb:99:10:99:10 | x | +| ssa.rb:91:3:91:3 | x | ssa.rb:91:3:91:3 | x | ssa.rb:95:10:95:10 | x | ssa.rb:101:10:101:10 | x | phi | parameters.rb:37:3:37:18 | phi | parameters.rb:35:16:35:16 | b | parameters.rb:35:1:38:3 | <uninitialized> | -| parameters.rb:37:3:37:18 | phi | parameters.rb:35:16:35:16 | b | parameters.rb:35:16:35:20 | ... = ... | +| parameters.rb:37:3:37:18 | phi | parameters.rb:35:16:35:16 | b | parameters.rb:35:16:35:16 | b | | parameters.rb:42:3:42:18 | phi | parameters.rb:40:15:40:15 | e | parameters.rb:40:1:43:3 | <uninitialized> | -| parameters.rb:42:3:42:18 | phi | parameters.rb:40:15:40:15 | e | parameters.rb:40:15:40:19 | ... = ... | +| parameters.rb:42:3:42:18 | phi | parameters.rb:40:15:40:15 | e | parameters.rb:40:15:40:15 | e | | parameters.rb:55:4:55:9 | phi | parameters.rb:53:1:53:1 | x | parameters.rb:54:9:57:3 | <captured entry> x | -| parameters.rb:55:4:55:9 | phi | parameters.rb:53:1:53:1 | x | parameters.rb:54:19:54:23 | ... = ... | -| ssa.rb:5:3:13:5 | phi | ssa.rb:2:3:2:3 | i | ssa.rb:6:5:6:9 | ... = ... | -| ssa.rb:5:3:13:5 | phi | ssa.rb:2:3:2:3 | i | ssa.rb:10:5:10:9 | ... = ... | +| parameters.rb:55:4:55:9 | phi | parameters.rb:53:1:53:1 | x | parameters.rb:54:19:54:19 | x | +| ssa.rb:5:3:13:5 | phi | ssa.rb:2:3:2:3 | i | ssa.rb:6:5:6:5 | i | +| ssa.rb:5:3:13:5 | phi | ssa.rb:2:3:2:3 | i | ssa.rb:10:5:10:5 | i | | ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:18:8:18:8 | x | -| ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:21:5:21:10 | ... = ... | +| ssa.rb:19:9:19:9 | phi | ssa.rb:18:8:18:8 | x | ssa.rb:21:5:21:5 | x | | ssa.rb:45:3:45:12 | phi | ssa.rb:45:3:45:3 | x | ssa.rb:44:1:47:3 | <uninitialized> | -| ssa.rb:45:3:45:12 | phi | ssa.rb:45:3:45:3 | x | ssa.rb:45:3:45:7 | ... = ... | +| ssa.rb:45:3:45:12 | phi | ssa.rb:45:3:45:3 | x | ssa.rb:45:3:45:3 | x | | ssa.rb:50:3:50:8 | phi | ssa.rb:49:14:49:14 | y | ssa.rb:49:1:51:3 | <uninitialized> | -| ssa.rb:50:3:50:8 | phi | ssa.rb:49:14:49:14 | y | ssa.rb:49:14:49:19 | ... = ... | +| ssa.rb:50:3:50:8 | phi | ssa.rb:49:14:49:14 | y | ssa.rb:49:14:49:14 | y | phiReadNode | parameters.rb:26:3:26:11 | SSA phi read(name) | parameters.rb:25:15:25:18 | name | | ssa.rb:5:3:13:5 | SSA phi read(self) | ssa.rb:1:1:16:3 | self | @@ -763,7 +763,7 @@ phiReadInput | ssa.rb:19:9:19:9 | SSA phi read(self) | ssa.rb:19:9:19:9 | SSA phi read(self) | | ssa.rb:92:3:96:5 | SSA phi read(self) | ssa.rb:90:1:103:3 | self (m12) | | ssa.rb:92:3:96:5 | SSA phi read(self) | ssa.rb:94:3:95:10 | SSA phi read(self) | -| ssa.rb:92:3:96:5 | SSA phi read(x) | ssa.rb:91:3:91:7 | ... = ... | +| ssa.rb:92:3:96:5 | SSA phi read(x) | ssa.rb:91:3:91:3 | x | | ssa.rb:92:3:96:5 | SSA phi read(x) | ssa.rb:94:3:95:10 | SSA phi read(x) | | ssa.rb:94:3:95:10 | SSA phi read(self) | ssa.rb:90:1:103:3 | self (m12) | -| ssa.rb:94:3:95:10 | SSA phi read(x) | ssa.rb:91:3:91:7 | ... = ... | +| ssa.rb:94:3:95:10 | SSA phi read(x) | ssa.rb:91:3:91:3 | x | diff --git a/ruby/ql/test/library-tests/variables/varaccess.expected b/ruby/ql/test/library-tests/variables/varaccess.expected index 4443373e8c2..82bc6c8cd58 100644 --- a/ruby/ql/test/library-tests/variables/varaccess.expected +++ b/ruby/ql/test/library-tests/variables/varaccess.expected @@ -332,12 +332,12 @@ explicitWrite | scopes.rb:13:4:13:4 | a | scopes.rb:13:4:13:32 | ... = ... | | scopes.rb:13:7:13:7 | b | scopes.rb:13:4:13:32 | ... = ... | | scopes.rb:13:7:13:7 | b | scopes.rb:13:7:13:7 | ... = ... | -| scopes.rb:13:10:13:15 | __synth__0__1 | scopes.rb:13:10:13:15 | ... = ... | +| scopes.rb:13:10:13:15 | __synth__2__1 | scopes.rb:13:10:13:15 | ... = ... | | scopes.rb:13:11:13:11 | c | scopes.rb:13:4:13:32 | ... = ... | | scopes.rb:13:11:13:11 | c | scopes.rb:13:11:13:11 | ... = ... | | scopes.rb:13:14:13:14 | d | scopes.rb:13:4:13:32 | ... = ... | | scopes.rb:13:14:13:14 | d | scopes.rb:13:14:13:14 | ... = ... | -| scopes.rb:13:19:13:32 | __synth__0 | scopes.rb:13:19:13:32 | ... = ... | +| scopes.rb:13:19:13:32 | __synth__3 | scopes.rb:13:19:13:32 | ... = ... | | scopes.rb:21:1:21:7 | $global | scopes.rb:21:1:21:12 | ... = ... | | scopes.rb:24:1:24:6 | script | scopes.rb:24:1:24:11 | ... = ... | | scopes.rb:27:1:27:1 | x | scopes.rb:27:1:27:5 | ... = ... | @@ -525,11 +525,11 @@ readAccess | scopes.rb:11:4:11:4 | a | | scopes.rb:12:4:12:9 | self | | scopes.rb:12:9:12:9 | a | -| scopes.rb:13:4:13:4 | __synth__0 | -| scopes.rb:13:7:13:7 | __synth__0 | -| scopes.rb:13:10:13:15 | __synth__0 | -| scopes.rb:13:11:13:11 | __synth__0__1 | -| scopes.rb:13:14:13:14 | __synth__0__1 | +| scopes.rb:13:4:13:4 | __synth__3 | +| scopes.rb:13:7:13:7 | __synth__3 | +| scopes.rb:13:10:13:15 | __synth__3 | +| scopes.rb:13:11:13:11 | __synth__2__1 | +| scopes.rb:13:14:13:14 | __synth__2__1 | | scopes.rb:14:4:14:9 | self | | scopes.rb:14:9:14:9 | a | | scopes.rb:15:4:15:9 | self | diff --git a/ruby/ql/test/library-tests/variables/variable.expected b/ruby/ql/test/library-tests/variables/variable.expected index ccab8a3cdf4..55288f74088 100644 --- a/ruby/ql/test/library-tests/variables/variable.expected +++ b/ruby/ql/test/library-tests/variables/variable.expected @@ -100,8 +100,13 @@ | scopes.rb:7:1:7:1 | a | | scopes.rb:9:14:9:14 | x | | scopes.rb:13:4:13:32 | __synth__0 | +| scopes.rb:13:4:13:32 | __synth__1 | +| scopes.rb:13:4:13:32 | __synth__2 | +| scopes.rb:13:4:13:32 | __synth__3 | | scopes.rb:13:7:13:7 | b | | scopes.rb:13:10:13:15 | __synth__0__1 | +| scopes.rb:13:10:13:15 | __synth__1__1 | +| scopes.rb:13:10:13:15 | __synth__2__1 | | scopes.rb:13:11:13:11 | c | | scopes.rb:13:14:13:14 | d | | scopes.rb:24:1:24:6 | script | diff --git a/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected b/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected index 7f7e0a5bbe4..a3e20d71b20 100644 --- a/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected +++ b/ruby/ql/test/query-tests/experimental/TemplateInjection/TemplateInjection.expected @@ -1,30 +1,36 @@ edges +| ErbInjection.rb:5:5:5:8 | name : | ErbInjection.rb:8:5:8:12 | bad_text : | +| ErbInjection.rb:5:5:5:8 | name : | ErbInjection.rb:11:11:11:14 | name : | | ErbInjection.rb:5:12:5:17 | call to params : | ErbInjection.rb:5:12:5:24 | ...[...] : | -| ErbInjection.rb:5:12:5:24 | ...[...] : | ErbInjection.rb:11:11:11:14 | name : | -| ErbInjection.rb:5:12:5:24 | ...[...] : | ErbInjection.rb:15:24:15:31 | bad_text | -| ErbInjection.rb:8:16:11:14 | ... % ... : | ErbInjection.rb:15:24:15:31 | bad_text | +| ErbInjection.rb:5:12:5:24 | ...[...] : | ErbInjection.rb:5:5:5:8 | name : | +| ErbInjection.rb:8:5:8:12 | bad_text : | ErbInjection.rb:15:24:15:31 | bad_text | +| ErbInjection.rb:8:16:11:14 | ... % ... : | ErbInjection.rb:8:5:8:12 | bad_text : | | ErbInjection.rb:11:11:11:14 | name : | ErbInjection.rb:8:16:11:14 | ... % ... : | +| SlimInjection.rb:5:5:5:8 | name : | SlimInjection.rb:8:5:8:12 | bad_text : | +| SlimInjection.rb:5:5:5:8 | name : | SlimInjection.rb:11:11:11:14 | name : | +| SlimInjection.rb:5:5:5:8 | name : | SlimInjection.rb:17:5:17:13 | bad2_text : | | SlimInjection.rb:5:12:5:17 | call to params : | SlimInjection.rb:5:12:5:24 | ...[...] : | -| SlimInjection.rb:5:12:5:24 | ...[...] : | SlimInjection.rb:8:5:11:14 | ... = ... : | -| SlimInjection.rb:5:12:5:24 | ...[...] : | SlimInjection.rb:11:11:11:14 | name : | -| SlimInjection.rb:5:12:5:24 | ...[...] : | SlimInjection.rb:17:5:20:7 | ... = ... : | -| SlimInjection.rb:8:5:11:14 | ... = ... : | SlimInjection.rb:14:25:14:32 | bad_text | -| SlimInjection.rb:8:16:11:14 | ... % ... : | SlimInjection.rb:8:5:11:14 | ... = ... : | +| SlimInjection.rb:5:12:5:24 | ...[...] : | SlimInjection.rb:5:5:5:8 | name : | +| SlimInjection.rb:8:5:8:12 | bad_text : | SlimInjection.rb:14:25:14:32 | bad_text | +| SlimInjection.rb:8:16:11:14 | ... % ... : | SlimInjection.rb:8:5:8:12 | bad_text : | | SlimInjection.rb:11:11:11:14 | name : | SlimInjection.rb:8:16:11:14 | ... % ... : | -| SlimInjection.rb:17:5:20:7 | ... = ... : | SlimInjection.rb:23:25:23:33 | bad2_text | +| SlimInjection.rb:17:5:17:13 | bad2_text : | SlimInjection.rb:23:25:23:33 | bad2_text | nodes +| ErbInjection.rb:5:5:5:8 | name : | semmle.label | name : | | ErbInjection.rb:5:12:5:17 | call to params : | semmle.label | call to params : | | ErbInjection.rb:5:12:5:24 | ...[...] : | semmle.label | ...[...] : | +| ErbInjection.rb:8:5:8:12 | bad_text : | semmle.label | bad_text : | | ErbInjection.rb:8:16:11:14 | ... % ... : | semmle.label | ... % ... : | | ErbInjection.rb:11:11:11:14 | name : | semmle.label | name : | | ErbInjection.rb:15:24:15:31 | bad_text | semmle.label | bad_text | +| SlimInjection.rb:5:5:5:8 | name : | semmle.label | name : | | SlimInjection.rb:5:12:5:17 | call to params : | semmle.label | call to params : | | SlimInjection.rb:5:12:5:24 | ...[...] : | semmle.label | ...[...] : | -| SlimInjection.rb:8:5:11:14 | ... = ... : | semmle.label | ... = ... : | +| SlimInjection.rb:8:5:8:12 | bad_text : | semmle.label | bad_text : | | SlimInjection.rb:8:16:11:14 | ... % ... : | semmle.label | ... % ... : | | SlimInjection.rb:11:11:11:14 | name : | semmle.label | name : | | SlimInjection.rb:14:25:14:32 | bad_text | semmle.label | bad_text | -| SlimInjection.rb:17:5:20:7 | ... = ... : | semmle.label | ... = ... : | +| SlimInjection.rb:17:5:17:13 | bad2_text : | semmle.label | bad2_text : | | SlimInjection.rb:23:25:23:33 | bad2_text | semmle.label | bad2_text | subpaths #select diff --git a/ruby/ql/test/query-tests/experimental/cwe-022-ZipSlip/ZipSlip.expected b/ruby/ql/test/query-tests/experimental/cwe-022-ZipSlip/ZipSlip.expected index 4b7ace007ed..ca200083a96 100644 --- a/ruby/ql/test/query-tests/experimental/cwe-022-ZipSlip/ZipSlip.expected +++ b/ruby/ql/test/query-tests/experimental/cwe-022-ZipSlip/ZipSlip.expected @@ -1,5 +1,6 @@ edges -| zip_slip.rb:8:15:8:54 | call to new : | zip_slip.rb:9:5:9:11 | tarfile : | +| zip_slip.rb:8:5:8:11 | tarfile : | zip_slip.rb:9:5:9:11 | tarfile : | +| zip_slip.rb:8:15:8:54 | call to new : | zip_slip.rb:8:5:8:11 | tarfile : | | zip_slip.rb:9:5:9:11 | tarfile : | zip_slip.rb:9:22:9:26 | entry : | | zip_slip.rb:9:22:9:26 | entry : | zip_slip.rb:10:19:10:33 | call to full_name | | zip_slip.rb:20:50:20:56 | tarfile : | zip_slip.rb:21:7:21:13 | tarfile : | @@ -10,15 +11,20 @@ edges | zip_slip.rb:56:30:56:37 | zip_file : | zip_slip.rb:57:7:57:14 | zip_file : | | zip_slip.rb:57:7:57:14 | zip_file : | zip_slip.rb:57:25:57:29 | entry : | | zip_slip.rb:57:25:57:29 | entry : | zip_slip.rb:58:19:58:28 | call to name | -| zip_slip.rb:90:12:90:54 | call to open : | zip_slip.rb:91:11:91:14 | gzip : | +| zip_slip.rb:90:5:90:8 | gzip : | zip_slip.rb:91:11:91:14 | gzip : | +| zip_slip.rb:90:12:90:54 | call to open : | zip_slip.rb:90:5:90:8 | gzip : | | zip_slip.rb:91:11:91:14 | gzip : | zip_slip.rb:97:42:97:56 | compressed_file : | | zip_slip.rb:97:42:97:56 | compressed_file : | zip_slip.rb:98:7:98:21 | compressed_file : | | zip_slip.rb:98:7:98:21 | compressed_file : | zip_slip.rb:98:32:98:36 | entry : | -| zip_slip.rb:98:32:98:36 | entry : | zip_slip.rb:100:21:100:30 | entry_path | -| zip_slip.rb:123:12:123:34 | call to new : | zip_slip.rb:124:7:124:8 | gz : | +| zip_slip.rb:98:32:98:36 | entry : | zip_slip.rb:99:9:99:18 | entry_path : | +| zip_slip.rb:99:9:99:18 | entry_path : | zip_slip.rb:100:21:100:30 | entry_path | +| zip_slip.rb:123:7:123:8 | gz : | zip_slip.rb:124:7:124:8 | gz : | +| zip_slip.rb:123:12:123:34 | call to new : | zip_slip.rb:123:7:123:8 | gz : | | zip_slip.rb:124:7:124:8 | gz : | zip_slip.rb:124:19:124:23 | entry : | -| zip_slip.rb:124:19:124:23 | entry : | zip_slip.rb:126:21:126:30 | entry_path | +| zip_slip.rb:124:19:124:23 | entry : | zip_slip.rb:125:9:125:18 | entry_path : | +| zip_slip.rb:125:9:125:18 | entry_path : | zip_slip.rb:126:21:126:30 | entry_path | nodes +| zip_slip.rb:8:5:8:11 | tarfile : | semmle.label | tarfile : | | zip_slip.rb:8:15:8:54 | call to new : | semmle.label | call to new : | | zip_slip.rb:9:5:9:11 | tarfile : | semmle.label | tarfile : | | zip_slip.rb:9:22:9:26 | entry : | semmle.label | entry : | @@ -34,15 +40,19 @@ nodes | zip_slip.rb:57:7:57:14 | zip_file : | semmle.label | zip_file : | | zip_slip.rb:57:25:57:29 | entry : | semmle.label | entry : | | zip_slip.rb:58:19:58:28 | call to name | semmle.label | call to name | +| zip_slip.rb:90:5:90:8 | gzip : | semmle.label | gzip : | | zip_slip.rb:90:12:90:54 | call to open : | semmle.label | call to open : | | zip_slip.rb:91:11:91:14 | gzip : | semmle.label | gzip : | | zip_slip.rb:97:42:97:56 | compressed_file : | semmle.label | compressed_file : | | zip_slip.rb:98:7:98:21 | compressed_file : | semmle.label | compressed_file : | | zip_slip.rb:98:32:98:36 | entry : | semmle.label | entry : | +| zip_slip.rb:99:9:99:18 | entry_path : | semmle.label | entry_path : | | zip_slip.rb:100:21:100:30 | entry_path | semmle.label | entry_path | +| zip_slip.rb:123:7:123:8 | gz : | semmle.label | gz : | | zip_slip.rb:123:12:123:34 | call to new : | semmle.label | call to new : | | zip_slip.rb:124:7:124:8 | gz : | semmle.label | gz : | | zip_slip.rb:124:19:124:23 | entry : | semmle.label | entry : | +| zip_slip.rb:125:9:125:18 | entry_path : | semmle.label | entry_path : | | zip_slip.rb:126:21:126:30 | entry_path | semmle.label | entry_path | subpaths #select diff --git a/ruby/ql/test/query-tests/experimental/manually-check-http-verb/ManuallyCheckHttpVerb.expected b/ruby/ql/test/query-tests/experimental/manually-check-http-verb/ManuallyCheckHttpVerb.expected index b7dff706a1f..b43c529946f 100644 --- a/ruby/ql/test/query-tests/experimental/manually-check-http-verb/ManuallyCheckHttpVerb.expected +++ b/ruby/ql/test/query-tests/experimental/manually-check-http-verb/ManuallyCheckHttpVerb.expected @@ -1,22 +1,32 @@ edges +| ManuallyCheckHttpVerb.rb:11:5:11:10 | method : | ManuallyCheckHttpVerb.rb:12:8:12:22 | ... == ... | | ManuallyCheckHttpVerb.rb:11:14:11:24 | call to env : | ManuallyCheckHttpVerb.rb:11:14:11:42 | ...[...] : | -| ManuallyCheckHttpVerb.rb:11:14:11:42 | ...[...] : | ManuallyCheckHttpVerb.rb:12:8:12:22 | ... == ... | -| ManuallyCheckHttpVerb.rb:19:14:19:35 | call to request_method : | ManuallyCheckHttpVerb.rb:20:8:20:22 | ... == ... | -| ManuallyCheckHttpVerb.rb:27:14:27:27 | call to method : | ManuallyCheckHttpVerb.rb:28:8:28:22 | ... == ... | -| ManuallyCheckHttpVerb.rb:35:14:35:39 | call to raw_request_method : | ManuallyCheckHttpVerb.rb:36:8:36:22 | ... == ... | -| ManuallyCheckHttpVerb.rb:51:16:51:44 | call to request_method_symbol : | ManuallyCheckHttpVerb.rb:52:10:52:23 | ... == ... | +| ManuallyCheckHttpVerb.rb:11:14:11:42 | ...[...] : | ManuallyCheckHttpVerb.rb:11:5:11:10 | method : | +| ManuallyCheckHttpVerb.rb:19:5:19:10 | method : | ManuallyCheckHttpVerb.rb:20:8:20:22 | ... == ... | +| ManuallyCheckHttpVerb.rb:19:14:19:35 | call to request_method : | ManuallyCheckHttpVerb.rb:19:5:19:10 | method : | +| ManuallyCheckHttpVerb.rb:27:5:27:10 | method : | ManuallyCheckHttpVerb.rb:28:8:28:22 | ... == ... | +| ManuallyCheckHttpVerb.rb:27:14:27:27 | call to method : | ManuallyCheckHttpVerb.rb:27:5:27:10 | method : | +| ManuallyCheckHttpVerb.rb:35:5:35:10 | method : | ManuallyCheckHttpVerb.rb:36:8:36:22 | ... == ... | +| ManuallyCheckHttpVerb.rb:35:14:35:39 | call to raw_request_method : | ManuallyCheckHttpVerb.rb:35:5:35:10 | method : | +| ManuallyCheckHttpVerb.rb:51:7:51:12 | method : | ManuallyCheckHttpVerb.rb:52:10:52:23 | ... == ... | +| ManuallyCheckHttpVerb.rb:51:16:51:44 | call to request_method_symbol : | ManuallyCheckHttpVerb.rb:51:7:51:12 | method : | | ManuallyCheckHttpVerb.rb:59:10:59:20 | call to env : | ManuallyCheckHttpVerb.rb:59:10:59:38 | ...[...] | nodes | ManuallyCheckHttpVerb.rb:4:8:4:19 | call to get? | semmle.label | call to get? | +| ManuallyCheckHttpVerb.rb:11:5:11:10 | method : | semmle.label | method : | | ManuallyCheckHttpVerb.rb:11:14:11:24 | call to env : | semmle.label | call to env : | | ManuallyCheckHttpVerb.rb:11:14:11:42 | ...[...] : | semmle.label | ...[...] : | | ManuallyCheckHttpVerb.rb:12:8:12:22 | ... == ... | semmle.label | ... == ... | +| ManuallyCheckHttpVerb.rb:19:5:19:10 | method : | semmle.label | method : | | ManuallyCheckHttpVerb.rb:19:14:19:35 | call to request_method : | semmle.label | call to request_method : | | ManuallyCheckHttpVerb.rb:20:8:20:22 | ... == ... | semmle.label | ... == ... | +| ManuallyCheckHttpVerb.rb:27:5:27:10 | method : | semmle.label | method : | | ManuallyCheckHttpVerb.rb:27:14:27:27 | call to method : | semmle.label | call to method : | | ManuallyCheckHttpVerb.rb:28:8:28:22 | ... == ... | semmle.label | ... == ... | +| ManuallyCheckHttpVerb.rb:35:5:35:10 | method : | semmle.label | method : | | ManuallyCheckHttpVerb.rb:35:14:35:39 | call to raw_request_method : | semmle.label | call to raw_request_method : | | ManuallyCheckHttpVerb.rb:36:8:36:22 | ... == ... | semmle.label | ... == ... | +| ManuallyCheckHttpVerb.rb:51:7:51:12 | method : | semmle.label | method : | | ManuallyCheckHttpVerb.rb:51:16:51:44 | call to request_method_symbol : | semmle.label | call to request_method_symbol : | | ManuallyCheckHttpVerb.rb:52:10:52:23 | ... == ... | semmle.label | ... == ... | | ManuallyCheckHttpVerb.rb:59:10:59:20 | call to env : | semmle.label | call to env : | diff --git a/ruby/ql/test/query-tests/security/cwe-022/PathInjection.expected b/ruby/ql/test/query-tests/security/cwe-022/PathInjection.expected index 5e05271252e..7d5598d1d49 100644 --- a/ruby/ql/test/query-tests/security/cwe-022/PathInjection.expected +++ b/ruby/ql/test/query-tests/security/cwe-022/PathInjection.expected @@ -6,48 +6,62 @@ edges | ArchiveApiPathTraversal.rb:15:9:15:14 | call to params : | ArchiveApiPathTraversal.rb:15:9:15:25 | ...[...] : | | ArchiveApiPathTraversal.rb:15:9:15:25 | ...[...] : | ArchiveApiPathTraversal.rb:75:11:75:18 | filename : | | ArchiveApiPathTraversal.rb:49:17:49:27 | destination : | ArchiveApiPathTraversal.rb:52:38:52:48 | destination : | -| ArchiveApiPathTraversal.rb:52:28:52:67 | call to join : | ArchiveApiPathTraversal.rb:59:21:59:36 | destination_file | +| ArchiveApiPathTraversal.rb:52:9:52:24 | destination_file : | ArchiveApiPathTraversal.rb:59:21:59:36 | destination_file | +| ArchiveApiPathTraversal.rb:52:28:52:67 | call to join : | ArchiveApiPathTraversal.rb:52:9:52:24 | destination_file : | | ArchiveApiPathTraversal.rb:52:38:52:48 | destination : | ArchiveApiPathTraversal.rb:52:28:52:67 | call to join : | | ArchiveApiPathTraversal.rb:67:13:67:16 | file : | ArchiveApiPathTraversal.rb:68:20:68:23 | file | | ArchiveApiPathTraversal.rb:75:11:75:18 | filename : | ArchiveApiPathTraversal.rb:76:19:76:26 | filename | +| tainted_path.rb:4:5:4:8 | path : | tainted_path.rb:5:26:5:29 | path | | tainted_path.rb:4:12:4:17 | call to params : | tainted_path.rb:4:12:4:24 | ...[...] : | -| tainted_path.rb:4:12:4:24 | ...[...] : | tainted_path.rb:5:26:5:29 | path | -| tainted_path.rb:10:12:10:43 | call to absolute_path : | tainted_path.rb:11:26:11:29 | path | +| tainted_path.rb:4:12:4:24 | ...[...] : | tainted_path.rb:4:5:4:8 | path : | +| tainted_path.rb:10:5:10:8 | path : | tainted_path.rb:11:26:11:29 | path | +| tainted_path.rb:10:12:10:43 | call to absolute_path : | tainted_path.rb:10:5:10:8 | path : | | tainted_path.rb:10:31:10:36 | call to params : | tainted_path.rb:10:31:10:43 | ...[...] : | | tainted_path.rb:10:31:10:43 | ...[...] : | tainted_path.rb:10:12:10:43 | call to absolute_path : | -| tainted_path.rb:16:15:16:41 | call to dirname : | tainted_path.rb:17:26:17:29 | path | +| tainted_path.rb:16:5:16:8 | path : | tainted_path.rb:17:26:17:29 | path | +| tainted_path.rb:16:15:16:41 | call to dirname : | tainted_path.rb:16:5:16:8 | path : | | tainted_path.rb:16:28:16:33 | call to params : | tainted_path.rb:16:28:16:40 | ...[...] : | | tainted_path.rb:16:28:16:40 | ...[...] : | tainted_path.rb:16:15:16:41 | call to dirname : | -| tainted_path.rb:22:12:22:41 | call to expand_path : | tainted_path.rb:23:26:23:29 | path | +| tainted_path.rb:22:5:22:8 | path : | tainted_path.rb:23:26:23:29 | path | +| tainted_path.rb:22:12:22:41 | call to expand_path : | tainted_path.rb:22:5:22:8 | path : | | tainted_path.rb:22:29:22:34 | call to params : | tainted_path.rb:22:29:22:41 | ...[...] : | | tainted_path.rb:22:29:22:41 | ...[...] : | tainted_path.rb:22:12:22:41 | call to expand_path : | -| tainted_path.rb:28:12:28:34 | call to path : | tainted_path.rb:29:26:29:29 | path | +| tainted_path.rb:28:5:28:8 | path : | tainted_path.rb:29:26:29:29 | path | +| tainted_path.rb:28:12:28:34 | call to path : | tainted_path.rb:28:5:28:8 | path : | | tainted_path.rb:28:22:28:27 | call to params : | tainted_path.rb:28:22:28:34 | ...[...] : | | tainted_path.rb:28:22:28:34 | ...[...] : | tainted_path.rb:28:12:28:34 | call to path : | -| tainted_path.rb:34:12:34:41 | call to realdirpath : | tainted_path.rb:35:26:35:29 | path | +| tainted_path.rb:34:5:34:8 | path : | tainted_path.rb:35:26:35:29 | path | +| tainted_path.rb:34:12:34:41 | call to realdirpath : | tainted_path.rb:34:5:34:8 | path : | | tainted_path.rb:34:29:34:34 | call to params : | tainted_path.rb:34:29:34:41 | ...[...] : | | tainted_path.rb:34:29:34:41 | ...[...] : | tainted_path.rb:34:12:34:41 | call to realdirpath : | -| tainted_path.rb:40:12:40:38 | call to realpath : | tainted_path.rb:41:26:41:29 | path | +| tainted_path.rb:40:5:40:8 | path : | tainted_path.rb:41:26:41:29 | path | +| tainted_path.rb:40:12:40:38 | call to realpath : | tainted_path.rb:40:5:40:8 | path : | | tainted_path.rb:40:26:40:31 | call to params : | tainted_path.rb:40:26:40:38 | ...[...] : | | tainted_path.rb:40:26:40:38 | ...[...] : | tainted_path.rb:40:12:40:38 | call to realpath : | -| tainted_path.rb:47:12:47:63 | call to join : | tainted_path.rb:48:26:48:29 | path | +| tainted_path.rb:47:5:47:8 | path : | tainted_path.rb:48:26:48:29 | path | +| tainted_path.rb:47:12:47:63 | call to join : | tainted_path.rb:47:5:47:8 | path : | | tainted_path.rb:47:43:47:48 | call to params : | tainted_path.rb:47:43:47:55 | ...[...] : | | tainted_path.rb:47:43:47:55 | ...[...] : | tainted_path.rb:47:12:47:63 | call to join : | -| tainted_path.rb:59:12:59:53 | call to new : | tainted_path.rb:60:26:60:29 | path | +| tainted_path.rb:59:5:59:8 | path : | tainted_path.rb:60:26:60:29 | path | +| tainted_path.rb:59:12:59:53 | call to new : | tainted_path.rb:59:5:59:8 | path : | | tainted_path.rb:59:40:59:45 | call to params : | tainted_path.rb:59:40:59:52 | ...[...] : | | tainted_path.rb:59:40:59:52 | ...[...] : | tainted_path.rb:59:12:59:53 | call to new : | -| tainted_path.rb:71:12:71:53 | call to new : | tainted_path.rb:72:15:72:18 | path | +| tainted_path.rb:71:5:71:8 | path : | tainted_path.rb:72:15:72:18 | path | +| tainted_path.rb:71:12:71:53 | call to new : | tainted_path.rb:71:5:71:8 | path : | | tainted_path.rb:71:40:71:45 | call to params : | tainted_path.rb:71:40:71:52 | ...[...] : | | tainted_path.rb:71:40:71:52 | ...[...] : | tainted_path.rb:71:12:71:53 | call to new : | -| tainted_path.rb:77:12:77:53 | call to new : | tainted_path.rb:78:19:78:22 | path | -| tainted_path.rb:77:12:77:53 | call to new : | tainted_path.rb:79:14:79:17 | path | +| tainted_path.rb:77:5:77:8 | path : | tainted_path.rb:78:19:78:22 | path | +| tainted_path.rb:77:5:77:8 | path : | tainted_path.rb:79:14:79:17 | path | +| tainted_path.rb:77:12:77:53 | call to new : | tainted_path.rb:77:5:77:8 | path : | | tainted_path.rb:77:40:77:45 | call to params : | tainted_path.rb:77:40:77:52 | ...[...] : | | tainted_path.rb:77:40:77:52 | ...[...] : | tainted_path.rb:77:12:77:53 | call to new : | -| tainted_path.rb:84:12:84:53 | call to new : | tainted_path.rb:85:10:85:13 | path | -| tainted_path.rb:84:12:84:53 | call to new : | tainted_path.rb:86:25:86:28 | path | +| tainted_path.rb:84:5:84:8 | path : | tainted_path.rb:85:10:85:13 | path | +| tainted_path.rb:84:5:84:8 | path : | tainted_path.rb:86:25:86:28 | path | +| tainted_path.rb:84:12:84:53 | call to new : | tainted_path.rb:84:5:84:8 | path : | | tainted_path.rb:84:40:84:45 | call to params : | tainted_path.rb:84:40:84:52 | ...[...] : | | tainted_path.rb:84:40:84:52 | ...[...] : | tainted_path.rb:84:12:84:53 | call to new : | -| tainted_path.rb:90:12:90:53 | call to new : | tainted_path.rb:92:11:92:14 | path | +| tainted_path.rb:90:5:90:8 | path : | tainted_path.rb:92:11:92:14 | path | +| tainted_path.rb:90:12:90:53 | call to new : | tainted_path.rb:90:5:90:8 | path : | | tainted_path.rb:90:40:90:45 | call to params : | tainted_path.rb:90:40:90:52 | ...[...] : | | tainted_path.rb:90:40:90:52 | ...[...] : | tainted_path.rb:90:12:90:53 | call to new : | nodes @@ -58,6 +72,7 @@ nodes | ArchiveApiPathTraversal.rb:15:9:15:14 | call to params : | semmle.label | call to params : | | ArchiveApiPathTraversal.rb:15:9:15:25 | ...[...] : | semmle.label | ...[...] : | | ArchiveApiPathTraversal.rb:49:17:49:27 | destination : | semmle.label | destination : | +| ArchiveApiPathTraversal.rb:52:9:52:24 | destination_file : | semmle.label | destination_file : | | ArchiveApiPathTraversal.rb:52:28:52:67 | call to join : | semmle.label | call to join : | | ArchiveApiPathTraversal.rb:52:38:52:48 | destination : | semmle.label | destination : | | ArchiveApiPathTraversal.rb:59:21:59:36 | destination_file | semmle.label | destination_file | @@ -65,55 +80,68 @@ nodes | ArchiveApiPathTraversal.rb:68:20:68:23 | file | semmle.label | file | | ArchiveApiPathTraversal.rb:75:11:75:18 | filename : | semmle.label | filename : | | ArchiveApiPathTraversal.rb:76:19:76:26 | filename | semmle.label | filename | +| tainted_path.rb:4:5:4:8 | path : | semmle.label | path : | | tainted_path.rb:4:12:4:17 | call to params : | semmle.label | call to params : | | tainted_path.rb:4:12:4:24 | ...[...] : | semmle.label | ...[...] : | | tainted_path.rb:5:26:5:29 | path | semmle.label | path | +| tainted_path.rb:10:5:10:8 | path : | semmle.label | path : | | tainted_path.rb:10:12:10:43 | call to absolute_path : | semmle.label | call to absolute_path : | | tainted_path.rb:10:31:10:36 | call to params : | semmle.label | call to params : | | tainted_path.rb:10:31:10:43 | ...[...] : | semmle.label | ...[...] : | | tainted_path.rb:11:26:11:29 | path | semmle.label | path | +| tainted_path.rb:16:5:16:8 | path : | semmle.label | path : | | tainted_path.rb:16:15:16:41 | call to dirname : | semmle.label | call to dirname : | | tainted_path.rb:16:28:16:33 | call to params : | semmle.label | call to params : | | tainted_path.rb:16:28:16:40 | ...[...] : | semmle.label | ...[...] : | | tainted_path.rb:17:26:17:29 | path | semmle.label | path | +| tainted_path.rb:22:5:22:8 | path : | semmle.label | path : | | tainted_path.rb:22:12:22:41 | call to expand_path : | semmle.label | call to expand_path : | | tainted_path.rb:22:29:22:34 | call to params : | semmle.label | call to params : | | tainted_path.rb:22:29:22:41 | ...[...] : | semmle.label | ...[...] : | | tainted_path.rb:23:26:23:29 | path | semmle.label | path | +| tainted_path.rb:28:5:28:8 | path : | semmle.label | path : | | tainted_path.rb:28:12:28:34 | call to path : | semmle.label | call to path : | | tainted_path.rb:28:22:28:27 | call to params : | semmle.label | call to params : | | tainted_path.rb:28:22:28:34 | ...[...] : | semmle.label | ...[...] : | | tainted_path.rb:29:26:29:29 | path | semmle.label | path | +| tainted_path.rb:34:5:34:8 | path : | semmle.label | path : | | tainted_path.rb:34:12:34:41 | call to realdirpath : | semmle.label | call to realdirpath : | | tainted_path.rb:34:29:34:34 | call to params : | semmle.label | call to params : | | tainted_path.rb:34:29:34:41 | ...[...] : | semmle.label | ...[...] : | | tainted_path.rb:35:26:35:29 | path | semmle.label | path | +| tainted_path.rb:40:5:40:8 | path : | semmle.label | path : | | tainted_path.rb:40:12:40:38 | call to realpath : | semmle.label | call to realpath : | | tainted_path.rb:40:26:40:31 | call to params : | semmle.label | call to params : | | tainted_path.rb:40:26:40:38 | ...[...] : | semmle.label | ...[...] : | | tainted_path.rb:41:26:41:29 | path | semmle.label | path | +| tainted_path.rb:47:5:47:8 | path : | semmle.label | path : | | tainted_path.rb:47:12:47:63 | call to join : | semmle.label | call to join : | | tainted_path.rb:47:43:47:48 | call to params : | semmle.label | call to params : | | tainted_path.rb:47:43:47:55 | ...[...] : | semmle.label | ...[...] : | | tainted_path.rb:48:26:48:29 | path | semmle.label | path | +| tainted_path.rb:59:5:59:8 | path : | semmle.label | path : | | tainted_path.rb:59:12:59:53 | call to new : | semmle.label | call to new : | | tainted_path.rb:59:40:59:45 | call to params : | semmle.label | call to params : | | tainted_path.rb:59:40:59:52 | ...[...] : | semmle.label | ...[...] : | | tainted_path.rb:60:26:60:29 | path | semmle.label | path | +| tainted_path.rb:71:5:71:8 | path : | semmle.label | path : | | tainted_path.rb:71:12:71:53 | call to new : | semmle.label | call to new : | | tainted_path.rb:71:40:71:45 | call to params : | semmle.label | call to params : | | tainted_path.rb:71:40:71:52 | ...[...] : | semmle.label | ...[...] : | | tainted_path.rb:72:15:72:18 | path | semmle.label | path | +| tainted_path.rb:77:5:77:8 | path : | semmle.label | path : | | tainted_path.rb:77:12:77:53 | call to new : | semmle.label | call to new : | | tainted_path.rb:77:40:77:45 | call to params : | semmle.label | call to params : | | tainted_path.rb:77:40:77:52 | ...[...] : | semmle.label | ...[...] : | | tainted_path.rb:78:19:78:22 | path | semmle.label | path | | tainted_path.rb:79:14:79:17 | path | semmle.label | path | +| tainted_path.rb:84:5:84:8 | path : | semmle.label | path : | | tainted_path.rb:84:12:84:53 | call to new : | semmle.label | call to new : | | tainted_path.rb:84:40:84:45 | call to params : | semmle.label | call to params : | | tainted_path.rb:84:40:84:52 | ...[...] : | semmle.label | ...[...] : | | tainted_path.rb:85:10:85:13 | path | semmle.label | path | | tainted_path.rb:86:25:86:28 | path | semmle.label | path | +| tainted_path.rb:90:5:90:8 | path : | semmle.label | path : | | tainted_path.rb:90:12:90:53 | call to new : | semmle.label | call to new : | | tainted_path.rb:90:40:90:45 | call to params : | semmle.label | call to params : | | tainted_path.rb:90:40:90:52 | ...[...] : | semmle.label | ...[...] : | diff --git a/ruby/ql/test/query-tests/security/cwe-078/CommandInjection/CommandInjection.expected b/ruby/ql/test/query-tests/security/cwe-078/CommandInjection/CommandInjection.expected index dda603763e2..de8b527312e 100644 --- a/ruby/ql/test/query-tests/security/cwe-078/CommandInjection/CommandInjection.expected +++ b/ruby/ql/test/query-tests/security/cwe-078/CommandInjection/CommandInjection.expected @@ -1,25 +1,30 @@ edges +| CommandInjection.rb:6:9:6:11 | cmd : | CommandInjection.rb:7:10:7:15 | #{...} | +| CommandInjection.rb:6:9:6:11 | cmd : | CommandInjection.rb:8:16:8:18 | cmd | +| CommandInjection.rb:6:9:6:11 | cmd : | CommandInjection.rb:10:14:10:16 | cmd | +| CommandInjection.rb:6:9:6:11 | cmd : | CommandInjection.rb:11:17:11:22 | #{...} | +| CommandInjection.rb:6:9:6:11 | cmd : | CommandInjection.rb:13:9:13:14 | #{...} | +| CommandInjection.rb:6:9:6:11 | cmd : | CommandInjection.rb:29:19:29:24 | #{...} | +| CommandInjection.rb:6:9:6:11 | cmd : | CommandInjection.rb:33:24:33:36 | "echo #{...}" | +| CommandInjection.rb:6:9:6:11 | cmd : | CommandInjection.rb:34:39:34:51 | "grep #{...}" | | CommandInjection.rb:6:15:6:20 | call to params : | CommandInjection.rb:6:15:6:26 | ...[...] : | -| CommandInjection.rb:6:15:6:26 | ...[...] : | CommandInjection.rb:7:10:7:15 | #{...} | -| CommandInjection.rb:6:15:6:26 | ...[...] : | CommandInjection.rb:8:16:8:18 | cmd | -| CommandInjection.rb:6:15:6:26 | ...[...] : | CommandInjection.rb:10:14:10:16 | cmd | -| CommandInjection.rb:6:15:6:26 | ...[...] : | CommandInjection.rb:11:17:11:22 | #{...} | -| CommandInjection.rb:6:15:6:26 | ...[...] : | CommandInjection.rb:13:9:13:14 | #{...} | -| CommandInjection.rb:6:15:6:26 | ...[...] : | CommandInjection.rb:29:19:29:24 | #{...} | -| CommandInjection.rb:6:15:6:26 | ...[...] : | CommandInjection.rb:33:24:33:36 | "echo #{...}" | -| CommandInjection.rb:6:15:6:26 | ...[...] : | CommandInjection.rb:34:39:34:51 | "grep #{...}" | +| CommandInjection.rb:6:15:6:26 | ...[...] : | CommandInjection.rb:6:9:6:11 | cmd : | +| CommandInjection.rb:46:9:46:11 | cmd : | CommandInjection.rb:50:24:50:36 | "echo #{...}" | | CommandInjection.rb:46:15:46:20 | call to params : | CommandInjection.rb:46:15:46:26 | ...[...] : | -| CommandInjection.rb:46:15:46:26 | ...[...] : | CommandInjection.rb:50:24:50:36 | "echo #{...}" | +| CommandInjection.rb:46:15:46:26 | ...[...] : | CommandInjection.rb:46:9:46:11 | cmd : | +| CommandInjection.rb:54:7:54:9 | cmd : | CommandInjection.rb:59:14:59:16 | cmd | | CommandInjection.rb:54:13:54:18 | call to params : | CommandInjection.rb:54:13:54:24 | ...[...] : | -| CommandInjection.rb:54:13:54:24 | ...[...] : | CommandInjection.rb:59:14:59:16 | cmd | +| CommandInjection.rb:54:13:54:24 | ...[...] : | CommandInjection.rb:54:7:54:9 | cmd : | | CommandInjection.rb:73:18:73:23 | number : | CommandInjection.rb:74:14:74:29 | "echo #{...}" | | CommandInjection.rb:81:23:81:33 | blah_number : | CommandInjection.rb:82:14:82:34 | "echo #{...}" | | CommandInjection.rb:90:20:90:25 | **args : | CommandInjection.rb:91:22:91:25 | args : | | CommandInjection.rb:91:22:91:25 | args : | CommandInjection.rb:91:22:91:37 | ...[...] : | | CommandInjection.rb:91:22:91:37 | ...[...] : | CommandInjection.rb:91:14:91:39 | "echo #{...}" | +| CommandInjection.rb:103:9:103:12 | file : | CommandInjection.rb:104:16:104:28 | "cat #{...}" | | CommandInjection.rb:103:16:103:21 | call to params : | CommandInjection.rb:103:16:103:28 | ...[...] : | -| CommandInjection.rb:103:16:103:28 | ...[...] : | CommandInjection.rb:104:16:104:28 | "cat #{...}" | +| CommandInjection.rb:103:16:103:28 | ...[...] : | CommandInjection.rb:103:9:103:12 | file : | nodes +| CommandInjection.rb:6:9:6:11 | cmd : | semmle.label | cmd : | | CommandInjection.rb:6:15:6:20 | call to params : | semmle.label | call to params : | | CommandInjection.rb:6:15:6:26 | ...[...] : | semmle.label | ...[...] : | | CommandInjection.rb:7:10:7:15 | #{...} | semmle.label | #{...} | @@ -30,9 +35,11 @@ nodes | CommandInjection.rb:29:19:29:24 | #{...} | semmle.label | #{...} | | CommandInjection.rb:33:24:33:36 | "echo #{...}" | semmle.label | "echo #{...}" | | CommandInjection.rb:34:39:34:51 | "grep #{...}" | semmle.label | "grep #{...}" | +| CommandInjection.rb:46:9:46:11 | cmd : | semmle.label | cmd : | | CommandInjection.rb:46:15:46:20 | call to params : | semmle.label | call to params : | | CommandInjection.rb:46:15:46:26 | ...[...] : | semmle.label | ...[...] : | | CommandInjection.rb:50:24:50:36 | "echo #{...}" | semmle.label | "echo #{...}" | +| CommandInjection.rb:54:7:54:9 | cmd : | semmle.label | cmd : | | CommandInjection.rb:54:13:54:18 | call to params : | semmle.label | call to params : | | CommandInjection.rb:54:13:54:24 | ...[...] : | semmle.label | ...[...] : | | CommandInjection.rb:59:14:59:16 | cmd | semmle.label | cmd | @@ -44,6 +51,7 @@ nodes | CommandInjection.rb:91:14:91:39 | "echo #{...}" | semmle.label | "echo #{...}" | | CommandInjection.rb:91:22:91:25 | args : | semmle.label | args : | | CommandInjection.rb:91:22:91:37 | ...[...] : | semmle.label | ...[...] : | +| CommandInjection.rb:103:9:103:12 | file : | semmle.label | file : | | CommandInjection.rb:103:16:103:21 | call to params : | semmle.label | call to params : | | CommandInjection.rb:103:16:103:28 | ...[...] : | semmle.label | ...[...] : | | CommandInjection.rb:104:16:104:28 | "cat #{...}" | semmle.label | "cat #{...}" | diff --git a/ruby/ql/test/query-tests/security/cwe-078/KernelOpen/KernelOpen.expected b/ruby/ql/test/query-tests/security/cwe-078/KernelOpen/KernelOpen.expected index 1a7088fcbe8..b64fd8c416f 100644 --- a/ruby/ql/test/query-tests/security/cwe-078/KernelOpen/KernelOpen.expected +++ b/ruby/ql/test/query-tests/security/cwe-078/KernelOpen/KernelOpen.expected @@ -1,17 +1,19 @@ edges +| KernelOpen.rb:3:5:3:8 | file : | KernelOpen.rb:4:10:4:13 | file | +| KernelOpen.rb:3:5:3:8 | file : | KernelOpen.rb:5:13:5:16 | file | +| KernelOpen.rb:3:5:3:8 | file : | KernelOpen.rb:6:14:6:17 | file | +| KernelOpen.rb:3:5:3:8 | file : | KernelOpen.rb:7:16:7:19 | file | +| KernelOpen.rb:3:5:3:8 | file : | KernelOpen.rb:8:17:8:20 | file | +| KernelOpen.rb:3:5:3:8 | file : | KernelOpen.rb:9:16:9:19 | file | +| KernelOpen.rb:3:5:3:8 | file : | KernelOpen.rb:10:18:10:21 | file | +| KernelOpen.rb:3:5:3:8 | file : | KernelOpen.rb:11:14:11:17 | file | +| KernelOpen.rb:3:5:3:8 | file : | KernelOpen.rb:13:23:13:26 | file : | +| KernelOpen.rb:3:5:3:8 | file : | KernelOpen.rb:26:10:26:13 | file | | KernelOpen.rb:3:12:3:17 | call to params : | KernelOpen.rb:3:12:3:24 | ...[...] : | -| KernelOpen.rb:3:12:3:24 | ...[...] : | KernelOpen.rb:4:10:4:13 | file | -| KernelOpen.rb:3:12:3:24 | ...[...] : | KernelOpen.rb:5:13:5:16 | file | -| KernelOpen.rb:3:12:3:24 | ...[...] : | KernelOpen.rb:6:14:6:17 | file | -| KernelOpen.rb:3:12:3:24 | ...[...] : | KernelOpen.rb:7:16:7:19 | file | -| KernelOpen.rb:3:12:3:24 | ...[...] : | KernelOpen.rb:8:17:8:20 | file | -| KernelOpen.rb:3:12:3:24 | ...[...] : | KernelOpen.rb:9:16:9:19 | file | -| KernelOpen.rb:3:12:3:24 | ...[...] : | KernelOpen.rb:10:18:10:21 | file | -| KernelOpen.rb:3:12:3:24 | ...[...] : | KernelOpen.rb:11:14:11:17 | file | -| KernelOpen.rb:3:12:3:24 | ...[...] : | KernelOpen.rb:13:23:13:26 | file : | -| KernelOpen.rb:3:12:3:24 | ...[...] : | KernelOpen.rb:26:10:26:13 | file | +| KernelOpen.rb:3:12:3:24 | ...[...] : | KernelOpen.rb:3:5:3:8 | file : | | KernelOpen.rb:13:23:13:26 | file : | KernelOpen.rb:13:13:13:31 | call to join | nodes +| KernelOpen.rb:3:5:3:8 | file : | semmle.label | file : | | KernelOpen.rb:3:12:3:17 | call to params : | semmle.label | call to params : | | KernelOpen.rb:3:12:3:24 | ...[...] : | semmle.label | ...[...] : | | KernelOpen.rb:4:10:4:13 | file | semmle.label | file | diff --git a/ruby/ql/test/query-tests/security/cwe-079/ReflectedXSS.expected b/ruby/ql/test/query-tests/security/cwe-079/ReflectedXSS.expected index 55e0ea7f42b..40062a572a1 100644 --- a/ruby/ql/test/query-tests/security/cwe-079/ReflectedXSS.expected +++ b/ruby/ql/test/query-tests/security/cwe-079/ReflectedXSS.expected @@ -8,9 +8,10 @@ edges | 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:5:18:6 | dt : | app/controllers/foo/bars_controller.rb:19:22:19:23 | dt : | +| app/controllers/foo/bars_controller.rb:18:5:18:6 | dt : | app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : | | 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:18:10:18:22 | ...[...] : | app/controllers/foo/bars_controller.rb:18:5:18:6 | dt : | | 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 | ... = ... | @@ -20,8 +21,9 @@ edges | 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:5:30:7 | str : | app/controllers/foo/bars_controller.rb:31:5:31:7 | str | | 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/controllers/foo/bars_controller.rb:30:11:30:28 | ...[...] : | app/controllers/foo/bars_controller.rb:30:5:30:7 | str : | | 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 | ...[...] | @@ -41,6 +43,7 @@ nodes | app/controllers/foo/bars_controller.rb:13:20:13:37 | ...[...] : | semmle.label | ...[...] : | | app/controllers/foo/bars_controller.rb:17:21:17:26 | call to params : | semmle.label | call to params : | | app/controllers/foo/bars_controller.rb:17:21:17:36 | ...[...] : | semmle.label | ...[...] : | +| app/controllers/foo/bars_controller.rb:18:5:18:6 | dt : | semmle.label | dt : | | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | semmle.label | call to params : | | app/controllers/foo/bars_controller.rb:18:10:18:22 | ...[...] : | semmle.label | ...[...] : | | app/controllers/foo/bars_controller.rb:19:22:19:23 | dt : | semmle.label | dt : | @@ -48,6 +51,7 @@ nodes | app/controllers/foo/bars_controller.rb:24:39:24:59 | ... = ... | semmle.label | ... = ... | | app/controllers/foo/bars_controller.rb:24:39:24:59 | ...[...] : | semmle.label | ...[...] : | | app/controllers/foo/bars_controller.rb:26:53:26:54 | dt : | semmle.label | dt : | +| app/controllers/foo/bars_controller.rb:30:5:30:7 | str : | semmle.label | str : | | app/controllers/foo/bars_controller.rb:30:11:30:16 | call to params : | semmle.label | call to params : | | 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 | diff --git a/ruby/ql/test/query-tests/security/cwe-079/StoredXSS.expected b/ruby/ql/test/query-tests/security/cwe-079/StoredXSS.expected index 3edc843ea2f..01a48d43371 100644 --- a/ruby/ql/test/query-tests/security/cwe-079/StoredXSS.expected +++ b/ruby/ql/test/query-tests/security/cwe-079/StoredXSS.expected @@ -1,6 +1,7 @@ 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:8:5:8:6 | dt : | app/controllers/foo/stores_controller.rb:9:22:9:23 | dt : | +| app/controllers/foo/stores_controller.rb:8:5:8:6 | dt : | app/controllers/foo/stores_controller.rb:13:55:13:56 | dt : | +| app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/controllers/foo/stores_controller.rb:8:5:8:6 | dt : | | 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 | @@ -18,6 +19,7 @@ edges | 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:5:8:6 | dt : | semmle.label | dt : | | 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 : | diff --git a/ruby/ql/test/query-tests/security/cwe-089/SqlInjection.expected b/ruby/ql/test/query-tests/security/cwe-089/SqlInjection.expected index cac3c53820c..a41722107d6 100644 --- a/ruby/ql/test/query-tests/security/cwe-089/SqlInjection.expected +++ b/ruby/ql/test/query-tests/security/cwe-089/SqlInjection.expected @@ -28,16 +28,21 @@ edges | ActiveRecordInjection.rb:92:21:92:26 | call to params : | ActiveRecordInjection.rb:92:21:92:35 | ...[...] | | ActiveRecordInjection.rb:94:18:94:23 | call to params : | ActiveRecordInjection.rb:94:18:94:35 | ...[...] | | ActiveRecordInjection.rb:96:23:96:28 | call to params : | ActiveRecordInjection.rb:96:23:96:47 | ...[...] | -| ActiveRecordInjection.rb:102:10:102:15 | call to params : | ActiveRecordInjection.rb:103:11:103:12 | ps : | +| ActiveRecordInjection.rb:102:5:102:6 | ps : | ActiveRecordInjection.rb:103:11:103:12 | ps : | +| ActiveRecordInjection.rb:102:10:102:15 | call to params : | ActiveRecordInjection.rb:102:5:102:6 | ps : | +| ActiveRecordInjection.rb:103:5:103:7 | uid : | ActiveRecordInjection.rb:104:5:104:9 | uidEq : | | ActiveRecordInjection.rb:103:11:103:12 | ps : | ActiveRecordInjection.rb:103:11:103:17 | ...[...] : | -| ActiveRecordInjection.rb:103:11:103:17 | ...[...] : | ActiveRecordInjection.rb:108:20:108:32 | ... + ... | +| ActiveRecordInjection.rb:103:11:103:17 | ...[...] : | ActiveRecordInjection.rb:103:5:103:7 | uid : | +| ActiveRecordInjection.rb:104:5:104:9 | uidEq : | ActiveRecordInjection.rb:108:20:108:32 | ... + ... | | ActiveRecordInjection.rb:141:21:141:26 | call to params : | ActiveRecordInjection.rb:141:21:141:44 | ...[...] : | | ActiveRecordInjection.rb:141:21:141:44 | ...[...] : | ActiveRecordInjection.rb:20:22:20:30 | condition : | | ActiveRecordInjection.rb:155:59:155:64 | call to params : | ActiveRecordInjection.rb:155:59:155:74 | ...[...] : | | ActiveRecordInjection.rb:155:59:155:74 | ...[...] : | ActiveRecordInjection.rb:155:27:155:76 | "this is an unsafe annotation:..." | -| ActiveRecordInjection.rb:166:17:166:32 | call to permitted_params : | ActiveRecordInjection.rb:167:47:167:55 | my_params : | +| ActiveRecordInjection.rb:166:5:166:13 | my_params : | ActiveRecordInjection.rb:167:47:167:55 | my_params : | +| ActiveRecordInjection.rb:166:17:166:32 | call to permitted_params : | ActiveRecordInjection.rb:166:5:166:13 | my_params : | +| ActiveRecordInjection.rb:167:5:167:9 | query : | ActiveRecordInjection.rb:168:37:168:41 | query | | ActiveRecordInjection.rb:167:47:167:55 | my_params : | ActiveRecordInjection.rb:167:47:167:65 | ...[...] : | -| ActiveRecordInjection.rb:167:47:167:65 | ...[...] : | ActiveRecordInjection.rb:168:37:168:41 | query | +| ActiveRecordInjection.rb:167:47:167:65 | ...[...] : | ActiveRecordInjection.rb:167:5:167:9 | query : | | ActiveRecordInjection.rb:173:5:173:10 | call to params : | ActiveRecordInjection.rb:173:5:173:27 | call to require : | | ActiveRecordInjection.rb:173:5:173:27 | call to require : | ActiveRecordInjection.rb:173:5:173:59 | call to permit : | | ActiveRecordInjection.rb:173:5:173:59 | call to permit : | ActiveRecordInjection.rb:166:17:166:32 | call to permitted_params : | @@ -47,8 +52,9 @@ edges | ActiveRecordInjection.rb:177:77:177:102 | ...[...] : | ActiveRecordInjection.rb:177:43:177:104 | "SELECT * FROM users WHERE id ..." | | ActiveRecordInjection.rb:178:69:178:84 | call to permitted_params : | ActiveRecordInjection.rb:178:69:178:94 | ...[...] : | | ActiveRecordInjection.rb:178:69:178:94 | ...[...] : | ActiveRecordInjection.rb:178:35:178:96 | "SELECT * FROM users WHERE id ..." | +| ArelInjection.rb:4:5:4:8 | name : | ArelInjection.rb:6:20:6:61 | "SELECT * FROM users WHERE nam..." | | ArelInjection.rb:4:12:4:17 | call to params : | ArelInjection.rb:4:12:4:29 | ...[...] : | -| ArelInjection.rb:4:12:4:29 | ...[...] : | ArelInjection.rb:6:20:6:61 | "SELECT * FROM users WHERE nam..." | +| ArelInjection.rb:4:12:4:29 | ...[...] : | ArelInjection.rb:4:5:4:8 | name : | nodes | ActiveRecordInjection.rb:8:25:8:28 | name : | semmle.label | name : | | ActiveRecordInjection.rb:8:31:8:34 | pass : | semmle.label | pass : | @@ -96,16 +102,21 @@ nodes | ActiveRecordInjection.rb:94:18:94:35 | ...[...] | semmle.label | ...[...] | | ActiveRecordInjection.rb:96:23:96:28 | call to params : | semmle.label | call to params : | | ActiveRecordInjection.rb:96:23:96:47 | ...[...] | semmle.label | ...[...] | +| ActiveRecordInjection.rb:102:5:102:6 | ps : | semmle.label | ps : | | ActiveRecordInjection.rb:102:10:102:15 | call to params : | semmle.label | call to params : | +| ActiveRecordInjection.rb:103:5:103:7 | uid : | semmle.label | uid : | | ActiveRecordInjection.rb:103:11:103:12 | ps : | semmle.label | ps : | | ActiveRecordInjection.rb:103:11:103:17 | ...[...] : | semmle.label | ...[...] : | +| ActiveRecordInjection.rb:104:5:104:9 | uidEq : | semmle.label | uidEq : | | ActiveRecordInjection.rb:108:20:108:32 | ... + ... | semmle.label | ... + ... | | ActiveRecordInjection.rb:141:21:141:26 | call to params : | semmle.label | call to params : | | ActiveRecordInjection.rb:141:21:141:44 | ...[...] : | semmle.label | ...[...] : | | ActiveRecordInjection.rb:155:27:155:76 | "this is an unsafe annotation:..." | semmle.label | "this is an unsafe annotation:..." | | ActiveRecordInjection.rb:155:59:155:64 | call to params : | semmle.label | call to params : | | ActiveRecordInjection.rb:155:59:155:74 | ...[...] : | semmle.label | ...[...] : | +| ActiveRecordInjection.rb:166:5:166:13 | my_params : | semmle.label | my_params : | | ActiveRecordInjection.rb:166:17:166:32 | call to permitted_params : | semmle.label | call to permitted_params : | +| ActiveRecordInjection.rb:167:5:167:9 | query : | semmle.label | query : | | ActiveRecordInjection.rb:167:47:167:55 | my_params : | semmle.label | my_params : | | ActiveRecordInjection.rb:167:47:167:65 | ...[...] : | semmle.label | ...[...] : | | ActiveRecordInjection.rb:168:37:168:41 | query | semmle.label | query | @@ -118,6 +129,7 @@ nodes | ActiveRecordInjection.rb:178:35:178:96 | "SELECT * FROM users WHERE id ..." | semmle.label | "SELECT * FROM users WHERE id ..." | | ActiveRecordInjection.rb:178:69:178:84 | call to permitted_params : | semmle.label | call to permitted_params : | | ActiveRecordInjection.rb:178:69:178:94 | ...[...] : | semmle.label | ...[...] : | +| ArelInjection.rb:4:5:4:8 | name : | semmle.label | name : | | ArelInjection.rb:4:12:4:17 | call to params : | semmle.label | call to params : | | ArelInjection.rb:4:12:4:29 | ...[...] : | semmle.label | ...[...] : | | ArelInjection.rb:6:20:6:61 | "SELECT * FROM users WHERE nam..." | semmle.label | "SELECT * FROM users WHERE nam..." | diff --git a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection/CodeInjection.expected b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection/CodeInjection.expected index 53a181121c2..0c7a63915ed 100644 --- a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection/CodeInjection.expected +++ b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection/CodeInjection.expected @@ -1,26 +1,30 @@ edges +| CodeInjection.rb:5:5:5:8 | code : | CodeInjection.rb:8:10:8:13 | code | +| CodeInjection.rb:5:5:5:8 | code : | CodeInjection.rb:8:10:8:13 | code | +| CodeInjection.rb:5:5:5:8 | code : | CodeInjection.rb:20:20:20:23 | code | +| CodeInjection.rb:5:5:5:8 | code : | CodeInjection.rb:20:20:20:23 | code | +| CodeInjection.rb:5:5:5:8 | code : | CodeInjection.rb:23:21:23:24 | code | +| CodeInjection.rb:5:5:5:8 | code : | CodeInjection.rb:23:21:23:24 | code | +| CodeInjection.rb:5:5:5:8 | code : | CodeInjection.rb:29:15:29:18 | code | +| CodeInjection.rb:5:5:5:8 | code : | CodeInjection.rb:32:19:32:22 | code | +| CodeInjection.rb:5:5:5:8 | code : | CodeInjection.rb:38:24:38:27 | code : | +| CodeInjection.rb:5:5:5:8 | code : | CodeInjection.rb:38:24:38:27 | code : | +| CodeInjection.rb:5:5:5:8 | code : | CodeInjection.rb:41:40:41:43 | code | | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:5:12:5:24 | ...[...] : | | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:5:12:5:24 | ...[...] : | -| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:8:10:8:13 | code | -| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:8:10:8:13 | code | -| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:20:20:20:23 | code | -| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:20:20:20:23 | code | -| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:23:21:23:24 | code | -| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:23:21:23:24 | code | -| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:29:15:29:18 | code | -| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:32:19:32:22 | code | -| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:38:24:38:27 | code : | -| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:38:24:38:27 | code : | -| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:41:40:41:43 | code | +| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:5:5:5:8 | code : | +| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:5:5:5:8 | code : | | CodeInjection.rb:38:24:38:27 | code : | CodeInjection.rb:38:10:38:28 | call to escape | | CodeInjection.rb:38:24:38:27 | code : | CodeInjection.rb:38:10:38:28 | call to escape | +| CodeInjection.rb:78:5:78:8 | code : | CodeInjection.rb:80:16:80:19 | code | +| CodeInjection.rb:78:5:78:8 | code : | CodeInjection.rb:86:10:86:37 | ... + ... | +| CodeInjection.rb:78:5:78:8 | code : | CodeInjection.rb:88:10:88:32 | "prefix_#{...}_suffix" | +| CodeInjection.rb:78:5:78:8 | code : | CodeInjection.rb:90:10:90:13 | code | +| CodeInjection.rb:78:5:78:8 | code : | CodeInjection.rb:90:10:90:13 | code | | CodeInjection.rb:78:12:78:17 | call to params : | CodeInjection.rb:78:12:78:24 | ...[...] : | | CodeInjection.rb:78:12:78:17 | call to params : | CodeInjection.rb:78:12:78:24 | ...[...] : | -| CodeInjection.rb:78:12:78:24 | ...[...] : | CodeInjection.rb:80:16:80:19 | code | -| CodeInjection.rb:78:12:78:24 | ...[...] : | CodeInjection.rb:86:10:86:37 | ... + ... | -| CodeInjection.rb:78:12:78:24 | ...[...] : | CodeInjection.rb:88:10:88:32 | "prefix_#{...}_suffix" | -| CodeInjection.rb:78:12:78:24 | ...[...] : | CodeInjection.rb:90:10:90:13 | code | -| CodeInjection.rb:78:12:78:24 | ...[...] : | CodeInjection.rb:90:10:90:13 | code | +| CodeInjection.rb:78:12:78:24 | ...[...] : | CodeInjection.rb:78:5:78:8 | code : | +| CodeInjection.rb:78:12:78:24 | ...[...] : | CodeInjection.rb:78:5:78:8 | code : | | CodeInjection.rb:101:3:102:5 | self in index [@foo] : | CodeInjection.rb:111:3:113:5 | self in baz [@foo] : | | CodeInjection.rb:101:3:102:5 | self in index [@foo] : | CodeInjection.rb:111:3:113:5 | self in baz [@foo] : | | CodeInjection.rb:105:5:105:8 | [post] self [@foo] : | CodeInjection.rb:108:3:109:5 | self in bar [@foo] : | @@ -36,6 +40,8 @@ edges | CodeInjection.rb:112:10:112:13 | self [@foo] : | CodeInjection.rb:112:10:112:13 | @foo | | CodeInjection.rb:112:10:112:13 | self [@foo] : | CodeInjection.rb:112:10:112:13 | @foo | nodes +| CodeInjection.rb:5:5:5:8 | code : | semmle.label | code : | +| CodeInjection.rb:5:5:5:8 | code : | semmle.label | code : | | CodeInjection.rb:5:12:5:17 | call to params : | semmle.label | call to params : | | CodeInjection.rb:5:12:5:17 | call to params : | semmle.label | call to params : | | CodeInjection.rb:5:12:5:24 | ...[...] : | semmle.label | ...[...] : | @@ -55,6 +61,8 @@ nodes | CodeInjection.rb:38:24:38:27 | code : | semmle.label | code : | | CodeInjection.rb:38:24:38:27 | code : | semmle.label | code : | | CodeInjection.rb:41:40:41:43 | code | semmle.label | code | +| CodeInjection.rb:78:5:78:8 | code : | semmle.label | code : | +| CodeInjection.rb:78:5:78:8 | code : | semmle.label | code : | | CodeInjection.rb:78:12:78:17 | call to params : | semmle.label | call to params : | | CodeInjection.rb:78:12:78:17 | call to params : | semmle.label | call to params : | | CodeInjection.rb:78:12:78:24 | ...[...] : | semmle.label | ...[...] : | diff --git a/ruby/ql/test/query-tests/security/cwe-094/UnsafeCodeConstruction/UnsafeCodeConstruction.expected b/ruby/ql/test/query-tests/security/cwe-094/UnsafeCodeConstruction/UnsafeCodeConstruction.expected index 1b55dd3c999..f57dd6a3e88 100644 --- a/ruby/ql/test/query-tests/security/cwe-094/UnsafeCodeConstruction/UnsafeCodeConstruction.expected +++ b/ruby/ql/test/query-tests/security/cwe-094/UnsafeCodeConstruction/UnsafeCodeConstruction.expected @@ -4,7 +4,8 @@ edges | impl/unsafeCode.rb:12:12:12:12 | x : | impl/unsafeCode.rb:13:33:13:33 | x | | impl/unsafeCode.rb:28:17:28:22 | my_arr : | impl/unsafeCode.rb:29:10:29:15 | my_arr | | impl/unsafeCode.rb:32:21:32:21 | x : | impl/unsafeCode.rb:33:12:33:12 | x : | -| impl/unsafeCode.rb:33:12:33:12 | x : | impl/unsafeCode.rb:34:10:34:12 | arr | +| impl/unsafeCode.rb:33:5:33:7 | arr [element 0] : | impl/unsafeCode.rb:34:10:34:12 | arr | +| impl/unsafeCode.rb:33:12:33:12 | x : | impl/unsafeCode.rb:33:5:33:7 | arr [element 0] : | | impl/unsafeCode.rb:37:15:37:15 | x : | impl/unsafeCode.rb:39:14:39:14 | x : | | impl/unsafeCode.rb:39:5:39:7 | [post] arr [element] : | impl/unsafeCode.rb:40:10:40:12 | arr | | impl/unsafeCode.rb:39:5:39:7 | [post] arr [element] : | impl/unsafeCode.rb:44:10:44:12 | arr | @@ -13,10 +14,12 @@ edges | impl/unsafeCode.rb:54:21:54:21 | x : | impl/unsafeCode.rb:55:22:55:22 | x | | impl/unsafeCode.rb:59:21:59:21 | x : | impl/unsafeCode.rb:60:17:60:17 | x : | | impl/unsafeCode.rb:59:24:59:24 | y : | impl/unsafeCode.rb:63:30:63:30 | y : | -| impl/unsafeCode.rb:60:11:60:18 | call to Array [element 0] : | impl/unsafeCode.rb:61:10:61:12 | arr | +| impl/unsafeCode.rb:60:5:60:7 | arr [element 0] : | impl/unsafeCode.rb:61:10:61:12 | arr | +| impl/unsafeCode.rb:60:11:60:18 | call to Array [element 0] : | impl/unsafeCode.rb:60:5:60:7 | arr [element 0] : | | impl/unsafeCode.rb:60:17:60:17 | x : | impl/unsafeCode.rb:60:11:60:18 | call to Array [element 0] : | +| impl/unsafeCode.rb:63:5:63:8 | arr2 [element 0] : | impl/unsafeCode.rb:64:10:64:13 | arr2 | | impl/unsafeCode.rb:63:13:63:32 | call to Array [element 1] : | impl/unsafeCode.rb:63:13:63:42 | call to join : | -| impl/unsafeCode.rb:63:13:63:42 | call to join : | impl/unsafeCode.rb:64:10:64:13 | arr2 | +| impl/unsafeCode.rb:63:13:63:42 | call to join : | impl/unsafeCode.rb:63:5:63:8 | arr2 [element 0] : | | impl/unsafeCode.rb:63:30:63:30 | y : | impl/unsafeCode.rb:63:13:63:32 | call to Array [element 1] : | nodes | impl/unsafeCode.rb:2:12:2:17 | target : | semmle.label | target : | @@ -28,6 +31,7 @@ nodes | impl/unsafeCode.rb:28:17:28:22 | my_arr : | semmle.label | my_arr : | | impl/unsafeCode.rb:29:10:29:15 | my_arr | semmle.label | my_arr | | impl/unsafeCode.rb:32:21:32:21 | x : | semmle.label | x : | +| impl/unsafeCode.rb:33:5:33:7 | arr [element 0] : | semmle.label | arr [element 0] : | | impl/unsafeCode.rb:33:12:33:12 | x : | semmle.label | x : | | impl/unsafeCode.rb:34:10:34:12 | arr | semmle.label | arr | | impl/unsafeCode.rb:37:15:37:15 | x : | semmle.label | x : | @@ -41,9 +45,11 @@ nodes | impl/unsafeCode.rb:55:22:55:22 | x | semmle.label | x | | impl/unsafeCode.rb:59:21:59:21 | x : | semmle.label | x : | | impl/unsafeCode.rb:59:24:59:24 | y : | semmle.label | y : | +| impl/unsafeCode.rb:60:5:60:7 | arr [element 0] : | semmle.label | arr [element 0] : | | impl/unsafeCode.rb:60:11:60:18 | call to Array [element 0] : | semmle.label | call to Array [element 0] : | | impl/unsafeCode.rb:60:17:60:17 | x : | semmle.label | x : | | impl/unsafeCode.rb:61:10:61:12 | arr | semmle.label | arr | +| impl/unsafeCode.rb:63:5:63:8 | arr2 [element 0] : | semmle.label | arr2 [element 0] : | | impl/unsafeCode.rb:63:13:63:32 | call to Array [element 1] : | semmle.label | call to Array [element 1] : | | impl/unsafeCode.rb:63:13:63:42 | call to join : | semmle.label | call to join : | | impl/unsafeCode.rb:63:30:63:30 | y : | semmle.label | y : | diff --git a/ruby/ql/test/query-tests/security/cwe-117/LogInjection.expected b/ruby/ql/test/query-tests/security/cwe-117/LogInjection.expected index b0da6305e8a..7f461d5efe1 100644 --- a/ruby/ql/test/query-tests/security/cwe-117/LogInjection.expected +++ b/ruby/ql/test/query-tests/security/cwe-117/LogInjection.expected @@ -1,28 +1,30 @@ edges +| app/controllers/users_controller.rb:15:5:15:15 | unsanitized : | app/controllers/users_controller.rb:16:19:16:29 | unsanitized | +| app/controllers/users_controller.rb:15:5:15:15 | unsanitized : | app/controllers/users_controller.rb:17:19:17:41 | ... + ... | +| app/controllers/users_controller.rb:15:5:15:15 | unsanitized : | app/controllers/users_controller.rb:23:20:23:30 | unsanitized : | | app/controllers/users_controller.rb:15:19:15:24 | call to params : | app/controllers/users_controller.rb:15:19:15:30 | ...[...] : | -| app/controllers/users_controller.rb:15:19:15:30 | ...[...] : | app/controllers/users_controller.rb:16:19:16:29 | unsanitized | -| app/controllers/users_controller.rb:15:19:15:30 | ...[...] : | app/controllers/users_controller.rb:17:19:17:41 | ... + ... | -| app/controllers/users_controller.rb:15:19:15:30 | ...[...] : | app/controllers/users_controller.rb:23:20:23:30 | unsanitized : | -| app/controllers/users_controller.rb:23:5:23:44 | ... = ... : | app/controllers/users_controller.rb:25:7:25:18 | unsanitized2 | +| app/controllers/users_controller.rb:15:19:15:30 | ...[...] : | app/controllers/users_controller.rb:15:5:15:15 | unsanitized : | +| app/controllers/users_controller.rb:23:5:23:16 | unsanitized2 : | app/controllers/users_controller.rb:25:7:25:18 | unsanitized2 | +| app/controllers/users_controller.rb:23:5:23:16 | unsanitized2 : | app/controllers/users_controller.rb:27:16:27:39 | ... + ... | | app/controllers/users_controller.rb:23:20:23:30 | unsanitized : | app/controllers/users_controller.rb:23:20:23:44 | call to sub : | -| app/controllers/users_controller.rb:23:20:23:44 | call to sub : | app/controllers/users_controller.rb:23:5:23:44 | ... = ... : | -| app/controllers/users_controller.rb:23:20:23:44 | call to sub : | app/controllers/users_controller.rb:27:16:27:39 | ... + ... | -| app/controllers/users_controller.rb:33:5:33:31 | ... = ... : | app/controllers/users_controller.rb:34:33:34:43 | unsanitized | -| app/controllers/users_controller.rb:33:5:33:31 | ... = ... : | app/controllers/users_controller.rb:35:33:35:55 | ... + ... | +| app/controllers/users_controller.rb:23:20:23:44 | call to sub : | app/controllers/users_controller.rb:23:5:23:16 | unsanitized2 : | +| app/controllers/users_controller.rb:33:5:33:15 | unsanitized : | app/controllers/users_controller.rb:34:33:34:43 | unsanitized | +| app/controllers/users_controller.rb:33:5:33:15 | unsanitized : | app/controllers/users_controller.rb:35:33:35:55 | ... + ... | | app/controllers/users_controller.rb:33:19:33:25 | call to cookies : | app/controllers/users_controller.rb:33:19:33:31 | ...[...] : | -| app/controllers/users_controller.rb:33:19:33:31 | ...[...] : | app/controllers/users_controller.rb:33:5:33:31 | ... = ... : | +| app/controllers/users_controller.rb:33:19:33:31 | ...[...] : | app/controllers/users_controller.rb:33:5:33:15 | unsanitized : | | app/controllers/users_controller.rb:49:19:49:24 | call to params : | app/controllers/users_controller.rb:49:19:49:30 | ...[...] | nodes +| app/controllers/users_controller.rb:15:5:15:15 | unsanitized : | semmle.label | unsanitized : | | app/controllers/users_controller.rb:15:19:15:24 | call to params : | semmle.label | call to params : | | app/controllers/users_controller.rb:15:19:15:30 | ...[...] : | semmle.label | ...[...] : | | app/controllers/users_controller.rb:16:19:16:29 | unsanitized | semmle.label | unsanitized | | app/controllers/users_controller.rb:17:19:17:41 | ... + ... | semmle.label | ... + ... | -| app/controllers/users_controller.rb:23:5:23:44 | ... = ... : | semmle.label | ... = ... : | +| app/controllers/users_controller.rb:23:5:23:16 | unsanitized2 : | semmle.label | unsanitized2 : | | app/controllers/users_controller.rb:23:20:23:30 | unsanitized : | semmle.label | unsanitized : | | app/controllers/users_controller.rb:23:20:23:44 | call to sub : | semmle.label | call to sub : | | app/controllers/users_controller.rb:25:7:25:18 | unsanitized2 | semmle.label | unsanitized2 | | app/controllers/users_controller.rb:27:16:27:39 | ... + ... | semmle.label | ... + ... | -| app/controllers/users_controller.rb:33:5:33:31 | ... = ... : | semmle.label | ... = ... : | +| app/controllers/users_controller.rb:33:5:33:15 | unsanitized : | semmle.label | unsanitized : | | app/controllers/users_controller.rb:33:19:33:25 | call to cookies : | semmle.label | call to cookies : | | app/controllers/users_controller.rb:33:19:33:31 | ...[...] : | semmle.label | ...[...] : | | app/controllers/users_controller.rb:34:33:34:43 | unsanitized | semmle.label | unsanitized | diff --git a/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.expected b/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.expected index c428efe29cd..1d8170fd428 100644 --- a/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.expected +++ b/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.expected @@ -1,42 +1,50 @@ edges +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:10:5:10:8 | name | +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:11:5:11:8 | name | +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:12:5:12:8 | name | +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:13:5:13:8 | name | +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:14:5:14:8 | name | +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:15:5:15:8 | name | +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:16:5:16:8 | name | +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:17:5:17:8 | name | +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:18:5:18:8 | name | +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:19:5:19:8 | name | +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:20:5:20:8 | name | +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:21:5:21:8 | name | +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:22:5:22:8 | name | +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:23:17:23:20 | name | +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:24:18:24:21 | name | +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:42:10:42:13 | name | +| PolynomialReDoS.rb:4:5:4:8 | name : | PolynomialReDoS.rb:47:10:47:13 | name | | PolynomialReDoS.rb:4:12:4:17 | call to params : | PolynomialReDoS.rb:4:12:4:24 | ...[...] : | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:10:5:10:8 | name | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:11:5:11:8 | name | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:12:5:12:8 | name | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:13:5:13:8 | name | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:14:5:14:8 | name | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:15:5:15:8 | name | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:16:5:16:8 | name | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:17:5:17:8 | name | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:18:5:18:8 | name | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:19:5:19:8 | name | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:20:5:20:8 | name | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:21:5:21:8 | name | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:22:5:22:8 | name | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:23:17:23:20 | name | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:24:18:24:21 | name | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:42:10:42:13 | name | -| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:47:10:47:13 | name | +| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:4:5:4:8 | name : | +| PolynomialReDoS.rb:27:5:27:5 | a : | PolynomialReDoS.rb:28:5:28:5 | a | | PolynomialReDoS.rb:27:9:27:14 | call to params : | PolynomialReDoS.rb:27:9:27:18 | ...[...] : | -| PolynomialReDoS.rb:27:9:27:18 | ...[...] : | PolynomialReDoS.rb:28:5:28:5 | a | +| PolynomialReDoS.rb:27:9:27:18 | ...[...] : | PolynomialReDoS.rb:27:5:27:5 | a : | +| PolynomialReDoS.rb:29:5:29:5 | b : | PolynomialReDoS.rb:30:5:30:5 | b | | PolynomialReDoS.rb:29:9:29:14 | call to params : | PolynomialReDoS.rb:29:9:29:18 | ...[...] : | -| PolynomialReDoS.rb:29:9:29:18 | ...[...] : | PolynomialReDoS.rb:30:5:30:5 | b | +| PolynomialReDoS.rb:29:9:29:18 | ...[...] : | PolynomialReDoS.rb:29:5:29:5 | b : | +| PolynomialReDoS.rb:31:5:31:5 | c : | PolynomialReDoS.rb:32:5:32:5 | c | | PolynomialReDoS.rb:31:9:31:14 | call to params : | PolynomialReDoS.rb:31:9:31:18 | ...[...] : | -| PolynomialReDoS.rb:31:9:31:18 | ...[...] : | PolynomialReDoS.rb:32:5:32:5 | c | +| PolynomialReDoS.rb:31:9:31:18 | ...[...] : | PolynomialReDoS.rb:31:5:31:5 | c : | +| PolynomialReDoS.rb:54:5:54:8 | name : | PolynomialReDoS.rb:56:38:56:41 | name : | +| PolynomialReDoS.rb:54:5:54:8 | name : | PolynomialReDoS.rb:58:37:58:40 | name : | | PolynomialReDoS.rb:54:12:54:17 | call to params : | PolynomialReDoS.rb:54:12:54:24 | ...[...] : | -| PolynomialReDoS.rb:54:12:54:24 | ...[...] : | PolynomialReDoS.rb:56:38:56:41 | name : | -| PolynomialReDoS.rb:54:12:54:24 | ...[...] : | PolynomialReDoS.rb:58:37:58:40 | name : | +| PolynomialReDoS.rb:54:12:54:24 | ...[...] : | PolynomialReDoS.rb:54:5:54:8 | name : | | PolynomialReDoS.rb:56:38:56:41 | name : | PolynomialReDoS.rb:61:33:61:37 | input : | | PolynomialReDoS.rb:58:37:58:40 | name : | PolynomialReDoS.rb:65:42:65:46 | input : | | PolynomialReDoS.rb:61:33:61:37 | input : | PolynomialReDoS.rb:62:5:62:9 | input | | PolynomialReDoS.rb:65:42:65:46 | input : | PolynomialReDoS.rb:66:5:66:9 | input | +| PolynomialReDoS.rb:70:5:70:8 | name : | PolynomialReDoS.rb:73:32:73:35 | name : | | PolynomialReDoS.rb:70:12:70:17 | call to params : | PolynomialReDoS.rb:70:12:70:24 | ...[...] : | -| PolynomialReDoS.rb:70:12:70:24 | ...[...] : | PolynomialReDoS.rb:73:32:73:35 | name : | +| PolynomialReDoS.rb:70:12:70:24 | ...[...] : | PolynomialReDoS.rb:70:5:70:8 | name : | | PolynomialReDoS.rb:73:32:73:35 | name : | PolynomialReDoS.rb:76:35:76:39 | input : | | PolynomialReDoS.rb:76:35:76:39 | input : | PolynomialReDoS.rb:77:5:77:9 | input | | lib/index.rb:2:11:2:11 | x : | lib/index.rb:4:13:4:13 | x | | lib/index.rb:8:13:8:13 | x : | lib/index.rb:9:15:9:15 | x | +| lib/index.rb:8:13:8:13 | x : | lib/index.rb:11:16:11:16 | x | nodes +| PolynomialReDoS.rb:4:5:4:8 | name : | semmle.label | name : | | PolynomialReDoS.rb:4:12:4:17 | call to params : | semmle.label | call to params : | | PolynomialReDoS.rb:4:12:4:24 | ...[...] : | semmle.label | ...[...] : | | PolynomialReDoS.rb:10:5:10:8 | name | semmle.label | name | @@ -54,17 +62,21 @@ nodes | PolynomialReDoS.rb:22:5:22:8 | name | semmle.label | name | | PolynomialReDoS.rb:23:17:23:20 | name | semmle.label | name | | PolynomialReDoS.rb:24:18:24:21 | name | semmle.label | name | +| PolynomialReDoS.rb:27:5:27:5 | a : | semmle.label | a : | | PolynomialReDoS.rb:27:9:27:14 | call to params : | semmle.label | call to params : | | PolynomialReDoS.rb:27:9:27:18 | ...[...] : | semmle.label | ...[...] : | | PolynomialReDoS.rb:28:5:28:5 | a | semmle.label | a | +| PolynomialReDoS.rb:29:5:29:5 | b : | semmle.label | b : | | PolynomialReDoS.rb:29:9:29:14 | call to params : | semmle.label | call to params : | | PolynomialReDoS.rb:29:9:29:18 | ...[...] : | semmle.label | ...[...] : | | PolynomialReDoS.rb:30:5:30:5 | b | semmle.label | b | +| PolynomialReDoS.rb:31:5:31:5 | c : | semmle.label | c : | | PolynomialReDoS.rb:31:9:31:14 | call to params : | semmle.label | call to params : | | PolynomialReDoS.rb:31:9:31:18 | ...[...] : | semmle.label | ...[...] : | | PolynomialReDoS.rb:32:5:32:5 | c | semmle.label | c | | PolynomialReDoS.rb:42:10:42:13 | name | semmle.label | name | | PolynomialReDoS.rb:47:10:47:13 | name | semmle.label | name | +| PolynomialReDoS.rb:54:5:54:8 | name : | semmle.label | name : | | PolynomialReDoS.rb:54:12:54:17 | call to params : | semmle.label | call to params : | | PolynomialReDoS.rb:54:12:54:24 | ...[...] : | semmle.label | ...[...] : | | PolynomialReDoS.rb:56:38:56:41 | name : | semmle.label | name : | @@ -73,6 +85,7 @@ nodes | PolynomialReDoS.rb:62:5:62:9 | input | semmle.label | input | | PolynomialReDoS.rb:65:42:65:46 | input : | semmle.label | input : | | PolynomialReDoS.rb:66:5:66:9 | input | semmle.label | input | +| PolynomialReDoS.rb:70:5:70:8 | name : | semmle.label | name : | | PolynomialReDoS.rb:70:12:70:17 | call to params : | semmle.label | call to params : | | PolynomialReDoS.rb:70:12:70:24 | ...[...] : | semmle.label | ...[...] : | | PolynomialReDoS.rb:73:32:73:35 | name : | semmle.label | name : | @@ -82,6 +95,7 @@ nodes | lib/index.rb:4:13:4:13 | x | semmle.label | x | | lib/index.rb:8:13:8:13 | x : | semmle.label | x : | | lib/index.rb:9:15:9:15 | x | semmle.label | x | +| lib/index.rb:11:16:11:16 | x | semmle.label | x | subpaths #select | PolynomialReDoS.rb:10:5:10:17 | ... =~ ... | PolynomialReDoS.rb:4:12:4:17 | call to params : | PolynomialReDoS.rb:10:5:10:8 | name | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | PolynomialReDoS.rb:7:19:7:21 | \\s+ | regular expression | PolynomialReDoS.rb:4:12:4:17 | call to params | user-provided value | @@ -109,3 +123,4 @@ subpaths | PolynomialReDoS.rb:77:5:77:22 | call to gsub | PolynomialReDoS.rb:70:12:70:17 | call to params : | PolynomialReDoS.rb:77:5:77:9 | input | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | PolynomialReDoS.rb:72:28:72:30 | \\s+ | regular expression | PolynomialReDoS.rb:70:12:70:17 | call to params | user-provided value | | lib/index.rb:4:13:4:26 | call to match | lib/index.rb:2:11:2:11 | x : | lib/index.rb:4:13:4:13 | x | This $@ that depends on a $@ may run slow on strings with many repetitions of 'a'. | lib/index.rb:4:22:4:23 | a+ | regular expression | lib/index.rb:2:11:2:11 | x | library input | | lib/index.rb:9:15:9:28 | call to match | lib/index.rb:8:13:8:13 | x : | lib/index.rb:9:15:9:15 | x | This $@ that depends on a $@ may run slow on strings with many repetitions of 'a'. | lib/index.rb:9:24:9:25 | a+ | regular expression | lib/index.rb:8:13:8:13 | x | library input | +| lib/index.rb:11:16:11:276 | call to match | lib/index.rb:8:13:8:13 | x : | lib/index.rb:11:16:11:16 | x | This $@ that depends on a $@ may run slow on strings starting with 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC' and with many repetitions of 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC'. | lib/index.rb:11:271:11:272 | .* | regular expression | lib/index.rb:8:13:8:13 | x | library input | diff --git a/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/lib/index.rb b/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/lib/index.rb index 5fb919ecf67..b6bf9570f4d 100644 --- a/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/lib/index.rb +++ b/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/lib/index.rb @@ -7,5 +7,7 @@ module Foo protected def baz(x) match = x.match(/a+$/) + + match2 = x.match(/(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)(AA|BB)C.*Y$/) end end \ No newline at end of file diff --git a/ruby/ql/test/query-tests/security/cwe-1333-regexp-injection/RegExpInjection.expected b/ruby/ql/test/query-tests/security/cwe-1333-regexp-injection/RegExpInjection.expected index 80c434f8002..8318c0a8ec8 100644 --- a/ruby/ql/test/query-tests/security/cwe-1333-regexp-injection/RegExpInjection.expected +++ b/ruby/ql/test/query-tests/security/cwe-1333-regexp-injection/RegExpInjection.expected @@ -1,27 +1,37 @@ edges +| RegExpInjection.rb:4:5:4:8 | name : | RegExpInjection.rb:5:13:5:21 | /#{...}/ | | RegExpInjection.rb:4:12:4:17 | call to params : | RegExpInjection.rb:4:12:4:24 | ...[...] : | -| RegExpInjection.rb:4:12:4:24 | ...[...] : | RegExpInjection.rb:5:13:5:21 | /#{...}/ | +| RegExpInjection.rb:4:12:4:24 | ...[...] : | RegExpInjection.rb:4:5:4:8 | name : | +| RegExpInjection.rb:10:5:10:8 | name : | RegExpInjection.rb:11:13:11:27 | /foo#{...}bar/ | | RegExpInjection.rb:10:12:10:17 | call to params : | RegExpInjection.rb:10:12:10:24 | ...[...] : | -| RegExpInjection.rb:10:12:10:24 | ...[...] : | RegExpInjection.rb:11:13:11:27 | /foo#{...}bar/ | +| RegExpInjection.rb:10:12:10:24 | ...[...] : | RegExpInjection.rb:10:5:10:8 | name : | +| RegExpInjection.rb:16:5:16:8 | name : | RegExpInjection.rb:17:24:17:27 | name | | RegExpInjection.rb:16:12:16:17 | call to params : | RegExpInjection.rb:16:12:16:24 | ...[...] : | -| RegExpInjection.rb:16:12:16:24 | ...[...] : | RegExpInjection.rb:17:24:17:27 | name | +| RegExpInjection.rb:16:12:16:24 | ...[...] : | RegExpInjection.rb:16:5:16:8 | name : | +| RegExpInjection.rb:22:5:22:8 | name : | RegExpInjection.rb:23:24:23:33 | ... + ... | | RegExpInjection.rb:22:12:22:17 | call to params : | RegExpInjection.rb:22:12:22:24 | ...[...] : | -| RegExpInjection.rb:22:12:22:24 | ...[...] : | RegExpInjection.rb:23:24:23:33 | ... + ... | +| RegExpInjection.rb:22:12:22:24 | ...[...] : | RegExpInjection.rb:22:5:22:8 | name : | +| RegExpInjection.rb:54:5:54:8 | name : | RegExpInjection.rb:55:28:55:37 | ... + ... | | RegExpInjection.rb:54:12:54:17 | call to params : | RegExpInjection.rb:54:12:54:24 | ...[...] : | -| RegExpInjection.rb:54:12:54:24 | ...[...] : | RegExpInjection.rb:55:28:55:37 | ... + ... | +| RegExpInjection.rb:54:12:54:24 | ...[...] : | RegExpInjection.rb:54:5:54:8 | name : | nodes +| RegExpInjection.rb:4:5:4:8 | name : | semmle.label | name : | | RegExpInjection.rb:4:12:4:17 | call to params : | semmle.label | call to params : | | RegExpInjection.rb:4:12:4:24 | ...[...] : | semmle.label | ...[...] : | | RegExpInjection.rb:5:13:5:21 | /#{...}/ | semmle.label | /#{...}/ | +| RegExpInjection.rb:10:5:10:8 | name : | semmle.label | name : | | RegExpInjection.rb:10:12:10:17 | call to params : | semmle.label | call to params : | | RegExpInjection.rb:10:12:10:24 | ...[...] : | semmle.label | ...[...] : | | RegExpInjection.rb:11:13:11:27 | /foo#{...}bar/ | semmle.label | /foo#{...}bar/ | +| RegExpInjection.rb:16:5:16:8 | name : | semmle.label | name : | | RegExpInjection.rb:16:12:16:17 | call to params : | semmle.label | call to params : | | RegExpInjection.rb:16:12:16:24 | ...[...] : | semmle.label | ...[...] : | | RegExpInjection.rb:17:24:17:27 | name | semmle.label | name | +| RegExpInjection.rb:22:5:22:8 | name : | semmle.label | name : | | RegExpInjection.rb:22:12:22:17 | call to params : | semmle.label | call to params : | | RegExpInjection.rb:22:12:22:24 | ...[...] : | semmle.label | ...[...] : | | RegExpInjection.rb:23:24:23:33 | ... + ... | semmle.label | ... + ... | +| RegExpInjection.rb:54:5:54:8 | name : | semmle.label | name : | | RegExpInjection.rb:54:12:54:17 | call to params : | semmle.label | call to params : | | RegExpInjection.rb:54:12:54:24 | ...[...] : | semmle.label | ...[...] : | | RegExpInjection.rb:55:28:55:37 | ... + ... | semmle.label | ... + ... | diff --git a/ruby/ql/test/query-tests/security/cwe-209/StackTraceExposure.expected b/ruby/ql/test/query-tests/security/cwe-209/StackTraceExposure.expected index 0dba484c65a..532c7752905 100644 --- a/ruby/ql/test/query-tests/security/cwe-209/StackTraceExposure.expected +++ b/ruby/ql/test/query-tests/security/cwe-209/StackTraceExposure.expected @@ -1,7 +1,9 @@ edges -| StackTraceExposure.rb:11:10:11:17 | call to caller : | StackTraceExposure.rb:12:18:12:19 | bt | +| StackTraceExposure.rb:11:5:11:6 | bt : | StackTraceExposure.rb:12:18:12:19 | bt | +| StackTraceExposure.rb:11:10:11:17 | call to caller : | StackTraceExposure.rb:11:5:11:6 | bt : | nodes | StackTraceExposure.rb:6:18:6:28 | call to backtrace | semmle.label | call to backtrace | +| StackTraceExposure.rb:11:5:11:6 | bt : | semmle.label | bt : | | StackTraceExposure.rb:11:10:11:17 | call to caller : | semmle.label | call to caller : | | StackTraceExposure.rb:12:18:12:19 | bt | semmle.label | bt | | StackTraceExposure.rb:18:18:18:28 | call to backtrace | semmle.label | call to backtrace | diff --git a/ruby/ql/test/query-tests/security/cwe-312/CleartextLogging.expected b/ruby/ql/test/query-tests/security/cwe-312/CleartextLogging.expected index 2931f4869c4..90968a06b2b 100644 --- a/ruby/ql/test/query-tests/security/cwe-312/CleartextLogging.expected +++ b/ruby/ql/test/query-tests/security/cwe-312/CleartextLogging.expected @@ -1,34 +1,45 @@ edges -| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : | logging.rb:6:20:6:27 | password | -| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : | logging.rb:8:21:8:28 | password | -| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : | logging.rb:10:21:10:28 | password | -| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : | logging.rb:12:21:12:28 | password | -| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : | logging.rb:14:23:14:30 | password | -| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : | logging.rb:16:20:16:27 | password | -| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : | logging.rb:19:33:19:40 | password | -| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : | logging.rb:21:44:21:51 | password | -| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : | logging.rb:23:33:23:40 | password | -| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : | logging.rb:26:18:26:34 | "pw: #{...}" | -| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : | logging.rb:28:26:28:33 | password | -| logging.rb:30:20:30:53 | "aec5058e61f7f122998b1a30ee2c66b6" : | logging.rb:38:20:38:23 | hsh1 [element :password] : | +| logging.rb:3:1:3:8 | password : | logging.rb:6:20:6:27 | password | +| logging.rb:3:1:3:8 | password : | logging.rb:8:21:8:28 | password | +| logging.rb:3:1:3:8 | password : | logging.rb:10:21:10:28 | password | +| logging.rb:3:1:3:8 | password : | logging.rb:12:21:12:28 | password | +| logging.rb:3:1:3:8 | password : | logging.rb:14:23:14:30 | password | +| logging.rb:3:1:3:8 | password : | logging.rb:16:20:16:27 | password | +| logging.rb:3:1:3:8 | password : | logging.rb:19:33:19:40 | password | +| logging.rb:3:1:3:8 | password : | logging.rb:21:44:21:51 | password | +| logging.rb:3:1:3:8 | password : | logging.rb:23:33:23:40 | password | +| logging.rb:3:1:3:8 | password : | logging.rb:26:18:26:34 | "pw: #{...}" | +| logging.rb:3:1:3:8 | password : | logging.rb:28:26:28:33 | password | +| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : | logging.rb:3:1:3:8 | password : | +| logging.rb:30:1:30:4 | hsh1 [element :password] : | logging.rb:38:20:38:23 | hsh1 [element :password] : | +| logging.rb:30:20:30:53 | "aec5058e61f7f122998b1a30ee2c66b6" : | logging.rb:30:1:30:4 | hsh1 [element :password] : | +| logging.rb:34:1:34:4 | [post] hsh2 [element :password] : | logging.rb:35:1:35:4 | hsh3 [element :password] : | | logging.rb:34:1:34:4 | [post] hsh2 [element :password] : | logging.rb:40:20:40:23 | hsh2 [element :password] : | -| logging.rb:34:1:34:4 | [post] hsh2 [element :password] : | logging.rb:42:20:42:23 | hsh3 [element :password] : | | logging.rb:34:19:34:52 | "beeda625d7306b45784d91ea0336e201" : | logging.rb:34:1:34:4 | [post] hsh2 [element :password] : | +| logging.rb:35:1:35:4 | hsh3 [element :password] : | logging.rb:42:20:42:23 | hsh3 [element :password] : | | logging.rb:38:20:38:23 | hsh1 [element :password] : | logging.rb:38:20:38:34 | ...[...] | | logging.rb:40:20:40:23 | hsh2 [element :password] : | logging.rb:40:20:40:34 | ...[...] | | logging.rb:42:20:42:23 | hsh3 [element :password] : | logging.rb:42:20:42:34 | ...[...] | -| logging.rb:64:35:64:68 | "ca497451f5e883662fb1a37bc9ec7838" : | logging.rb:68:35:68:65 | password_masked_ineffective_sub : | -| logging.rb:65:38:65:71 | "ca497451f5e883662fb1a37bc9ec7838" : | logging.rb:78:20:78:53 | password_masked_ineffective_sub_ex | -| logging.rb:66:36:66:69 | "a7e3747b19930d4f4b8181047194832f" : | logging.rb:70:36:70:67 | password_masked_ineffective_gsub : | -| logging.rb:67:39:67:72 | "a7e3747b19930d4f4b8181047194832f" : | logging.rb:80:20:80:54 | password_masked_ineffective_gsub_ex | +| logging.rb:64:1:64:31 | password_masked_ineffective_sub : | logging.rb:68:35:68:65 | password_masked_ineffective_sub : | +| logging.rb:64:35:64:68 | "ca497451f5e883662fb1a37bc9ec7838" : | logging.rb:64:1:64:31 | password_masked_ineffective_sub : | +| logging.rb:65:1:65:34 | password_masked_ineffective_sub_ex : | logging.rb:78:20:78:53 | password_masked_ineffective_sub_ex | +| logging.rb:65:38:65:71 | "ca497451f5e883662fb1a37bc9ec7838" : | logging.rb:65:1:65:34 | password_masked_ineffective_sub_ex : | +| logging.rb:66:1:66:32 | password_masked_ineffective_gsub : | logging.rb:70:36:70:67 | password_masked_ineffective_gsub : | +| logging.rb:66:36:66:69 | "a7e3747b19930d4f4b8181047194832f" : | logging.rb:66:1:66:32 | password_masked_ineffective_gsub : | +| logging.rb:67:1:67:35 | password_masked_ineffective_gsub_ex : | logging.rb:80:20:80:54 | password_masked_ineffective_gsub_ex | +| logging.rb:67:39:67:72 | "a7e3747b19930d4f4b8181047194832f" : | logging.rb:67:1:67:35 | password_masked_ineffective_gsub_ex : | +| logging.rb:68:1:68:31 | password_masked_ineffective_sub : | logging.rb:74:20:74:50 | password_masked_ineffective_sub | | logging.rb:68:35:68:65 | password_masked_ineffective_sub : | logging.rb:68:35:68:88 | call to sub : | -| logging.rb:68:35:68:88 | call to sub : | logging.rb:74:20:74:50 | password_masked_ineffective_sub | +| logging.rb:68:35:68:88 | call to sub : | logging.rb:68:1:68:31 | password_masked_ineffective_sub : | +| logging.rb:70:1:70:32 | password_masked_ineffective_gsub : | logging.rb:76:20:76:51 | password_masked_ineffective_gsub | | logging.rb:70:36:70:67 | password_masked_ineffective_gsub : | logging.rb:70:36:70:86 | call to gsub : | -| logging.rb:70:36:70:86 | call to gsub : | logging.rb:76:20:76:51 | password_masked_ineffective_gsub | +| logging.rb:70:36:70:86 | call to gsub : | logging.rb:70:1:70:32 | password_masked_ineffective_gsub : | | logging.rb:82:9:82:16 | password : | logging.rb:84:15:84:22 | password | -| logging.rb:87:16:87:49 | "65f2950df2f0e2c38d7ba2ccca767291" : | logging.rb:88:5:88:16 | password_arg : | +| logging.rb:87:1:87:12 | password_arg : | logging.rb:88:5:88:16 | password_arg : | +| logging.rb:87:16:87:49 | "65f2950df2f0e2c38d7ba2ccca767291" : | logging.rb:87:1:87:12 | password_arg : | | logging.rb:88:5:88:16 | password_arg : | logging.rb:82:9:82:16 | password : | nodes +| logging.rb:3:1:3:8 | password : | semmle.label | password : | | logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" : | semmle.label | "043697b96909e03ca907599d6420555f" : | | logging.rb:6:20:6:27 | password | semmle.label | password | | logging.rb:8:21:8:28 | password | semmle.label | password | @@ -41,21 +52,29 @@ nodes | logging.rb:23:33:23:40 | password | semmle.label | password | | logging.rb:26:18:26:34 | "pw: #{...}" | semmle.label | "pw: #{...}" | | logging.rb:28:26:28:33 | password | semmle.label | password | +| logging.rb:30:1:30:4 | hsh1 [element :password] : | semmle.label | hsh1 [element :password] : | | logging.rb:30:20:30:53 | "aec5058e61f7f122998b1a30ee2c66b6" : | semmle.label | "aec5058e61f7f122998b1a30ee2c66b6" : | | logging.rb:34:1:34:4 | [post] hsh2 [element :password] : | semmle.label | [post] hsh2 [element :password] : | | logging.rb:34:19:34:52 | "beeda625d7306b45784d91ea0336e201" : | semmle.label | "beeda625d7306b45784d91ea0336e201" : | +| logging.rb:35:1:35:4 | hsh3 [element :password] : | semmle.label | hsh3 [element :password] : | | logging.rb:38:20:38:23 | hsh1 [element :password] : | semmle.label | hsh1 [element :password] : | | logging.rb:38:20:38:34 | ...[...] | semmle.label | ...[...] | | logging.rb:40:20:40:23 | hsh2 [element :password] : | semmle.label | hsh2 [element :password] : | | logging.rb:40:20:40:34 | ...[...] | semmle.label | ...[...] | | logging.rb:42:20:42:23 | hsh3 [element :password] : | semmle.label | hsh3 [element :password] : | | logging.rb:42:20:42:34 | ...[...] | semmle.label | ...[...] | +| logging.rb:64:1:64:31 | password_masked_ineffective_sub : | semmle.label | password_masked_ineffective_sub : | | logging.rb:64:35:64:68 | "ca497451f5e883662fb1a37bc9ec7838" : | semmle.label | "ca497451f5e883662fb1a37bc9ec7838" : | +| logging.rb:65:1:65:34 | password_masked_ineffective_sub_ex : | semmle.label | password_masked_ineffective_sub_ex : | | logging.rb:65:38:65:71 | "ca497451f5e883662fb1a37bc9ec7838" : | semmle.label | "ca497451f5e883662fb1a37bc9ec7838" : | +| logging.rb:66:1:66:32 | password_masked_ineffective_gsub : | semmle.label | password_masked_ineffective_gsub : | | logging.rb:66:36:66:69 | "a7e3747b19930d4f4b8181047194832f" : | semmle.label | "a7e3747b19930d4f4b8181047194832f" : | +| logging.rb:67:1:67:35 | password_masked_ineffective_gsub_ex : | semmle.label | password_masked_ineffective_gsub_ex : | | logging.rb:67:39:67:72 | "a7e3747b19930d4f4b8181047194832f" : | semmle.label | "a7e3747b19930d4f4b8181047194832f" : | +| logging.rb:68:1:68:31 | password_masked_ineffective_sub : | semmle.label | password_masked_ineffective_sub : | | logging.rb:68:35:68:65 | password_masked_ineffective_sub : | semmle.label | password_masked_ineffective_sub : | | logging.rb:68:35:68:88 | call to sub : | semmle.label | call to sub : | +| logging.rb:70:1:70:32 | password_masked_ineffective_gsub : | semmle.label | password_masked_ineffective_gsub : | | logging.rb:70:36:70:67 | password_masked_ineffective_gsub : | semmle.label | password_masked_ineffective_gsub : | | logging.rb:70:36:70:86 | call to gsub : | semmle.label | call to gsub : | | logging.rb:74:20:74:50 | password_masked_ineffective_sub | semmle.label | password_masked_ineffective_sub | @@ -64,6 +83,7 @@ nodes | logging.rb:80:20:80:54 | password_masked_ineffective_gsub_ex | semmle.label | password_masked_ineffective_gsub_ex | | logging.rb:82:9:82:16 | password : | semmle.label | password : | | logging.rb:84:15:84:22 | password | semmle.label | password | +| logging.rb:87:1:87:12 | password_arg : | semmle.label | password_arg : | | logging.rb:87:16:87:49 | "65f2950df2f0e2c38d7ba2ccca767291" : | semmle.label | "65f2950df2f0e2c38d7ba2ccca767291" : | | logging.rb:88:5:88:16 | password_arg : | semmle.label | password_arg : | subpaths diff --git a/ruby/ql/test/query-tests/security/cwe-312/CleartextStorage.expected b/ruby/ql/test/query-tests/security/cwe-312/CleartextStorage.expected index 39f771ed08d..9f8f849b10a 100644 --- a/ruby/ql/test/query-tests/security/cwe-312/CleartextStorage.expected +++ b/ruby/ql/test/query-tests/security/cwe-312/CleartextStorage.expected @@ -1,51 +1,71 @@ edges -| app/controllers/users_controller.rb:3:20:3:53 | "043697b96909e03ca907599d6420555f" : | app/controllers/users_controller.rb:5:39:5:50 | new_password | -| app/controllers/users_controller.rb:3:20:3:53 | "043697b96909e03ca907599d6420555f" : | app/controllers/users_controller.rb:7:41:7:52 | new_password | -| app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" : | app/controllers/users_controller.rb:13:42:13:53 | new_password | -| app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" : | app/controllers/users_controller.rb:15:49:15:60 | new_password | -| app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" : | app/controllers/users_controller.rb:15:49:15:60 | new_password : | -| app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" : | app/controllers/users_controller.rb:15:87:15:98 | new_password | +| app/controllers/users_controller.rb:3:5:3:16 | new_password : | app/controllers/users_controller.rb:5:39:5:50 | new_password | +| app/controllers/users_controller.rb:3:5:3:16 | new_password : | app/controllers/users_controller.rb:7:41:7:52 | new_password | +| app/controllers/users_controller.rb:3:20:3:53 | "043697b96909e03ca907599d6420555f" : | app/controllers/users_controller.rb:3:5:3:16 | new_password : | +| app/controllers/users_controller.rb:11:5:11:16 | new_password : | app/controllers/users_controller.rb:13:42:13:53 | new_password | +| app/controllers/users_controller.rb:11:5:11:16 | new_password : | app/controllers/users_controller.rb:15:49:15:60 | new_password | +| app/controllers/users_controller.rb:11:5:11:16 | new_password : | app/controllers/users_controller.rb:15:49:15:60 | new_password : | +| app/controllers/users_controller.rb:11:5:11:16 | new_password : | app/controllers/users_controller.rb:15:87:15:98 | new_password | +| app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" : | app/controllers/users_controller.rb:11:5:11:16 | new_password : | | app/controllers/users_controller.rb:15:49:15:60 | new_password : | app/controllers/users_controller.rb:15:87:15:98 | new_password | -| app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" : | app/controllers/users_controller.rb:21:45:21:56 | new_password | -| app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" : | app/controllers/users_controller.rb:21:45:21:56 | new_password : | -| app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" : | app/controllers/users_controller.rb:21:83:21:94 | new_password | +| app/controllers/users_controller.rb:19:5:19:16 | new_password : | app/controllers/users_controller.rb:21:45:21:56 | new_password | +| app/controllers/users_controller.rb:19:5:19:16 | new_password : | app/controllers/users_controller.rb:21:45:21:56 | new_password : | +| app/controllers/users_controller.rb:19:5:19:16 | new_password : | app/controllers/users_controller.rb:21:83:21:94 | new_password | +| app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" : | app/controllers/users_controller.rb:19:5:19:16 | new_password : | | app/controllers/users_controller.rb:21:45:21:56 | new_password : | app/controllers/users_controller.rb:21:83:21:94 | new_password | -| app/controllers/users_controller.rb:26:20:26:53 | "7d6ae08394c3f284506dca70f05995f6" : | app/controllers/users_controller.rb:28:27:28:38 | new_password | -| app/controllers/users_controller.rb:26:20:26:53 | "7d6ae08394c3f284506dca70f05995f6" : | app/controllers/users_controller.rb:30:28:30:39 | new_password | -| app/controllers/users_controller.rb:35:20:35:53 | "ff295f8648a406c37fbe378377320e4c" : | app/controllers/users_controller.rb:37:39:37:50 | new_password | -| app/controllers/users_controller.rb:42:20:42:53 | "78ffbec583b546bd073efd898f833184" : | app/controllers/users_controller.rb:44:21:44:32 | new_password | -| app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" : | app/controllers/users_controller.rb:61:25:61:53 | "password: #{...}\\n" | -| app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" : | app/controllers/users_controller.rb:64:35:64:61 | "password: #{...}" | -| app/models/user.rb:3:20:3:53 | "06c38c6a8a9c11a9d3b209a3193047b4" : | app/models/user.rb:5:27:5:38 | new_password | -| app/models/user.rb:9:20:9:53 | "52652fb5c709fb6b9b5a0194af7c6067" : | app/models/user.rb:11:22:11:33 | new_password | -| app/models/user.rb:15:20:15:53 | "f982bf2531c149a8a1444a951b12e830" : | app/models/user.rb:17:21:17:32 | new_password | +| app/controllers/users_controller.rb:26:5:26:16 | new_password : | app/controllers/users_controller.rb:28:27:28:38 | new_password | +| app/controllers/users_controller.rb:26:5:26:16 | new_password : | app/controllers/users_controller.rb:30:28:30:39 | new_password | +| app/controllers/users_controller.rb:26:20:26:53 | "7d6ae08394c3f284506dca70f05995f6" : | app/controllers/users_controller.rb:26:5:26:16 | new_password : | +| app/controllers/users_controller.rb:35:5:35:16 | new_password : | app/controllers/users_controller.rb:37:39:37:50 | new_password | +| app/controllers/users_controller.rb:35:20:35:53 | "ff295f8648a406c37fbe378377320e4c" : | app/controllers/users_controller.rb:35:5:35:16 | new_password : | +| app/controllers/users_controller.rb:42:5:42:16 | new_password : | app/controllers/users_controller.rb:44:21:44:32 | new_password | +| app/controllers/users_controller.rb:42:20:42:53 | "78ffbec583b546bd073efd898f833184" : | app/controllers/users_controller.rb:42:5:42:16 | new_password : | +| app/controllers/users_controller.rb:58:5:58:16 | new_password : | app/controllers/users_controller.rb:61:25:61:53 | "password: #{...}\\n" | +| app/controllers/users_controller.rb:58:5:58:16 | new_password : | app/controllers/users_controller.rb:64:35:64:61 | "password: #{...}" | +| app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" : | app/controllers/users_controller.rb:58:5:58:16 | new_password : | +| app/models/user.rb:3:5:3:16 | new_password : | app/models/user.rb:5:27:5:38 | new_password | +| app/models/user.rb:3:20:3:53 | "06c38c6a8a9c11a9d3b209a3193047b4" : | app/models/user.rb:3:5:3:16 | new_password : | +| app/models/user.rb:9:5:9:16 | new_password : | app/models/user.rb:11:22:11:33 | new_password | +| app/models/user.rb:9:20:9:53 | "52652fb5c709fb6b9b5a0194af7c6067" : | app/models/user.rb:9:5:9:16 | new_password : | +| app/models/user.rb:15:5:15:16 | new_password : | app/models/user.rb:17:21:17:32 | new_password | +| app/models/user.rb:15:20:15:53 | "f982bf2531c149a8a1444a951b12e830" : | app/models/user.rb:15:5:15:16 | new_password : | nodes +| app/controllers/users_controller.rb:3:5:3:16 | new_password : | semmle.label | new_password : | | app/controllers/users_controller.rb:3:20:3:53 | "043697b96909e03ca907599d6420555f" : | semmle.label | "043697b96909e03ca907599d6420555f" : | | app/controllers/users_controller.rb:5:39:5:50 | new_password | semmle.label | new_password | | app/controllers/users_controller.rb:7:41:7:52 | new_password | semmle.label | new_password | +| app/controllers/users_controller.rb:11:5:11:16 | new_password : | semmle.label | new_password : | | app/controllers/users_controller.rb:11:20:11:53 | "083c9e1da4cc0c2f5480bb4dbe6ff141" : | semmle.label | "083c9e1da4cc0c2f5480bb4dbe6ff141" : | | app/controllers/users_controller.rb:13:42:13:53 | new_password | semmle.label | new_password | | app/controllers/users_controller.rb:15:49:15:60 | new_password | semmle.label | new_password | | app/controllers/users_controller.rb:15:49:15:60 | new_password : | semmle.label | new_password : | | app/controllers/users_controller.rb:15:87:15:98 | new_password | semmle.label | new_password | +| app/controllers/users_controller.rb:19:5:19:16 | new_password : | semmle.label | new_password : | | app/controllers/users_controller.rb:19:20:19:53 | "504d224a806cf8073cd14ef08242d422" : | semmle.label | "504d224a806cf8073cd14ef08242d422" : | | app/controllers/users_controller.rb:21:45:21:56 | new_password | semmle.label | new_password | | app/controllers/users_controller.rb:21:45:21:56 | new_password : | semmle.label | new_password : | | app/controllers/users_controller.rb:21:83:21:94 | new_password | semmle.label | new_password | +| app/controllers/users_controller.rb:26:5:26:16 | new_password : | semmle.label | new_password : | | app/controllers/users_controller.rb:26:20:26:53 | "7d6ae08394c3f284506dca70f05995f6" : | semmle.label | "7d6ae08394c3f284506dca70f05995f6" : | | app/controllers/users_controller.rb:28:27:28:38 | new_password | semmle.label | new_password | | app/controllers/users_controller.rb:30:28:30:39 | new_password | semmle.label | new_password | +| app/controllers/users_controller.rb:35:5:35:16 | new_password : | semmle.label | new_password : | | app/controllers/users_controller.rb:35:20:35:53 | "ff295f8648a406c37fbe378377320e4c" : | semmle.label | "ff295f8648a406c37fbe378377320e4c" : | | app/controllers/users_controller.rb:37:39:37:50 | new_password | semmle.label | new_password | +| app/controllers/users_controller.rb:42:5:42:16 | new_password : | semmle.label | new_password : | | app/controllers/users_controller.rb:42:20:42:53 | "78ffbec583b546bd073efd898f833184" : | semmle.label | "78ffbec583b546bd073efd898f833184" : | | app/controllers/users_controller.rb:44:21:44:32 | new_password | semmle.label | new_password | +| app/controllers/users_controller.rb:58:5:58:16 | new_password : | semmle.label | new_password : | | app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" : | semmle.label | "0157af7c38cbdd24f1616de4e5321861" : | | app/controllers/users_controller.rb:61:25:61:53 | "password: #{...}\\n" | semmle.label | "password: #{...}\\n" | | app/controllers/users_controller.rb:64:35:64:61 | "password: #{...}" | semmle.label | "password: #{...}" | +| app/models/user.rb:3:5:3:16 | new_password : | semmle.label | new_password : | | app/models/user.rb:3:20:3:53 | "06c38c6a8a9c11a9d3b209a3193047b4" : | semmle.label | "06c38c6a8a9c11a9d3b209a3193047b4" : | | app/models/user.rb:5:27:5:38 | new_password | semmle.label | new_password | +| app/models/user.rb:9:5:9:16 | new_password : | semmle.label | new_password : | | app/models/user.rb:9:20:9:53 | "52652fb5c709fb6b9b5a0194af7c6067" : | semmle.label | "52652fb5c709fb6b9b5a0194af7c6067" : | | app/models/user.rb:11:22:11:33 | new_password | semmle.label | new_password | +| app/models/user.rb:15:5:15:16 | new_password : | semmle.label | new_password : | | app/models/user.rb:15:20:15:53 | "f982bf2531c149a8a1444a951b12e830" : | semmle.label | "f982bf2531c149a8a1444a951b12e830" : | | app/models/user.rb:17:21:17:32 | new_password | semmle.label | new_password | subpaths diff --git a/ruby/ql/test/query-tests/security/cwe-502/oj-global-options/UnsafeDeserialization.expected b/ruby/ql/test/query-tests/security/cwe-502/oj-global-options/UnsafeDeserialization.expected index 72c25575a21..38499665118 100644 --- a/ruby/ql/test/query-tests/security/cwe-502/oj-global-options/UnsafeDeserialization.expected +++ b/ruby/ql/test/query-tests/security/cwe-502/oj-global-options/UnsafeDeserialization.expected @@ -1,7 +1,9 @@ edges +| OjGlobalOptions.rb:13:5:13:13 | json_data : | OjGlobalOptions.rb:14:22:14:30 | json_data | | OjGlobalOptions.rb:13:17:13:22 | call to params : | OjGlobalOptions.rb:13:17:13:28 | ...[...] : | -| OjGlobalOptions.rb:13:17:13:28 | ...[...] : | OjGlobalOptions.rb:14:22:14:30 | json_data | +| OjGlobalOptions.rb:13:17:13:28 | ...[...] : | OjGlobalOptions.rb:13:5:13:13 | json_data : | nodes +| OjGlobalOptions.rb:13:5:13:13 | json_data : | semmle.label | json_data : | | OjGlobalOptions.rb:13:17:13:22 | call to params : | semmle.label | call to params : | | OjGlobalOptions.rb:13:17:13:28 | ...[...] : | semmle.label | ...[...] : | | OjGlobalOptions.rb:14:22:14:30 | json_data | semmle.label | json_data | diff --git a/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.expected b/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.expected index fe4addd5d4d..13fe16295d9 100644 --- a/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.expected +++ b/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.expected @@ -1,53 +1,71 @@ edges -| UnsafeDeserialization.rb:10:23:10:50 | call to decode64 : | UnsafeDeserialization.rb:11:27:11:41 | serialized_data | +| UnsafeDeserialization.rb:10:5:10:19 | serialized_data : | UnsafeDeserialization.rb:11:27:11:41 | serialized_data | +| UnsafeDeserialization.rb:10:23:10:50 | call to decode64 : | UnsafeDeserialization.rb:10:5:10:19 | serialized_data : | | UnsafeDeserialization.rb:10:39:10:44 | call to params : | UnsafeDeserialization.rb:10:39:10:50 | ...[...] : | | UnsafeDeserialization.rb:10:39:10:50 | ...[...] : | UnsafeDeserialization.rb:10:23:10:50 | call to decode64 : | -| UnsafeDeserialization.rb:16:23:16:50 | call to decode64 : | UnsafeDeserialization.rb:17:30:17:44 | serialized_data | +| UnsafeDeserialization.rb:16:5:16:19 | serialized_data : | UnsafeDeserialization.rb:17:30:17:44 | serialized_data | +| UnsafeDeserialization.rb:16:23:16:50 | call to decode64 : | UnsafeDeserialization.rb:16:5:16:19 | serialized_data : | | UnsafeDeserialization.rb:16:39:16:44 | call to params : | UnsafeDeserialization.rb:16:39:16:50 | ...[...] : | | UnsafeDeserialization.rb:16:39:16:50 | ...[...] : | UnsafeDeserialization.rb:16:23:16:50 | call to decode64 : | +| UnsafeDeserialization.rb:22:5:22:13 | json_data : | UnsafeDeserialization.rb:23:24:23:32 | json_data | | UnsafeDeserialization.rb:22:17:22:22 | call to params : | UnsafeDeserialization.rb:22:17:22:28 | ...[...] : | -| UnsafeDeserialization.rb:22:17:22:28 | ...[...] : | UnsafeDeserialization.rb:23:24:23:32 | json_data | +| UnsafeDeserialization.rb:22:17:22:28 | ...[...] : | UnsafeDeserialization.rb:22:5:22:13 | json_data : | +| UnsafeDeserialization.rb:28:5:28:13 | json_data : | UnsafeDeserialization.rb:29:27:29:35 | json_data | | UnsafeDeserialization.rb:28:17:28:22 | call to params : | UnsafeDeserialization.rb:28:17:28:28 | ...[...] : | -| UnsafeDeserialization.rb:28:17:28:28 | ...[...] : | UnsafeDeserialization.rb:29:27:29:35 | json_data | +| UnsafeDeserialization.rb:28:17:28:28 | ...[...] : | UnsafeDeserialization.rb:28:5:28:13 | json_data : | +| UnsafeDeserialization.rb:40:5:40:13 | yaml_data : | UnsafeDeserialization.rb:41:24:41:32 | yaml_data | | UnsafeDeserialization.rb:40:17:40:22 | call to params : | UnsafeDeserialization.rb:40:17:40:28 | ...[...] : | -| UnsafeDeserialization.rb:40:17:40:28 | ...[...] : | UnsafeDeserialization.rb:41:24:41:32 | yaml_data | +| UnsafeDeserialization.rb:40:17:40:28 | ...[...] : | UnsafeDeserialization.rb:40:5:40:13 | yaml_data : | +| UnsafeDeserialization.rb:52:5:52:13 | json_data : | UnsafeDeserialization.rb:53:22:53:30 | json_data | +| UnsafeDeserialization.rb:52:5:52:13 | json_data : | UnsafeDeserialization.rb:54:22:54:30 | json_data | | UnsafeDeserialization.rb:52:17:52:22 | call to params : | UnsafeDeserialization.rb:52:17:52:28 | ...[...] : | -| UnsafeDeserialization.rb:52:17:52:28 | ...[...] : | UnsafeDeserialization.rb:53:22:53:30 | json_data | -| UnsafeDeserialization.rb:52:17:52:28 | ...[...] : | UnsafeDeserialization.rb:54:22:54:30 | json_data | +| UnsafeDeserialization.rb:52:17:52:28 | ...[...] : | UnsafeDeserialization.rb:52:5:52:13 | json_data : | +| UnsafeDeserialization.rb:59:5:59:13 | json_data : | UnsafeDeserialization.rb:69:23:69:31 | json_data | | UnsafeDeserialization.rb:59:17:59:22 | call to params : | UnsafeDeserialization.rb:59:17:59:28 | ...[...] : | -| UnsafeDeserialization.rb:59:17:59:28 | ...[...] : | UnsafeDeserialization.rb:69:23:69:31 | json_data | +| UnsafeDeserialization.rb:59:17:59:28 | ...[...] : | UnsafeDeserialization.rb:59:5:59:13 | json_data : | +| UnsafeDeserialization.rb:81:5:81:7 | xml : | UnsafeDeserialization.rb:82:34:82:36 | xml | | UnsafeDeserialization.rb:81:11:81:16 | call to params : | UnsafeDeserialization.rb:81:11:81:22 | ...[...] : | -| UnsafeDeserialization.rb:81:11:81:22 | ...[...] : | UnsafeDeserialization.rb:82:34:82:36 | xml | +| UnsafeDeserialization.rb:81:11:81:22 | ...[...] : | UnsafeDeserialization.rb:81:5:81:7 | xml : | +| UnsafeDeserialization.rb:87:5:87:13 | yaml_data : | UnsafeDeserialization.rb:88:25:88:33 | yaml_data | | UnsafeDeserialization.rb:87:17:87:22 | call to params : | UnsafeDeserialization.rb:87:17:87:28 | ...[...] : | -| UnsafeDeserialization.rb:87:17:87:28 | ...[...] : | UnsafeDeserialization.rb:88:25:88:33 | yaml_data | +| UnsafeDeserialization.rb:87:17:87:28 | ...[...] : | UnsafeDeserialization.rb:87:5:87:13 | yaml_data : | nodes +| UnsafeDeserialization.rb:10:5:10:19 | serialized_data : | semmle.label | serialized_data : | | UnsafeDeserialization.rb:10:23:10:50 | call to decode64 : | semmle.label | call to decode64 : | | UnsafeDeserialization.rb:10:39:10:44 | call to params : | semmle.label | call to params : | | UnsafeDeserialization.rb:10:39:10:50 | ...[...] : | semmle.label | ...[...] : | | UnsafeDeserialization.rb:11:27:11:41 | serialized_data | semmle.label | serialized_data | +| UnsafeDeserialization.rb:16:5:16:19 | serialized_data : | semmle.label | serialized_data : | | UnsafeDeserialization.rb:16:23:16:50 | call to decode64 : | semmle.label | call to decode64 : | | UnsafeDeserialization.rb:16:39:16:44 | call to params : | semmle.label | call to params : | | UnsafeDeserialization.rb:16:39:16:50 | ...[...] : | semmle.label | ...[...] : | | UnsafeDeserialization.rb:17:30:17:44 | serialized_data | semmle.label | serialized_data | +| UnsafeDeserialization.rb:22:5:22:13 | json_data : | semmle.label | json_data : | | UnsafeDeserialization.rb:22:17:22:22 | call to params : | semmle.label | call to params : | | UnsafeDeserialization.rb:22:17:22:28 | ...[...] : | semmle.label | ...[...] : | | UnsafeDeserialization.rb:23:24:23:32 | json_data | semmle.label | json_data | +| UnsafeDeserialization.rb:28:5:28:13 | json_data : | semmle.label | json_data : | | UnsafeDeserialization.rb:28:17:28:22 | call to params : | semmle.label | call to params : | | UnsafeDeserialization.rb:28:17:28:28 | ...[...] : | semmle.label | ...[...] : | | UnsafeDeserialization.rb:29:27:29:35 | json_data | semmle.label | json_data | +| UnsafeDeserialization.rb:40:5:40:13 | yaml_data : | semmle.label | yaml_data : | | UnsafeDeserialization.rb:40:17:40:22 | call to params : | semmle.label | call to params : | | UnsafeDeserialization.rb:40:17:40:28 | ...[...] : | semmle.label | ...[...] : | | UnsafeDeserialization.rb:41:24:41:32 | yaml_data | semmle.label | yaml_data | +| UnsafeDeserialization.rb:52:5:52:13 | json_data : | semmle.label | json_data : | | UnsafeDeserialization.rb:52:17:52:22 | call to params : | semmle.label | call to params : | | UnsafeDeserialization.rb:52:17:52:28 | ...[...] : | semmle.label | ...[...] : | | UnsafeDeserialization.rb:53:22:53:30 | json_data | semmle.label | json_data | | UnsafeDeserialization.rb:54:22:54:30 | json_data | semmle.label | json_data | +| UnsafeDeserialization.rb:59:5:59:13 | json_data : | semmle.label | json_data : | | UnsafeDeserialization.rb:59:17:59:22 | call to params : | semmle.label | call to params : | | UnsafeDeserialization.rb:59:17:59:28 | ...[...] : | semmle.label | ...[...] : | | UnsafeDeserialization.rb:69:23:69:31 | json_data | semmle.label | json_data | +| UnsafeDeserialization.rb:81:5:81:7 | xml : | semmle.label | xml : | | UnsafeDeserialization.rb:81:11:81:16 | call to params : | semmle.label | call to params : | | UnsafeDeserialization.rb:81:11:81:22 | ...[...] : | semmle.label | ...[...] : | | UnsafeDeserialization.rb:82:34:82:36 | xml | semmle.label | xml | +| UnsafeDeserialization.rb:87:5:87:13 | yaml_data : | semmle.label | yaml_data : | | UnsafeDeserialization.rb:87:17:87:22 | call to params : | semmle.label | call to params : | | UnsafeDeserialization.rb:87:17:87:28 | ...[...] : | semmle.label | ...[...] : | | UnsafeDeserialization.rb:88:25:88:33 | yaml_data | semmle.label | yaml_data | diff --git a/ruby/ql/test/query-tests/security/cwe-506/HardcodedDataInterpretedAsCode.expected b/ruby/ql/test/query-tests/security/cwe-506/HardcodedDataInterpretedAsCode.expected index a52134aa7db..cf3cc204cbd 100644 --- a/ruby/ql/test/query-tests/security/cwe-506/HardcodedDataInterpretedAsCode.expected +++ b/ruby/ql/test/query-tests/security/cwe-506/HardcodedDataInterpretedAsCode.expected @@ -1,22 +1,26 @@ edges | tst.rb:1:7:1:7 | r : | tst.rb:2:4:2:4 | r : | | tst.rb:2:4:2:4 | r : | tst.rb:2:3:2:15 | call to pack : | -| tst.rb:5:27:5:72 | "707574732822636f646520696e6a6..." : | tst.rb:7:8:7:30 | totally_harmless_string : | +| tst.rb:5:1:5:23 | totally_harmless_string : | tst.rb:7:8:7:30 | totally_harmless_string : | +| tst.rb:5:27:5:72 | "707574732822636f646520696e6a6..." : | tst.rb:5:1:5:23 | totally_harmless_string : | | tst.rb:7:8:7:30 | totally_harmless_string : | tst.rb:1:7:1:7 | r : | | tst.rb:7:8:7:30 | totally_harmless_string : | tst.rb:7:6:7:31 | call to e | | tst.rb:10:11:10:24 | "666f6f626172" : | tst.rb:1:7:1:7 | r : | | tst.rb:10:11:10:24 | "666f6f626172" : | tst.rb:10:9:10:25 | call to e | -| tst.rb:16:31:16:84 | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." : | tst.rb:17:6:17:32 | another_questionable_string : | +| tst.rb:16:1:16:27 | another_questionable_string : | tst.rb:17:6:17:32 | another_questionable_string : | +| tst.rb:16:31:16:84 | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." : | tst.rb:16:1:16:27 | another_questionable_string : | | tst.rb:17:6:17:32 | another_questionable_string : | tst.rb:17:6:17:38 | call to strip | nodes | tst.rb:1:7:1:7 | r : | semmle.label | r : | | tst.rb:2:3:2:15 | call to pack : | semmle.label | call to pack : | | tst.rb:2:4:2:4 | r : | semmle.label | r : | +| tst.rb:5:1:5:23 | totally_harmless_string : | semmle.label | totally_harmless_string : | | tst.rb:5:27:5:72 | "707574732822636f646520696e6a6..." : | semmle.label | "707574732822636f646520696e6a6..." : | | tst.rb:7:6:7:31 | call to e | semmle.label | call to e | | tst.rb:7:8:7:30 | totally_harmless_string : | semmle.label | totally_harmless_string : | | tst.rb:10:9:10:25 | call to e | semmle.label | call to e | | tst.rb:10:11:10:24 | "666f6f626172" : | semmle.label | "666f6f626172" : | +| tst.rb:16:1:16:27 | another_questionable_string : | semmle.label | another_questionable_string : | | tst.rb:16:31:16:84 | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." : | semmle.label | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." : | | tst.rb:17:6:17:32 | another_questionable_string : | semmle.label | another_questionable_string : | | tst.rb:17:6:17:38 | call to strip | semmle.label | call to strip | diff --git a/ruby/ql/test/query-tests/security/cwe-598/SensitiveGetQuery.expected b/ruby/ql/test/query-tests/security/cwe-598/SensitiveGetQuery.expected index 005e2497be8..455befe0480 100644 --- a/ruby/ql/test/query-tests/security/cwe-598/SensitiveGetQuery.expected +++ b/ruby/ql/test/query-tests/security/cwe-598/SensitiveGetQuery.expected @@ -1,24 +1,3 @@ -edges -| app/controllers/users_controller.rb:4:11:4:16 | call to params : | app/controllers/users_controller.rb:4:11:4:27 | ...[...] | -| app/controllers/users_controller.rb:9:16:9:21 | call to params : | app/controllers/users_controller.rb:9:16:9:27 | ...[...] : | -| app/controllers/users_controller.rb:9:16:9:27 | ...[...] : | app/controllers/users_controller.rb:10:42:10:49 | password | -| app/controllers/users_controller.rb:14:5:14:13 | [post] self [@password] : | app/controllers/users_controller.rb:15:42:15:50 | self [@password] : | -| app/controllers/users_controller.rb:14:17:14:22 | call to params : | app/controllers/users_controller.rb:14:17:14:28 | ...[...] : | -| app/controllers/users_controller.rb:14:17:14:28 | ...[...] : | app/controllers/users_controller.rb:14:5:14:13 | [post] self [@password] : | -| app/controllers/users_controller.rb:15:42:15:50 | self [@password] : | app/controllers/users_controller.rb:15:42:15:50 | @password | -nodes -| app/controllers/users_controller.rb:4:11:4:16 | call to params : | semmle.label | call to params : | -| app/controllers/users_controller.rb:4:11:4:27 | ...[...] | semmle.label | ...[...] | -| app/controllers/users_controller.rb:9:16:9:21 | call to params : | semmle.label | call to params : | -| app/controllers/users_controller.rb:9:16:9:27 | ...[...] : | semmle.label | ...[...] : | -| app/controllers/users_controller.rb:10:42:10:49 | password | semmle.label | password | -| app/controllers/users_controller.rb:14:5:14:13 | [post] self [@password] : | semmle.label | [post] self [@password] : | -| app/controllers/users_controller.rb:14:17:14:22 | call to params : | semmle.label | call to params : | -| app/controllers/users_controller.rb:14:17:14:28 | ...[...] : | semmle.label | ...[...] : | -| app/controllers/users_controller.rb:15:42:15:50 | @password | semmle.label | @password | -| app/controllers/users_controller.rb:15:42:15:50 | self [@password] : | semmle.label | self [@password] : | -subpaths -#select -| app/controllers/users_controller.rb:4:11:4:16 | call to params | app/controllers/users_controller.rb:4:11:4:16 | call to params : | app/controllers/users_controller.rb:4:11:4:27 | ...[...] | $@ for GET requests uses query parameter as sensitive data. | app/controllers/users_controller.rb:3:3:6:5 | login_get_1 | Route handler | -| app/controllers/users_controller.rb:9:16:9:21 | call to params | app/controllers/users_controller.rb:9:16:9:21 | call to params : | app/controllers/users_controller.rb:10:42:10:49 | password | $@ for GET requests uses query parameter as sensitive data. | app/controllers/users_controller.rb:8:3:11:5 | login_get_2 | Route handler | -| app/controllers/users_controller.rb:14:17:14:22 | call to params | app/controllers/users_controller.rb:14:17:14:22 | call to params : | app/controllers/users_controller.rb:15:42:15:50 | @password | $@ for GET requests uses query parameter as sensitive data. | app/controllers/users_controller.rb:13:3:16:5 | login_get_3 | Route handler | +| app/controllers/users_controller.rb:4:11:4:16 | call to params | $@ for GET requests uses query parameter as sensitive data. | app/controllers/users_controller.rb:3:3:6:5 | login_get_1 | Route handler | +| app/controllers/users_controller.rb:9:16:9:21 | call to params | $@ for GET requests uses query parameter as sensitive data. | app/controllers/users_controller.rb:8:3:11:5 | login_get_2 | Route handler | +| app/controllers/users_controller.rb:14:17:14:22 | call to params | $@ for GET requests uses query parameter as sensitive data. | app/controllers/users_controller.rb:13:3:16:5 | login_get_3 | Route handler | diff --git a/ruby/ql/test/query-tests/security/cwe-611/libxml-backend/Xxe.expected b/ruby/ql/test/query-tests/security/cwe-611/libxml-backend/Xxe.expected index 30f57223c4b..6e0473c62c8 100644 --- a/ruby/ql/test/query-tests/security/cwe-611/libxml-backend/Xxe.expected +++ b/ruby/ql/test/query-tests/security/cwe-611/libxml-backend/Xxe.expected @@ -1,10 +1,12 @@ edges +| LibXmlBackend.rb:16:5:16:11 | content : | LibXmlBackend.rb:18:30:18:36 | content | +| LibXmlBackend.rb:16:5:16:11 | content : | LibXmlBackend.rb:19:19:19:25 | content | +| LibXmlBackend.rb:16:5:16:11 | content : | LibXmlBackend.rb:20:27:20:33 | content | +| LibXmlBackend.rb:16:5:16:11 | content : | LibXmlBackend.rb:21:34:21:40 | content | | LibXmlBackend.rb:16:15:16:20 | call to params : | LibXmlBackend.rb:16:15:16:26 | ...[...] : | -| LibXmlBackend.rb:16:15:16:26 | ...[...] : | LibXmlBackend.rb:18:30:18:36 | content | -| LibXmlBackend.rb:16:15:16:26 | ...[...] : | LibXmlBackend.rb:19:19:19:25 | content | -| LibXmlBackend.rb:16:15:16:26 | ...[...] : | LibXmlBackend.rb:20:27:20:33 | content | -| LibXmlBackend.rb:16:15:16:26 | ...[...] : | LibXmlBackend.rb:21:34:21:40 | content | +| LibXmlBackend.rb:16:15:16:26 | ...[...] : | LibXmlBackend.rb:16:5:16:11 | content : | nodes +| LibXmlBackend.rb:16:5:16:11 | content : | semmle.label | content : | | LibXmlBackend.rb:16:15:16:20 | call to params : | semmle.label | call to params : | | LibXmlBackend.rb:16:15:16:26 | ...[...] : | semmle.label | ...[...] : | | LibXmlBackend.rb:18:30:18:36 | content | semmle.label | content | diff --git a/ruby/ql/test/query-tests/security/cwe-611/xxe/Xxe.expected b/ruby/ql/test/query-tests/security/cwe-611/xxe/Xxe.expected index 442e5a9cfd4..638a3f3f805 100644 --- a/ruby/ql/test/query-tests/security/cwe-611/xxe/Xxe.expected +++ b/ruby/ql/test/query-tests/security/cwe-611/xxe/Xxe.expected @@ -1,30 +1,33 @@ edges +| LibXmlRuby.rb:3:5:3:11 | content : | LibXmlRuby.rb:4:34:4:40 | content | +| LibXmlRuby.rb:3:5:3:11 | content : | LibXmlRuby.rb:5:32:5:38 | content | +| LibXmlRuby.rb:3:5:3:11 | content : | LibXmlRuby.rb:6:30:6:36 | content | +| LibXmlRuby.rb:3:5:3:11 | content : | LibXmlRuby.rb:7:32:7:38 | content | +| LibXmlRuby.rb:3:5:3:11 | content : | LibXmlRuby.rb:8:30:8:36 | content | +| LibXmlRuby.rb:3:5:3:11 | content : | LibXmlRuby.rb:9:28:9:34 | content | +| LibXmlRuby.rb:3:5:3:11 | content : | LibXmlRuby.rb:11:26:11:32 | content | +| LibXmlRuby.rb:3:5:3:11 | content : | LibXmlRuby.rb:12:24:12:30 | content | | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:3:15:3:26 | ...[...] : | -| LibXmlRuby.rb:3:15:3:26 | ...[...] : | LibXmlRuby.rb:4:34:4:40 | content | -| LibXmlRuby.rb:3:15:3:26 | ...[...] : | LibXmlRuby.rb:5:32:5:38 | content | -| LibXmlRuby.rb:3:15:3:26 | ...[...] : | LibXmlRuby.rb:6:30:6:36 | content | -| LibXmlRuby.rb:3:15:3:26 | ...[...] : | LibXmlRuby.rb:7:32:7:38 | content | -| LibXmlRuby.rb:3:15:3:26 | ...[...] : | LibXmlRuby.rb:8:30:8:36 | content | -| LibXmlRuby.rb:3:15:3:26 | ...[...] : | LibXmlRuby.rb:9:28:9:34 | content | -| LibXmlRuby.rb:3:15:3:26 | ...[...] : | LibXmlRuby.rb:11:26:11:32 | content | -| LibXmlRuby.rb:3:15:3:26 | ...[...] : | LibXmlRuby.rb:12:24:12:30 | content | +| LibXmlRuby.rb:3:15:3:26 | ...[...] : | LibXmlRuby.rb:3:5:3:11 | content : | +| Nokogiri.rb:3:5:3:11 | content : | Nokogiri.rb:5:26:5:32 | content | +| Nokogiri.rb:3:5:3:11 | content : | Nokogiri.rb:6:26:6:32 | content | +| Nokogiri.rb:3:5:3:11 | content : | Nokogiri.rb:7:26:7:32 | content | +| Nokogiri.rb:3:5:3:11 | content : | Nokogiri.rb:8:26:8:32 | content | +| Nokogiri.rb:3:5:3:11 | content : | Nokogiri.rb:9:26:9:32 | content | +| Nokogiri.rb:3:5:3:11 | content : | Nokogiri.rb:11:26:11:32 | content | +| Nokogiri.rb:3:5:3:11 | content : | Nokogiri.rb:12:26:12:32 | content | +| Nokogiri.rb:3:5:3:11 | content : | Nokogiri.rb:15:26:15:32 | content | +| Nokogiri.rb:3:5:3:11 | content : | Nokogiri.rb:16:26:16:32 | content | +| Nokogiri.rb:3:5:3:11 | content : | Nokogiri.rb:18:26:18:32 | content | +| Nokogiri.rb:3:5:3:11 | content : | Nokogiri.rb:19:26:19:32 | content | +| Nokogiri.rb:3:5:3:11 | content : | Nokogiri.rb:22:26:22:32 | content | +| Nokogiri.rb:3:5:3:11 | content : | Nokogiri.rb:25:26:25:32 | content | +| Nokogiri.rb:3:5:3:11 | content : | Nokogiri.rb:27:26:27:32 | content | +| Nokogiri.rb:3:5:3:11 | content : | Nokogiri.rb:28:26:28:32 | content | | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:3:15:3:26 | ...[...] : | -| Nokogiri.rb:3:15:3:26 | ...[...] : | Nokogiri.rb:5:26:5:32 | content | -| Nokogiri.rb:3:15:3:26 | ...[...] : | Nokogiri.rb:6:26:6:32 | content | -| Nokogiri.rb:3:15:3:26 | ...[...] : | Nokogiri.rb:7:26:7:32 | content | -| Nokogiri.rb:3:15:3:26 | ...[...] : | Nokogiri.rb:8:26:8:32 | content | -| Nokogiri.rb:3:15:3:26 | ...[...] : | Nokogiri.rb:9:26:9:32 | content | -| Nokogiri.rb:3:15:3:26 | ...[...] : | Nokogiri.rb:11:26:11:32 | content | -| Nokogiri.rb:3:15:3:26 | ...[...] : | Nokogiri.rb:12:26:12:32 | content | -| Nokogiri.rb:3:15:3:26 | ...[...] : | Nokogiri.rb:15:26:15:32 | content | -| Nokogiri.rb:3:15:3:26 | ...[...] : | Nokogiri.rb:16:26:16:32 | content | -| Nokogiri.rb:3:15:3:26 | ...[...] : | Nokogiri.rb:18:26:18:32 | content | -| Nokogiri.rb:3:15:3:26 | ...[...] : | Nokogiri.rb:19:26:19:32 | content | -| Nokogiri.rb:3:15:3:26 | ...[...] : | Nokogiri.rb:22:26:22:32 | content | -| Nokogiri.rb:3:15:3:26 | ...[...] : | Nokogiri.rb:25:26:25:32 | content | -| Nokogiri.rb:3:15:3:26 | ...[...] : | Nokogiri.rb:27:26:27:32 | content | -| Nokogiri.rb:3:15:3:26 | ...[...] : | Nokogiri.rb:28:26:28:32 | content | +| Nokogiri.rb:3:15:3:26 | ...[...] : | Nokogiri.rb:3:5:3:11 | content : | nodes +| LibXmlRuby.rb:3:5:3:11 | content : | semmle.label | content : | | LibXmlRuby.rb:3:15:3:20 | call to params : | semmle.label | call to params : | | LibXmlRuby.rb:3:15:3:26 | ...[...] : | semmle.label | ...[...] : | | LibXmlRuby.rb:4:34:4:40 | content | semmle.label | content | @@ -35,6 +38,7 @@ nodes | LibXmlRuby.rb:9:28:9:34 | content | semmle.label | content | | LibXmlRuby.rb:11:26:11:32 | content | semmle.label | content | | LibXmlRuby.rb:12:24:12:30 | content | semmle.label | content | +| Nokogiri.rb:3:5:3:11 | content : | semmle.label | content : | | Nokogiri.rb:3:15:3:20 | call to params : | semmle.label | call to params : | | Nokogiri.rb:3:15:3:26 | ...[...] : | semmle.label | ...[...] : | | Nokogiri.rb:5:26:5:32 | content | semmle.label | content | diff --git a/ruby/ql/test/query-tests/security/cwe-732/WeakFilePermissions.expected b/ruby/ql/test/query-tests/security/cwe-732/WeakFilePermissions.expected index a7669549247..5df273f589f 100644 --- a/ruby/ql/test/query-tests/security/cwe-732/WeakFilePermissions.expected +++ b/ruby/ql/test/query-tests/security/cwe-732/WeakFilePermissions.expected @@ -1,17 +1,25 @@ edges -| FilePermissions.rb:51:10:51:13 | 0777 : | FilePermissions.rb:53:19:53:22 | perm | -| FilePermissions.rb:51:10:51:13 | 0777 : | FilePermissions.rb:56:19:56:23 | perm2 | -| FilePermissions.rb:58:10:58:26 | "u=wrx,g=rwx,o=x" : | FilePermissions.rb:61:19:61:23 | perm2 | +| FilePermissions.rb:51:3:51:6 | perm : | FilePermissions.rb:53:19:53:22 | perm | +| FilePermissions.rb:51:3:51:6 | perm : | FilePermissions.rb:54:3:54:7 | perm2 : | +| FilePermissions.rb:51:10:51:13 | 0777 : | FilePermissions.rb:51:3:51:6 | perm : | +| FilePermissions.rb:54:3:54:7 | perm2 : | FilePermissions.rb:56:19:56:23 | perm2 | +| FilePermissions.rb:58:3:58:6 | perm : | FilePermissions.rb:59:3:59:7 | perm2 : | +| FilePermissions.rb:58:10:58:26 | "u=wrx,g=rwx,o=x" : | FilePermissions.rb:58:3:58:6 | perm : | +| FilePermissions.rb:59:3:59:7 | perm2 : | FilePermissions.rb:61:19:61:23 | perm2 | nodes | FilePermissions.rb:5:19:5:22 | 0222 | semmle.label | 0222 | | FilePermissions.rb:7:19:7:22 | 0622 | semmle.label | 0622 | | FilePermissions.rb:9:19:9:22 | 0755 | semmle.label | 0755 | | FilePermissions.rb:11:19:11:22 | 0777 | semmle.label | 0777 | | FilePermissions.rb:28:13:28:16 | 0755 | semmle.label | 0755 | +| FilePermissions.rb:51:3:51:6 | perm : | semmle.label | perm : | | FilePermissions.rb:51:10:51:13 | 0777 : | semmle.label | 0777 : | | FilePermissions.rb:53:19:53:22 | perm | semmle.label | perm | +| FilePermissions.rb:54:3:54:7 | perm2 : | semmle.label | perm2 : | | FilePermissions.rb:56:19:56:23 | perm2 | semmle.label | perm2 | +| FilePermissions.rb:58:3:58:6 | perm : | semmle.label | perm : | | FilePermissions.rb:58:10:58:26 | "u=wrx,g=rwx,o=x" : | semmle.label | "u=wrx,g=rwx,o=x" : | +| FilePermissions.rb:59:3:59:7 | perm2 : | semmle.label | perm2 : | | FilePermissions.rb:61:19:61:23 | perm2 | semmle.label | perm2 | | FilePermissions.rb:63:19:63:29 | "u=rwx,o+r" | semmle.label | "u=rwx,o+r" | | FilePermissions.rb:67:19:67:24 | "a+rw" | semmle.label | "a+rw" | diff --git a/ruby/ql/test/query-tests/security/cwe-798/HardcodedCredentials.expected b/ruby/ql/test/query-tests/security/cwe-798/HardcodedCredentials.expected index 51e45945d0f..4d358671e34 100644 --- a/ruby/ql/test/query-tests/security/cwe-798/HardcodedCredentials.expected +++ b/ruby/ql/test/query-tests/security/cwe-798/HardcodedCredentials.expected @@ -3,8 +3,11 @@ edges | HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." : | HardcodedCredentials.rb:1:33:1:36 | cert | | HardcodedCredentials.rb:18:19:18:72 | ... + ... : | HardcodedCredentials.rb:1:23:1:30 | password | | HardcodedCredentials.rb:18:27:18:72 | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." : | HardcodedCredentials.rb:18:19:18:72 | ... + ... : | -| HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." : | HardcodedCredentials.rb:23:19:23:20 | pw : | -| HardcodedCredentials.rb:21:12:21:37 | "4fQuzXef4f2yow8KWvIJTA==" : | HardcodedCredentials.rb:23:19:23:20 | pw : | +| HardcodedCredentials.rb:20:1:20:7 | pw_left : | HardcodedCredentials.rb:22:1:22:2 | pw : | +| HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." : | HardcodedCredentials.rb:20:1:20:7 | pw_left : | +| HardcodedCredentials.rb:21:1:21:8 | pw_right : | HardcodedCredentials.rb:22:1:22:2 | pw : | +| HardcodedCredentials.rb:21:12:21:37 | "4fQuzXef4f2yow8KWvIJTA==" : | HardcodedCredentials.rb:21:1:21:8 | pw_right : | +| HardcodedCredentials.rb:22:1:22:2 | pw : | HardcodedCredentials.rb:23:19:23:20 | pw : | | HardcodedCredentials.rb:23:19:23:20 | pw : | HardcodedCredentials.rb:1:23:1:30 | password | | HardcodedCredentials.rb:38:40:38:85 | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." : | HardcodedCredentials.rb:31:18:31:23 | passwd | | HardcodedCredentials.rb:43:29:43:43 | "user@test.com" : | HardcodedCredentials.rb:43:18:43:25 | username | @@ -19,8 +22,11 @@ nodes | HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." : | semmle.label | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." : | | HardcodedCredentials.rb:18:19:18:72 | ... + ... : | semmle.label | ... + ... : | | HardcodedCredentials.rb:18:27:18:72 | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." : | semmle.label | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." : | +| HardcodedCredentials.rb:20:1:20:7 | pw_left : | semmle.label | pw_left : | | HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." : | semmle.label | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." : | +| HardcodedCredentials.rb:21:1:21:8 | pw_right : | semmle.label | pw_right : | | HardcodedCredentials.rb:21:12:21:37 | "4fQuzXef4f2yow8KWvIJTA==" : | semmle.label | "4fQuzXef4f2yow8KWvIJTA==" : | +| HardcodedCredentials.rb:22:1:22:2 | pw : | semmle.label | pw : | | HardcodedCredentials.rb:23:19:23:20 | pw : | semmle.label | pw : | | HardcodedCredentials.rb:31:18:31:23 | passwd | semmle.label | passwd | | HardcodedCredentials.rb:38:40:38:85 | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." : | semmle.label | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." : | diff --git a/ruby/ql/test/query-tests/security/cwe-807-user-controlled-bypass/ConditionalBypass.expected b/ruby/ql/test/query-tests/security/cwe-807-user-controlled-bypass/ConditionalBypass.expected index 912900936a1..32b778130ef 100644 --- a/ruby/ql/test/query-tests/security/cwe-807-user-controlled-bypass/ConditionalBypass.expected +++ b/ruby/ql/test/query-tests/security/cwe-807-user-controlled-bypass/ConditionalBypass.expected @@ -1,16 +1,20 @@ edges +| ConditionalBypass.rb:3:5:3:9 | check : | ConditionalBypass.rb:6:8:6:12 | check | | ConditionalBypass.rb:3:13:3:18 | call to params : | ConditionalBypass.rb:3:13:3:26 | ...[...] : | -| ConditionalBypass.rb:3:13:3:26 | ...[...] : | ConditionalBypass.rb:6:8:6:12 | check | +| ConditionalBypass.rb:3:13:3:26 | ...[...] : | ConditionalBypass.rb:3:5:3:9 | check : | | ConditionalBypass.rb:14:14:14:19 | call to params : | ConditionalBypass.rb:14:14:14:27 | ...[...] | +| ConditionalBypass.rb:25:5:25:5 | p : | ConditionalBypass.rb:27:8:27:8 | p | | ConditionalBypass.rb:25:10:25:15 | call to params : | ConditionalBypass.rb:25:10:25:22 | ...[...] | | ConditionalBypass.rb:25:10:25:15 | call to params : | ConditionalBypass.rb:25:10:25:22 | ...[...] : | -| ConditionalBypass.rb:25:10:25:22 | ...[...] : | ConditionalBypass.rb:27:8:27:8 | p | +| ConditionalBypass.rb:25:10:25:22 | ...[...] : | ConditionalBypass.rb:25:5:25:5 | p : | nodes +| ConditionalBypass.rb:3:5:3:9 | check : | semmle.label | check : | | ConditionalBypass.rb:3:13:3:18 | call to params : | semmle.label | call to params : | | ConditionalBypass.rb:3:13:3:26 | ...[...] : | semmle.label | ...[...] : | | ConditionalBypass.rb:6:8:6:12 | check | semmle.label | check | | ConditionalBypass.rb:14:14:14:19 | call to params : | semmle.label | call to params : | | ConditionalBypass.rb:14:14:14:27 | ...[...] | semmle.label | ...[...] | +| ConditionalBypass.rb:25:5:25:5 | p : | semmle.label | p : | | ConditionalBypass.rb:25:10:25:15 | call to params : | semmle.label | call to params : | | ConditionalBypass.rb:25:10:25:22 | ...[...] | semmle.label | ...[...] | | ConditionalBypass.rb:25:10:25:22 | ...[...] : | semmle.label | ...[...] : | diff --git a/ruby/ql/test/query-tests/security/cwe-829/InsecureDownload.expected b/ruby/ql/test/query-tests/security/cwe-829/InsecureDownload.expected index 77e26750686..3562b7a8c98 100644 --- a/ruby/ql/test/query-tests/security/cwe-829/InsecureDownload.expected +++ b/ruby/ql/test/query-tests/security/cwe-829/InsecureDownload.expected @@ -1,10 +1,14 @@ failures edges -| insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" : | insecure_download.rb:33:15:33:17 | url | -| insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" : | insecure_download.rb:33:15:33:17 | url | +| insecure_download.rb:31:5:31:7 | url : | insecure_download.rb:33:15:33:17 | url | +| insecure_download.rb:31:5:31:7 | url : | insecure_download.rb:33:15:33:17 | url | +| insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" : | insecure_download.rb:31:5:31:7 | url : | +| insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" : | insecure_download.rb:31:5:31:7 | url : | nodes | insecure_download.rb:27:15:27:45 | "http://example.org/unsafe.APK" | semmle.label | "http://example.org/unsafe.APK" | | insecure_download.rb:27:15:27:45 | "http://example.org/unsafe.APK" | semmle.label | "http://example.org/unsafe.APK" | +| insecure_download.rb:31:5:31:7 | url : | semmle.label | url : | +| insecure_download.rb:31:5:31:7 | url : | semmle.label | url : | | insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" : | semmle.label | "http://example.org/unsafe.APK" : | | insecure_download.rb:31:11:31:41 | "http://example.org/unsafe.APK" : | semmle.label | "http://example.org/unsafe.APK" : | | insecure_download.rb:33:15:33:17 | url | semmle.label | url | diff --git a/ruby/ql/test/query-tests/security/cwe-912/HttpToFileAccess.expected b/ruby/ql/test/query-tests/security/cwe-912/HttpToFileAccess.expected index ba8d776656b..1f26bdc2221 100644 --- a/ruby/ql/test/query-tests/security/cwe-912/HttpToFileAccess.expected +++ b/ruby/ql/test/query-tests/security/cwe-912/HttpToFileAccess.expected @@ -1,10 +1,14 @@ edges -| http_to_file_access.rb:3:8:3:52 | call to body : | http_to_file_access.rb:5:12:5:15 | resp | +| http_to_file_access.rb:3:1:3:4 | resp : | http_to_file_access.rb:5:12:5:15 | resp | +| http_to_file_access.rb:3:8:3:52 | call to body : | http_to_file_access.rb:3:1:3:4 | resp : | +| http_to_file_access.rb:9:7:9:12 | script : | http_to_file_access.rb:11:18:11:23 | script | | http_to_file_access.rb:9:16:9:21 | call to params : | http_to_file_access.rb:9:16:9:30 | ...[...] : | -| http_to_file_access.rb:9:16:9:30 | ...[...] : | http_to_file_access.rb:11:18:11:23 | script | +| http_to_file_access.rb:9:16:9:30 | ...[...] : | http_to_file_access.rb:9:7:9:12 | script : | nodes +| http_to_file_access.rb:3:1:3:4 | resp : | semmle.label | resp : | | http_to_file_access.rb:3:8:3:52 | call to body : | semmle.label | call to body : | | http_to_file_access.rb:5:12:5:15 | resp | semmle.label | resp | +| http_to_file_access.rb:9:7:9:12 | script : | semmle.label | script : | | http_to_file_access.rb:9:16:9:21 | call to params : | semmle.label | call to params : | | http_to_file_access.rb:9:16:9:30 | ...[...] : | semmle.label | ...[...] : | | http_to_file_access.rb:11:18:11:23 | script | semmle.label | script | diff --git a/ruby/ql/test/query-tests/security/cwe-918/ServerSideRequestForgery.expected b/ruby/ql/test/query-tests/security/cwe-918/ServerSideRequestForgery.expected index 1ac18b48554..906d4666020 100644 --- a/ruby/ql/test/query-tests/security/cwe-918/ServerSideRequestForgery.expected +++ b/ruby/ql/test/query-tests/security/cwe-918/ServerSideRequestForgery.expected @@ -1,9 +1,11 @@ edges +| ServerSideRequestForgery.rb:10:9:10:28 | users_service_domain : | ServerSideRequestForgery.rb:11:31:11:62 | "#{...}/logins" | | ServerSideRequestForgery.rb:10:32:10:37 | call to params : | ServerSideRequestForgery.rb:10:32:10:60 | ...[...] : | -| ServerSideRequestForgery.rb:10:32:10:60 | ...[...] : | ServerSideRequestForgery.rb:11:31:11:62 | "#{...}/logins" | +| ServerSideRequestForgery.rb:10:32:10:60 | ...[...] : | ServerSideRequestForgery.rb:10:9:10:28 | users_service_domain : | | ServerSideRequestForgery.rb:15:33:15:38 | call to params : | ServerSideRequestForgery.rb:15:33:15:44 | ...[...] | | ServerSideRequestForgery.rb:20:45:20:50 | call to params : | ServerSideRequestForgery.rb:20:45:20:56 | ...[...] | nodes +| ServerSideRequestForgery.rb:10:9:10:28 | users_service_domain : | semmle.label | users_service_domain : | | ServerSideRequestForgery.rb:10:32:10:37 | call to params : | semmle.label | call to params : | | ServerSideRequestForgery.rb:10:32:10:60 | ...[...] : | semmle.label | ...[...] : | | ServerSideRequestForgery.rb:11:31:11:62 | "#{...}/logins" | semmle.label | "#{...}/logins" | diff --git a/ruby/ql/test/query-tests/security/decompression-api/DecompressionApi.expected b/ruby/ql/test/query-tests/security/decompression-api/DecompressionApi.expected index 20ec5943541..265142d1ccd 100644 --- a/ruby/ql/test/query-tests/security/decompression-api/DecompressionApi.expected +++ b/ruby/ql/test/query-tests/security/decompression-api/DecompressionApi.expected @@ -1,8 +1,10 @@ edges +| decompression_api.rb:4:9:4:12 | path : | decompression_api.rb:5:31:5:34 | path | | decompression_api.rb:4:16:4:21 | call to params : | decompression_api.rb:4:16:4:28 | ...[...] : | -| decompression_api.rb:4:16:4:28 | ...[...] : | decompression_api.rb:5:31:5:34 | path | +| decompression_api.rb:4:16:4:28 | ...[...] : | decompression_api.rb:4:9:4:12 | path : | | decompression_api.rb:15:31:15:36 | call to params : | decompression_api.rb:15:31:15:43 | ...[...] | nodes +| decompression_api.rb:4:9:4:12 | path : | semmle.label | path : | | decompression_api.rb:4:16:4:21 | call to params : | semmle.label | call to params : | | decompression_api.rb:4:16:4:28 | ...[...] : | semmle.label | ...[...] : | | decompression_api.rb:5:31:5:34 | path | semmle.label | path | diff --git a/ruby/scripts/create-extractor-pack.sh b/ruby/scripts/create-extractor-pack.sh index 37ed267b856..c014ed52016 100755 --- a/ruby/scripts/create-extractor-pack.sh +++ b/ruby/scripts/create-extractor-pack.sh @@ -14,7 +14,15 @@ else fi (cd extractor && "$CARGO" build --release) -extractor/target/release/generator --dbscheme ql/lib/ruby.dbscheme --library ql/lib/codeql/ruby/ast/internal/TreeSitter.qll + +# If building via cross, the binaries will be in extractor/target/<triple>/release +# If building via cargo, the binaries will be in extractor/target/release +BIN_DIR=extractor/target/release +if [[ "$CARGO" == "cross" ]]; then + BIN_DIR=extractor/target/x86_64-unknown-linux-gnu/release +fi + +"$BIN_DIR/generator" --dbscheme ql/lib/ruby.dbscheme --library ql/lib/codeql/ruby/ast/internal/TreeSitter.qll codeql query format -i ql/lib/codeql/ruby/ast/internal/TreeSitter.qll @@ -22,5 +30,5 @@ rm -rf extractor-pack mkdir -p extractor-pack cp -r codeql-extractor.yml downgrades tools ql/lib/ruby.dbscheme ql/lib/ruby.dbscheme.stats extractor-pack/ mkdir -p extractor-pack/tools/${platform} -cp extractor/target/release/extractor extractor-pack/tools/${platform}/extractor -cp extractor/target/release/autobuilder extractor-pack/tools/${platform}/autobuilder +cp "$BIN_DIR/extractor" extractor-pack/tools/${platform}/extractor +cp "$BIN_DIR/autobuilder" extractor-pack/tools/${platform}/autobuilder diff --git a/shared/regex/codeql/regex/nfa/NfaUtils.qll b/shared/regex/codeql/regex/nfa/NfaUtils.qll index cb5091c40aa..3fd4b97c829 100644 --- a/shared/regex/codeql/regex/nfa/NfaUtils.qll +++ b/shared/regex/codeql/regex/nfa/NfaUtils.qll @@ -147,6 +147,8 @@ module Make<RegexTreeViewSig TreeImpl> { /** * Gets a string for the full location of `t`. */ + bindingset[t] + pragma[inline_late] string getTermLocationString(RegExpTerm t) { exists(string file, int startLine, int startColumn, int endLine, int endColumn | t.hasLocationInfo(file, startLine, startColumn, endLine, endColumn) and @@ -851,6 +853,10 @@ module Make<RegexTreeViewSig TreeImpl> { * Gets the term represented by this state. */ RegExpTerm getRepr() { result = repr } + + predicate hasLocationInfo(string file, int line, int column, int endline, int endcolumn) { + repr.hasLocationInfo(file, line, column, endline, endcolumn) + } } /** diff --git a/shared/regex/codeql/regex/nfa/SuperlinearBackTracking.qll b/shared/regex/codeql/regex/nfa/SuperlinearBackTracking.qll index d06170502b4..3f16431e165 100644 --- a/shared/regex/codeql/regex/nfa/SuperlinearBackTracking.qll +++ b/shared/regex/codeql/regex/nfa/SuperlinearBackTracking.qll @@ -9,16 +9,16 @@ * Theorem 3 from the paper describes the basic idea. * * The following explains the idea using variables and predicate names that are used in the implementation: - * We consider a pair of repetitions, which we will call `pivot` and `succ`. + * We consider a pair of repetitions, which we will call `pivot` and `pumpEnd`. * * We create a product automaton of 3-tuples of states (see `StateTuple`). * There exists a transition `(a,b,c) -> (d,e,f)` in the product automaton * iff there exists three transitions in the NFA `a->d, b->e, c->f` where those three * transitions all match a shared character `char`. (see `getAThreewayIntersect`) * - * We start a search in the product automaton at `(pivot, pivot, succ)`, + * We start a search in the product automaton at `(pivot, pivot, pumpEnd)`, * and search for a series of transitions (a `Trace`), such that we end - * at `(pivot, succ, succ)` (see `isReachableFromStartTuple`). + * at `(pivot, pumpEnd, pumpEnd)` (see `isReachableFromStartTuple`). * * For example, consider the regular expression `/^\d*5\w*$/`. * The search will start at the tuple `(\d*, \d*, \w*)` and search @@ -51,20 +51,30 @@ module Make<RegexTreeViewSig TreeImpl> { private State getRootState() { result = mkMatch(any(RegExpRoot r)) } private newtype TStateTuple = - MkStateTuple(State q1, State q2, State q3) { - // starts at (pivot, pivot, succ) - isStartLoops(q1, q3) and q1 = q2 + /** + * A tuple of states `(q1, q2, q3)` in the product automaton that is reachable from `(pivot, pivot, pumpEnd)`. + */ + MkStateTuple(State pivot, State pumpEnd, State q1, State q2, State q3) { + // starts at (pivot, pivot, pumpEnd) + isStartLoops(q1, q3) and + q1 = q2 and + pivot = q1 and + pumpEnd = q3 or - step(_, _, _, _, q1, q2, q3) and FeasibleTuple::isFeasibleTuple(q1, q2, q3) + // recurse: any transition out where all 3 edges share a char (and the resulting tuple isn't obviously infeasible) + exists(StateTuple prev | + prev = MkStateTuple(pivot, pumpEnd, _, _, _) and + hasCommonStep(prev, _, _, _, q1, q2, q3) and + FeasibleTuple::isFeasibleTuple(pivot, pumpEnd, q1, q2, q3) + ) } /** - * A state in the product automaton. - * The product automaton contains 3-tuples of states. + * A state `(q1, q2, q3)` in the product automaton, that is reachable from `(pivot, pivot, pumpEnd)`. * * We lazily only construct those states that we are actually * going to need. - * Either a start state `(pivot, pivot, succ)`, or a state + * Either a start state `(pivot, pivot, pumpEnd)`, or a state * where there exists a transition from an already existing state. * * The exponential variant of this query (`js/redos`) uses an optimization @@ -72,11 +82,13 @@ module Make<RegexTreeViewSig TreeImpl> { * of the elements matter. */ class StateTuple extends TStateTuple { + State pivot; + State pumpEnd; State q1; State q2; State q3; - StateTuple() { this = MkStateTuple(q1, q2, q3) } + StateTuple() { this = MkStateTuple(pivot, pumpEnd, q1, q2, q3) } /** * Gest a string representation of this tuple. @@ -88,6 +100,39 @@ module Make<RegexTreeViewSig TreeImpl> { */ pragma[noinline] predicate isTuple(State r1, State r2, State r3) { r1 = q1 and r2 = q2 and r3 = q3 } + + /** + * Gets the first state of the tuple. + */ + State getFirst() { result = q1 } + + /** + * Gets the second state of the tuple. + */ + State getSecond() { result = q2 } + + /** + * Gets the third state of the tuple. + */ + State getThird() { result = q3 } + + /** + * Gets the pivot state. + */ + State getPivot() { result = pivot } + + /** + * Gets the pumpEnd state. + */ + State getPumpEnd() { result = pumpEnd } + + /** + * Holds if the pivot state has the specified location. + * This location has been chosen arbitrarily, and is only useful for debugging. + */ + predicate hasLocationInfo(string file, int line, int column, int endLine, int endColumn) { + pivot.hasLocationInfo(file, line, column, endLine, endColumn) + } } /** @@ -97,21 +142,36 @@ module Make<RegexTreeViewSig TreeImpl> { */ private module FeasibleTuple { /** - * Holds if the tuple `(r1, r2, r3)` might be on path from a start-state to an end-state in the product automaton. + * Holds if the tuple `(r1, r2, r3)` might be on path from a start-state `(pivot, pivot, pumpEnd)` to an end-state `(pivot, pumpEnd, pumpEnd)` in the product automaton. */ - pragma[inline] - predicate isFeasibleTuple(State r1, State r2, State r3) { + bindingset[pivot, pumpEnd, r1, r2, r3] + pragma[inline_late] + predicate isFeasibleTuple(State pivot, State pumpEnd, State r1, State r2, State r3) { + isStartLoops(pivot, pumpEnd) and + // r1 can reach the pivot state + reachesBeginning(r1, pivot) and + // r2 and r3 can reach the pumpEnd state + reachesEnd(r2, pumpEnd) and + reachesEnd(r3, pumpEnd) and // The first element is either inside a repetition (or the start state itself) isRepetitionOrStart(r1) and // The last element is inside a repetition stateInsideRepetition(r3) and // The states are reachable in the NFA in the order r1 -> r2 -> r3 delta+(r1) = r2 and - delta+(r2) = r3 and - // The first element can reach a beginning (the "pivot" state in a `(pivot, succ)` pair). - canReachABeginning(r1) and - // The last element can reach a target (the "succ" state in a `(pivot, succ)` pair). - canReachATarget(r3) + delta+(r2) = r3 + } + + pragma[noinline] + private predicate reachesBeginning(State s, State pivot) { + isStartLoops(pivot, _) and + delta+(s) = pivot + } + + pragma[noinline] + private predicate reachesEnd(State s, State pumpEnd) { + isStartLoops(_, pumpEnd) and + delta+(s) = pumpEnd } /** @@ -129,36 +189,18 @@ module Make<RegexTreeViewSig TreeImpl> { private predicate stateInsideRepetition(State s) { s.getRepr().getParent*() instanceof InfiniteRepetitionQuantifier } - - /** - * Holds if there exists a path in the NFA from `s` to a "pivot" state - * (from a `(pivot, succ)` pair that starts the search). - */ - pragma[noinline] - private predicate canReachABeginning(State s) { - delta+(s) = any(State pivot | isStartLoops(pivot, _)) - } - - /** - * Holds if there exists a path in the NFA from `s` to a "succ" state - * (from a `(pivot, succ)` pair that starts the search). - */ - pragma[noinline] - private predicate canReachATarget(State s) { - delta+(s) = any(State succ | isStartLoops(_, succ)) - } } /** - * Holds if `pivot` and `succ` are a pair of loops that could be the beginning of a quadratic blowup. + * Holds if `pivot` and `pumpEnd` are a pair of loops that could be the beginning of a quadratic blowup. * - * There is a slight implementation difference compared to the paper: this predicate requires that `pivot != succ`. - * The case where `pivot = succ` causes exponential backtracking and is handled by the `js/redos` query. + * There is a slight implementation difference compared to the paper: this predicate requires that `pivot != pumpEnd`. + * The case where `pivot = pumpEnd` causes exponential backtracking and is handled by the `js/redos` query. */ - predicate isStartLoops(State pivot, State succ) { - pivot != succ and - succ.getRepr() instanceof InfiniteRepetitionQuantifier and - delta+(pivot) = succ and + predicate isStartLoops(State pivot, State pumpEnd) { + pivot != pumpEnd and + pumpEnd.getRepr() instanceof InfiniteRepetitionQuantifier and + delta+(pivot) = pumpEnd and ( pivot.getRepr() instanceof InfiniteRepetitionQuantifier or @@ -174,62 +216,25 @@ module Make<RegexTreeViewSig TreeImpl> { /** * Holds if there are transitions from the components of `q` to the corresponding * components of `r` labelled with `s1`, `s2`, and `s3`, respectively. + * Where the edges `s1`, `s2`, and `s3` all share at least one character. */ pragma[nomagic] - private predicate stepHelper( - StateTuple q, InputSymbol s1, InputSymbol s2, InputSymbol s3, StateTuple r - ) { + private predicate step(StateTuple q, InputSymbol s1, InputSymbol s2, InputSymbol s3, StateTuple r) { exists(State r1, State r2, State r3 | - step(q, s1, s2, s3, r1, r2, r3) and r = MkStateTuple(r1, r2, r3) + hasCommonStep(q, s1, s2, s3, r1, r2, r3) and + r = + MkStateTuple(pragma[only_bind_out](q.getPivot()), pragma[only_bind_out](q.getPumpEnd()), + pragma[only_bind_out](r1), pragma[only_bind_out](r2), pragma[only_bind_out](r3)) ) } - /** - * Holds if there are transitions from the components of `q` to the corresponding - * components of `r` labelled with `s1`, `s2`, and `s3`, respectively. - * - * Additionally, a heuristic is used to avoid blowups in the case of complex regexps. - * For regular expressions with more than 100 states, we only look at all the characters - * for the transitions out of `q` and only consider transitions that use the lexicographically - * smallest character. - */ - pragma[noinline] - predicate step(StateTuple q, InputSymbol s1, InputSymbol s2, InputSymbol s3, StateTuple r) { - stepHelper(q, s1, s2, s3, r) and - ( - countStates(any(State s | q.isTuple(s, _, _)).getRepr().getRootTerm()) < 100 - or - // arbitrarily pick an edge out of `q` for complex regexps. This is a heuristic to avoid potential blowups. - exists(string char | - char = - min(string str, InputSymbol x1, InputSymbol x2, InputSymbol x3 | - stepHelper(q, x1, x2, x3, _) and str = getAStepChar(x1, x2, x3) - | - str - ) and - char = getAStepChar(s1, s2, s3) - ) - ) - } - - // specialized version of `getAThreewayIntersect` to be used in `step` above. - pragma[noinline] - private string getAStepChar(InputSymbol s1, InputSymbol s2, InputSymbol s3) { - stepHelper(_, s1, s2, s3, _) and result = getAThreewayIntersect(s1, s2, s3) - } - - /** Gets the number of states in the NFA for `root`. This is used to determine a complexity metric used in the `step` predicate above. */ - private int countStates(RegExpTerm root) { - root.isRootTerm() and - result = count(State s | s.getRepr().getRootTerm() = root) - } - /** * Holds if there are transitions from the components of `q` to `r1`, `r2`, and `r3 * labelled with `s1`, `s2`, and `s3`, respectively. + * Where `s1`, `s2`, and `s3` all share at least one character. */ pragma[noopt] - predicate step( + predicate hasCommonStep( StateTuple q, InputSymbol s1, InputSymbol s2, InputSymbol s3, State r1, State r2, State r3 ) { exists(State q1, State q2, State q3 | q.isTuple(q1, q2, q3) | @@ -264,41 +269,59 @@ module Make<RegexTreeViewSig TreeImpl> { result = [min(intersect(a, b)), max(intersect(a, b))] } - private newtype TTrace = - Nil() or - Step(InputSymbol s1, InputSymbol s2, InputSymbol s3, TTrace t) { - isReachableFromStartTuple(_, _, t, s1, s2, s3, _, _) - } - - /** - * A list of tuples of input symbols that describe a path in the product automaton - * starting from some start state. - */ - class Trace extends TTrace { - /** - * Gets a string representation of this Trace that can be used for debug purposes. - */ - string toString() { - this = Nil() and result = "Nil()" - or - exists(InputSymbol s1, InputSymbol s2, InputSymbol s3, Trace t | this = Step(s1, s2, s3, t) | - result = "Step(" + s1 + ", " + s2 + ", " + s3 + ", " + t + ")" - ) - } + /** Gets a tuple reachable in a forwards exploratory search from the start state `(pivot, pivot, pivot)`. */ + private StateTuple getReachableFromStartStateForwards(State pivot, State pumpEnd) { + // base case. + isStartLoops(pivot, pumpEnd) and + result = MkStateTuple(pivot, pumpEnd, pivot, pivot, pumpEnd) + or + // recursive case + exists(StateTuple p | + p = getReachableFromStartStateForwards(pivot, pumpEnd) and + step(p, _, _, _, result) + ) } /** - * Holds if there exists a transition from `r` to `q` in the product automaton. + * Gets a state tuple that can reach the end state `(pivot, pumpEnd, pumpEnd)`, found via a backwards exploratory search. + * Where the end state was reachable from a forwards search from the start state `(pivot, pivot, pumpEnd)`. + * The resulting tuples are exactly those that are on a path from the start state to the end state. + */ + private StateTuple getARelevantStateTuple(State pivot, State pumpEnd) { + // base case. + isStartLoops(pivot, pumpEnd) and + result = MkStateTuple(pivot, pumpEnd, pivot, pumpEnd, pumpEnd) and + result = getReachableFromStartStateForwards(pivot, pumpEnd) + or + // recursive case + exists(StateTuple p | + p = getARelevantStateTuple(pivot, pumpEnd) and + step(result, _, _, _, p) and + pragma[only_bind_out](result) = getReachableFromStartStateForwards(pivot, pumpEnd) // was reachable in the forwards pass. + ) + } + + /** + * Holds if there exists a transition from `src` to `dst` in the product automaton. + * Where `src` and `dst` are both on a path from a start state to an end state. * Notice that the arguments are flipped, and thus the direction is backwards. */ pragma[noinline] - predicate tupleDeltaBackwards(StateTuple q, StateTuple r) { step(r, _, _, _, q) } + predicate tupleDeltaBackwards(StateTuple dst, StateTuple src) { + step(src, _, _, _, dst) and + // `step` ensures that `src` and `dst` have the same pivot and pumpEnd. + src = getARelevantStateTuple(_, _) and + dst = getARelevantStateTuple(_, _) + } /** - * Holds if `tuple` is an end state in our search. - * That means there exists a pair of loops `(pivot, succ)` such that `tuple = (pivot, succ, succ)`. + * Holds if `tuple` is an end state in our search, and `tuple` is on a path from a start state to an end state. + * That means there exists a pair of loops `(pivot, pumpEnd)` such that `tuple = (pivot, pumpEnd, pumpEnd)`. */ - predicate isEndTuple(StateTuple tuple) { tuple = getAnEndTuple(_, _) } + predicate isEndTuple(StateTuple tuple) { + tuple = getEndTuple(_, _) and + tuple = getARelevantStateTuple(_, _) + } /** * Gets the minimum length of a path from `r` to some an end state `end`. @@ -311,72 +334,138 @@ module Make<RegexTreeViewSig TreeImpl> { shortestDistances(isEndTuple/1, tupleDeltaBackwards/2)(end, r, result) /** - * Holds if there exists a pair of repetitions `(pivot, succ)` in the regular expression such that: - * `tuple` is reachable from `(pivot, pivot, succ)` in the product automaton, - * and there is a distance of `dist` from `tuple` to the nearest end-tuple `(pivot, succ, succ)`, - * and a path from a start-state to `tuple` follows the transitions in `trace`. + * Holds if there is a step from `q` to `r` in the product automaton labeled with `s1`, `s2`, and `s3`. + * Where the step is on a path from a start state to an end state. */ - private predicate isReachableFromStartTuple( - State pivot, State succ, StateTuple tuple, Trace trace, int dist + private predicate isStepOnPath( + StateTuple q, InputSymbol s1, InputSymbol s2, InputSymbol s3, StateTuple r ) { - exists(InputSymbol s1, InputSymbol s2, InputSymbol s3, Trace v | - isReachableFromStartTuple(pivot, succ, v, s1, s2, s3, tuple, dist) and - trace = Step(s1, s2, s3, v) - ) - } - - private predicate isReachableFromStartTuple( - State pivot, State succ, Trace trace, InputSymbol s1, InputSymbol s2, InputSymbol s3, - StateTuple tuple, int dist - ) { - // base case. - isStartLoops(pivot, succ) and - step(MkStateTuple(pivot, pivot, succ), s1, s2, s3, tuple) and - tuple = MkStateTuple(_, _, _) and - trace = Nil() and - dist = distBackFromEnd(tuple, MkStateTuple(pivot, succ, succ)) - or - // recursive case - exists(StateTuple p | - isReachableFromStartTuple(pivot, succ, p, trace, dist + 1) and - dist = distBackFromEnd(tuple, MkStateTuple(pivot, succ, succ)) and - step(p, s1, s2, s3, tuple) + step(q, s1, s2, s3, r) and + exists(State pivot, State pumpEnd, StateTuple end | + end = MkStateTuple(pivot, pumpEnd, pivot, pumpEnd, pumpEnd) and + pragma[only_bind_out](distBackFromEnd(q, end)) = + pragma[only_bind_out](distBackFromEnd(r, end)) + 1 ) } /** - * Gets the tuple `(pivot, succ, succ)` from the product automaton. + * Gets a unique number for a `state`. + * Is used to create an ordering of states and tuples of states. */ - StateTuple getAnEndTuple(State pivot, State succ) { - isStartLoops(pivot, succ) and - result = MkStateTuple(pivot, succ, succ) + private int rankState(State state) { + state = + rank[result](State s, int startLine, int endLine, int startColumn, int endColumn | + exists(StateTuple tuple | tuple = getARelevantStateTuple(_, _) | + s = [tuple.getFirst(), tuple.getSecond(), tuple.getThird()] and + s.getRepr().hasLocationInfo(_, startLine, startColumn, endLine, endColumn) + ) + | + s order by startLine, startColumn, endLine, endColumn + ) + } + + /** + * Holds if there is a step from `q` to `r` in the product automaton labeled with `s1`, `s2`, and `s3`. + * Where the step is on a path from a start state to an end state. + * And the step is a uniquely chosen step from out of `q`. + */ + pragma[nomagic] + private predicate isUniqueMinStepOnPath( + StateTuple q, InputSymbol s1, InputSymbol s2, InputSymbol s3, StateTuple r + ) { + isStepOnPath(q, s1, s2, s3, r) and + r = + min(StateTuple cand | + isStepOnPath(q, _, _, _, cand) + | + cand + order by + rankState(cand.getFirst()), rankState(cand.getSecond()), rankState(cand.getThird()) + ) + } + + private newtype TTrace = + Nil(State pivot, State pumpEnd) { + isStartLoops(pivot, pumpEnd) and + getStartTuple(pivot, pumpEnd) = getARelevantStateTuple(pivot, pumpEnd) + } or + Step(TTrace prev, StateTuple nextTuple) { + exists(StateTuple prevTuple | + exists(State pivot, State pumpEnd | + prev = Nil(pivot, pumpEnd) and + prevTuple = getStartTuple(pivot, pumpEnd) + ) + or + prev = Step(_, prevTuple) + | + isUniqueMinStepOnPath(prevTuple, _, _, _, nextTuple) + ) + } + + /** + * A list of tuples of input symbols that describe a path in the product automaton + * starting from a start state `(pivot, pivot, pumpEnd)`. + */ + class Trace extends TTrace { + /** + * Gets a string representation of this Trace that can be used for debug purposes. + */ + string toString() { result = "a trace" } + + /** Gets a trace where the head has been removed. */ + Trace getPrev() { this = Step(result, _) } + + /** Gets the tuple at the head of this trace. */ + StateTuple getTuple() { + this = Step(_, result) + or + exists(State prev, State pumpEnd | + this = Nil(prev, pumpEnd) and + result = getStartTuple(prev, pumpEnd) + ) + } + } + + /** + * Gets the tuple `(pivot, pumpEnd, pumpEnd)` from the product automaton. + */ + StateTuple getEndTuple(State pivot, State pumpEnd) { + isStartLoops(pivot, pumpEnd) and + result = MkStateTuple(pivot, pumpEnd, pivot, pumpEnd, pumpEnd) + } + + /** + * Gets the tuple `(pivot, pivot, pumpEnd)` from the product automaton. + */ + StateTuple getStartTuple(State pivot, State pumpEnd) { + isStartLoops(pivot, pumpEnd) and + result = MkStateTuple(pivot, pumpEnd, pivot, pivot, pumpEnd) } /** An implementation of a chain containing chars for use by `Concretizer`. */ private module CharTreeImpl implements CharTree { class CharNode = Trace; - CharNode getPrev(CharNode t) { t = Step(_, _, _, result) } + CharNode getPrev(CharNode t) { result = t.getPrev() } - /** Holds if `n` is used in `isPumpable`. */ - predicate isARelevantEnd(CharNode n) { - exists(State pivot, State succ | - isReachableFromStartTuple(pivot, succ, getAnEndTuple(pivot, succ), n, _) - ) - } + predicate isARelevantEnd(CharNode n) { n.getTuple() = getEndTuple(_, _) } string getChar(CharNode t) { - exists(InputSymbol s1, InputSymbol s2, InputSymbol s3 | t = Step(s1, s2, s3, _) | - result = getAThreewayIntersect(s1, s2, s3) - ) + result = + min(string c, InputSymbol s1, InputSymbol s2, InputSymbol s3 | + isUniqueMinStepOnPath(t.getPrev().getTuple(), s1, s2, s3, t.getTuple()) and + c = getAThreewayIntersect(s1, s2, s3) + | + c + ) } } /** * Holds if matching repetitions of `pump` can: * 1) Transition from `pivot` back to `pivot`. - * 2) Transition from `pivot` to `succ`. - * 3) Transition from `succ` to `succ`. + * 2) Transition from `pivot` to `pumpEnd`. + * 3) Transition from `pumpEnd` to `pumpEnd`. * * From theorem 3 in the paper linked in the top of this file we can therefore conclude that * the regular expression has polynomial backtracking - if a rejecting suffix exists. @@ -384,10 +473,10 @@ module Make<RegexTreeViewSig TreeImpl> { * This predicate is used by `SuperLinearReDoSConfiguration`, and the final results are * available in the `hasReDoSResult` predicate. */ - predicate isPumpable(State pivot, State succ, string pump) { + predicate isPumpable(State pivot, State pumpEnd, string pump) { exists(StateTuple q, Trace t | - isReachableFromStartTuple(pivot, succ, q, t, _) and - q = getAnEndTuple(pivot, succ) and + q = getEndTuple(pivot, pumpEnd) and + q = t.getTuple() and pump = Concretizer<CharTreeImpl>::concretize(t) ) } diff --git a/shared/tree-sitter-extractor/.gitignore b/shared/tree-sitter-extractor/.gitignore new file mode 100644 index 00000000000..4fffb2f89cb --- /dev/null +++ b/shared/tree-sitter-extractor/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/shared/tree-sitter-extractor/Cargo.toml b/shared/tree-sitter-extractor/Cargo.toml new file mode 100644 index 00000000000..4aa363f2965 --- /dev/null +++ b/shared/tree-sitter-extractor/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "codeql-extractor" +version = "0.1.0" +edition = "2021" +authors = ["GitHub"] + +[dependencies] +flate2 = "1.0" +tree-sitter = "0.20" +tracing = "0.1" +rayon = "1.5.0" +regex = "1.7.1" +encoding = "0.2" +lazy_static = "1.4.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +chrono = { version = "0.4.19", features = ["serde"] } +num_cpus = "1.14.0" diff --git a/ruby/extractor/src/diagnostics.rs b/shared/tree-sitter-extractor/src/diagnostics.rs similarity index 100% rename from ruby/extractor/src/diagnostics.rs rename to shared/tree-sitter-extractor/src/diagnostics.rs diff --git a/ruby/extractor/src/extractor.rs b/shared/tree-sitter-extractor/src/extractor.rs similarity index 100% rename from ruby/extractor/src/extractor.rs rename to shared/tree-sitter-extractor/src/extractor.rs diff --git a/ruby/extractor/src/file_paths.rs b/shared/tree-sitter-extractor/src/file_paths.rs similarity index 100% rename from ruby/extractor/src/file_paths.rs rename to shared/tree-sitter-extractor/src/file_paths.rs diff --git a/ruby/extractor/src/generator/dbscheme.rs b/shared/tree-sitter-extractor/src/generator/dbscheme.rs similarity index 100% rename from ruby/extractor/src/generator/dbscheme.rs rename to shared/tree-sitter-extractor/src/generator/dbscheme.rs diff --git a/ql/generator/src/language.rs b/shared/tree-sitter-extractor/src/generator/language.rs similarity index 100% rename from ql/generator/src/language.rs rename to shared/tree-sitter-extractor/src/generator/language.rs diff --git a/ruby/extractor/src/generator/mod.rs b/shared/tree-sitter-extractor/src/generator/mod.rs similarity index 100% rename from ruby/extractor/src/generator/mod.rs rename to shared/tree-sitter-extractor/src/generator/mod.rs diff --git a/ql/generator/src/ql.rs b/shared/tree-sitter-extractor/src/generator/ql.rs similarity index 100% rename from ql/generator/src/ql.rs rename to shared/tree-sitter-extractor/src/generator/ql.rs diff --git a/ruby/extractor/src/generator/ql_gen.rs b/shared/tree-sitter-extractor/src/generator/ql_gen.rs similarity index 100% rename from ruby/extractor/src/generator/ql_gen.rs rename to shared/tree-sitter-extractor/src/generator/ql_gen.rs diff --git a/ruby/extractor/src/lib.rs b/shared/tree-sitter-extractor/src/lib.rs similarity index 86% rename from ruby/extractor/src/lib.rs rename to shared/tree-sitter-extractor/src/lib.rs index 88c54864f4b..eb175417993 100644 --- a/ruby/extractor/src/lib.rs +++ b/shared/tree-sitter-extractor/src/lib.rs @@ -3,4 +3,5 @@ pub mod extractor; pub mod file_paths; pub mod generator; pub mod node_types; +pub mod options; pub mod trap; diff --git a/ruby/extractor/src/node_types.rs b/shared/tree-sitter-extractor/src/node_types.rs similarity index 100% rename from ruby/extractor/src/node_types.rs rename to shared/tree-sitter-extractor/src/node_types.rs diff --git a/shared/tree-sitter-extractor/src/options.rs b/shared/tree-sitter-extractor/src/options.rs new file mode 100644 index 00000000000..1b43a215994 --- /dev/null +++ b/shared/tree-sitter-extractor/src/options.rs @@ -0,0 +1,44 @@ +use num_cpus; + +/// Gets the number of threads the extractor should use. +/// This is controlled by the CODEQL_THREADS environment variable. +pub fn num_threads() -> Result<usize, String> { + let threads_str = std::env::var("CODEQL_THREADS").unwrap_or_else(|_| "-1".into()); + let num_cpus = num_cpus::get(); + parse_codeql_threads(&threads_str, num_cpus) + .ok_or_else(|| format!("Unable to parse CODEQL_THREADS value '{}'", &threads_str)) +} + +/// Parses the given string to determine the number of threads the extractor +/// should use, as described in the extractor spec: +/// +/// "If the number is positive, it indicates the number of threads that should +/// be used. If the number is negative or zero, it should be added to the number +/// of cores available on the machine to determine how many threads to use +/// (minimum of 1). If unspecified, should be considered as set to -1." +/// +/// # Examples +/// +/// ``` +/// use codeql_extractor::options::parse_codeql_threads; +/// +/// assert_eq!(parse_codeql_threads("1", 4), Some(1)); +/// assert_eq!(parse_codeql_threads("5", 4), Some(5)); +/// assert_eq!(parse_codeql_threads("0", 4), Some(4)); +/// assert_eq!(parse_codeql_threads("-1", 4), Some(3)); +/// assert_eq!(parse_codeql_threads("-3", 4), Some(1)); +/// assert_eq!(parse_codeql_threads("-4", 4), Some(1)); +/// assert_eq!(parse_codeql_threads("-5", 4), Some(1)); +/// assert_eq!(parse_codeql_threads("nope", 4), None); +/// ``` +pub fn parse_codeql_threads(threads_str: &str, num_cpus: usize) -> Option<usize> { + match threads_str.parse::<i32>() { + Ok(num) if num <= 0 => { + let reduction = num.abs_diff(0) as usize; + Some(std::cmp::max(1, num_cpus.saturating_sub(reduction))) + } + Ok(num) => Some(num as usize), + + Err(_) => None, + } +} diff --git a/ruby/extractor/src/trap.rs b/shared/tree-sitter-extractor/src/trap.rs similarity index 100% rename from ruby/extractor/src/trap.rs rename to shared/tree-sitter-extractor/src/trap.rs diff --git a/swift/downgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/old.dbscheme b/swift/downgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/old.dbscheme new file mode 100644 index 00000000000..e646f9e0308 --- /dev/null +++ b/swift/downgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/old.dbscheme @@ -0,0 +1,2602 @@ +// generated by codegen/codegen.py + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @callable +| @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@callable = + @abstract_closure_expr +| @abstract_function_decl +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @case_label_item +| @condition_element +| @decl +| @expr +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @abstract_function_decl +| @extension_decl +| @generic_type_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_function_decl +| @abstract_storage_decl +| @enum_element_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_function_decl = + @constructor_decl +| @destructor_decl +| @func_decl +; + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessor_decls( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor_decl: @accessor_decl_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_base_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int base_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +constructor_decls( //dir=decl + unique int id: @constructor_decl +); + +destructor_decls( //dir=decl + unique int id: @destructor_decl +); + +@func_decl = + @accessor_decl +| @concrete_func_decl +; + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id, index] +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessor_decls( //dir=decl + unique int id: @accessor_decl +); + +#keyset[id] +accessor_decl_is_getter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_setter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_will_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_did_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_read( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_modify( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_address( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_mutable_address( //dir=decl + int id: @accessor_decl ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_func_decls( //dir=decl + unique int id: @concrete_func_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl, + int aliased_type: @type_or_none ref +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @abstract_closure_expr +| @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @collection_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initializer_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_constructor_decl_ref_expr +| @overloaded_decl_ref_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_constructor_expr +| @sequence_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@abstract_closure_expr = + @auto_closure_expr +| @closure_expr +; + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@collection_expr = + @array_expr +| @dictionary_expr +; + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id] +key_path_expr_parsed_paths( //dir=expr + int id: @key_path_expr ref, + int parsed_path: @expr_or_none ref +); + +lazy_initializer_exprs( //dir=expr + unique int id: @lazy_initializer_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @abstract_function_decl_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_constructor_decl_ref_exprs( //dir=expr + unique int id: @other_constructor_decl_ref_expr, + int constructor_decl: @constructor_decl_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_constructor_exprs( //dir=expr + unique int id: @rebind_self_in_constructor_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +closure_exprs( //dir=expr + unique int id: @closure_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_count_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int literal_capacity_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @constructor_ref_call_expr +| @dot_syntax_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +constructor_ref_call_exprs( //dir=expr + unique int id: @constructor_ref_call_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + string name: string ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int sequence: @expr_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @opaque_type_archetype_type +| @opened_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@abstract_function_decl_or_none = + @abstract_function_decl +| @unspecified_element +; + +@accessor_decl_or_none = + @accessor_decl +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@constructor_decl_or_none = + @constructor_decl +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/downgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/swift.dbscheme b/swift/downgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/swift.dbscheme new file mode 100644 index 00000000000..c2f01f2beb6 --- /dev/null +++ b/swift/downgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/swift.dbscheme @@ -0,0 +1,2601 @@ +// generated by codegen/codegen.py + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @callable +| @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@callable = + @abstract_closure_expr +| @abstract_function_decl +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @case_label_item +| @condition_element +| @decl +| @expr +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @abstract_function_decl +| @extension_decl +| @generic_type_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_function_decl +| @abstract_storage_decl +| @enum_element_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_function_decl = + @constructor_decl +| @destructor_decl +| @func_decl +; + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessor_decls( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor_decl: @accessor_decl_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_base_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int base_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +constructor_decls( //dir=decl + unique int id: @constructor_decl +); + +destructor_decls( //dir=decl + unique int id: @destructor_decl +); + +@func_decl = + @accessor_decl +| @concrete_func_decl +; + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id, index] +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessor_decls( //dir=decl + unique int id: @accessor_decl +); + +#keyset[id] +accessor_decl_is_getter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_setter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_will_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_did_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_read( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_modify( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_address( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_mutable_address( //dir=decl + int id: @accessor_decl ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_func_decls( //dir=decl + unique int id: @concrete_func_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @abstract_closure_expr +| @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @collection_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initializer_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_constructor_decl_ref_expr +| @overloaded_decl_ref_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_constructor_expr +| @sequence_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@abstract_closure_expr = + @auto_closure_expr +| @closure_expr +; + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@collection_expr = + @array_expr +| @dictionary_expr +; + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id] +key_path_expr_parsed_paths( //dir=expr + int id: @key_path_expr ref, + int parsed_path: @expr_or_none ref +); + +lazy_initializer_exprs( //dir=expr + unique int id: @lazy_initializer_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @abstract_function_decl_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_constructor_decl_ref_exprs( //dir=expr + unique int id: @other_constructor_decl_ref_expr, + int constructor_decl: @constructor_decl_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_constructor_exprs( //dir=expr + unique int id: @rebind_self_in_constructor_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +closure_exprs( //dir=expr + unique int id: @closure_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_count_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int literal_capacity_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @constructor_ref_call_expr +| @dot_syntax_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +constructor_ref_call_exprs( //dir=expr + unique int id: @constructor_ref_call_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + string name: string ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int sequence: @expr_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @opaque_type_archetype_type +| @opened_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@abstract_function_decl_or_none = + @abstract_function_decl +| @unspecified_element +; + +@accessor_decl_or_none = + @accessor_decl +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@constructor_decl_or_none = + @constructor_decl +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/downgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/type_alias_decls.ql b/swift/downgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/type_alias_decls.ql new file mode 100644 index 00000000000..72f89e3946d --- /dev/null +++ b/swift/downgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/type_alias_decls.ql @@ -0,0 +1,6 @@ +class TypeAliasDecl extends @type_alias_decl { + string toString() { result = "TypeAliasDecl" } +} + +from TypeAliasDecl id +select id diff --git a/swift/downgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/upgrade.properties b/swift/downgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/upgrade.properties new file mode 100644 index 00000000000..31ffe35bf1c --- /dev/null +++ b/swift/downgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/upgrade.properties @@ -0,0 +1,3 @@ +description: Revert adding TypeAliasDecl.getAliasedType() +compatibility: full +type_alias_decls.rel: run type_alias_decls.qlo diff --git a/swift/extractor/infra/SwiftDispatcher.h b/swift/extractor/infra/SwiftDispatcher.h index b2c347e36e6..dcd903c242f 100644 --- a/swift/extractor/infra/SwiftDispatcher.h +++ b/swift/extractor/infra/SwiftDispatcher.h @@ -265,7 +265,8 @@ class SwiftDispatcher { private: bool isLazyDeclaration(const swift::Decl& decl) { swift::ModuleDecl* module = decl.getModuleContext(); - return module->isBuiltinModule() || module->getName().str() == "__ObjC"; + return module->isBuiltinModule() || module->getName().str() == "__ObjC" || + module->isNonSwiftModule(); } template <typename T, typename = void> diff --git a/swift/extractor/main.cpp b/swift/extractor/main.cpp index 8220f8a1164..bb4f1d775c2 100644 --- a/swift/extractor/main.cpp +++ b/swift/extractor/main.cpp @@ -1,5 +1,3 @@ -#include <fstream> -#include <iomanip> #include <stdlib.h> #include <vector> #include <iostream> @@ -18,7 +16,6 @@ #include "swift/extractor/invocation/SwiftInvocationExtractor.h" #include "swift/extractor/trap/TrapDomain.h" #include "swift/extractor/infra/file/Path.h" -#include <swift/Basic/InitializeSwiftModules.h> using namespace std::string_literals; diff --git a/swift/extractor/translators/DeclTranslator.cpp b/swift/extractor/translators/DeclTranslator.cpp index 415f870df55..453379b2984 100644 --- a/swift/extractor/translators/DeclTranslator.cpp +++ b/swift/extractor/translators/DeclTranslator.cpp @@ -206,6 +206,7 @@ std::optional<codeql::AssociatedTypeDecl> DeclTranslator::translateAssociatedTyp std::optional<codeql::TypeAliasDecl> DeclTranslator::translateTypeAliasDecl( const swift::TypeAliasDecl& decl) { if (auto entry = createNamedEntry(decl)) { + entry->aliased_type = dispatcher.fetchLabel(decl.getUnderlyingType()); fillTypeDecl(decl, *entry); return entry; } diff --git a/swift/integration-tests/posix-only/deduplication/BuiltinTypes.expected b/swift/integration-tests/posix-only/deduplication/BuiltinTypes.expected index 881be23da5e..53b3a353f64 100644 --- a/swift/integration-tests/posix-only/deduplication/BuiltinTypes.expected +++ b/swift/integration-tests/posix-only/deduplication/BuiltinTypes.expected @@ -13,6 +13,7 @@ | Builtin.NativeObject | BuiltinNativeObjectType | | Builtin.RawPointer | BuiltinRawPointerType | | Builtin.RawUnsafeContinuation | BuiltinRawUnsafeContinuationType | +| Builtin.UnsafeValueBuffer | BuiltinUnsafeValueBufferType | | Builtin.Vec2xFPIEEE32 | BuiltinVectorType | | Builtin.Vec2xFPIEEE64 | BuiltinVectorType | | Builtin.Vec2xInt8 | BuiltinVectorType | diff --git a/swift/ql/.generated.list b/swift/ql/.generated.list index 4c93ef9d164..2a0d663241d 100644 --- a/swift/ql/.generated.list +++ b/swift/ql/.generated.list @@ -232,7 +232,6 @@ ql/lib/codeql/swift/elements/pattern/IsPatternConstructor.qll 209ad40227f49dfe1b ql/lib/codeql/swift/elements/pattern/NamedPatternConstructor.qll 437ccf0a28c204a83861babc91e0e422846630f001554a3d7764b323c8632a26 91c52727ccf6b035cc1f0c2ca1eb91482ef28fa874bca382fb34f9226c31c84e ql/lib/codeql/swift/elements/pattern/OptionalSomePatternConstructor.qll bc33a81415edfa4294ad9dfb57f5aa929ea4d7f21a013f145949352009a93975 9fb2afa86dc9cedd28af9f27543ea8babf431a4ba48e9941bcd484b9aa0aeab5 ql/lib/codeql/swift/elements/pattern/ParenPatternConstructor.qll 7229439aac7010dbb82f2aaa48aedf47b189e21cc70cb926072e00faa8358369 341cfacd838185178e95a2a7bb29f198e46954098f6d13890351a82943969809 -ql/lib/codeql/swift/elements/pattern/Pattern.qll a5cee4c72446f884107acc248a10b098871dc027513452c569294aaeecbc5890 cbecbc4b2d9bea7b571b9d184a0bb8cf472f66106e96d4f70e0e98d627f269a5 ql/lib/codeql/swift/elements/pattern/TuplePatternConstructor.qll 208fe1f6af1eb569ea4cd5f76e8fbe4dfab9a6264f6c12b762f074a237934bdc 174c55ad1bf3058059ed6c3c3502d6099cda95fbfce925cfd261705accbddbcd ql/lib/codeql/swift/elements/pattern/TypedPatternConstructor.qll 1befdd0455e94d4daa0332b644b74eae43f98bab6aab7491a37176a431c36c34 e574ecf38aac7d9381133bfb894da8cb96aec1c933093f4f7cc951dba8152570 ql/lib/codeql/swift/elements/stmt/BraceStmtConstructor.qll eb2b4817d84da4063eaa0b95fe22131cc980c761dcf41f1336566e95bc28aae4 c8e5f7fecd01a7724d8f58c2cd8c845264be91252281f37e3eb20f4a6f421c72 @@ -382,10 +381,10 @@ ql/lib/codeql/swift/generated/File.qll f88c485883dd9b2b4a366080e098372912e03fb31 ql/lib/codeql/swift/generated/Locatable.qll bdc98b9fb7788f44a4bf7e487ee5bd329473409950a8e9f116d61995615ad849 0b36b4fe45e2aa195e4bb70c50ea95f32f141b8e01e5f23466c6427dd9ab88fb ql/lib/codeql/swift/generated/Location.qll 851766e474cdfdfa67da42e0031fc42dd60196ff5edd39d82f08d3e32deb84c1 b29b2c37672f5acff15f1d3c5727d902f193e51122327b31bd27ec5f877bca3b ql/lib/codeql/swift/generated/OtherAvailabilitySpec.qll 0e26a203b26ff0581b7396b0c6d1606feec5cc32477f676585cdec4911af91c5 0e26a203b26ff0581b7396b0c6d1606feec5cc32477f676585cdec4911af91c5 -ql/lib/codeql/swift/generated/ParentChild.qll 0ac2139b8b2e172858262d80950a0212b21fe46bf6af7259d9058fb7193f8242 6f7464ecd8ca04b6aa261139b36a162e5b0636237d514b8431ef4f97a1c603dc +ql/lib/codeql/swift/generated/ParentChild.qll 7d45d4e872e769f37a5b157ba422c48afe482552e44d94ff5f6a5a6449d672e7 6f7464ecd8ca04b6aa261139b36a162e5b0636237d514b8431ef4f97a1c603dc ql/lib/codeql/swift/generated/PlatformVersionAvailabilitySpec.qll f82d9ca416fe8bd59b5531b65b1c74c9f317b3297a6101544a11339a1cffce38 7f5c6d3309e66c134107afe55bae76dfc9a72cb7cdd6d4c3706b6b34cee09fa0 ql/lib/codeql/swift/generated/PureSynthConstructors.qll 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98 -ql/lib/codeql/swift/generated/Raw.qll efe60f045f8a4aecedd7bfe8110c0c10539bcdcb9f17f342cf560c8d065e6aff 261825907250bb4ddeba8ccce0df29b45f13c6fb338eb41a06ea6b43e7aa9788 +ql/lib/codeql/swift/generated/Raw.qll b1ad09374cf2d5556e0a409a59eea723a7280882ae144f68fd2dae362cb147b7 587433583a7e93c9a8534cb59409fd802e4b6587faf1367df9447d06be191c73 ql/lib/codeql/swift/generated/Synth.qll af02e0b49fe7b488592687996cc74d9525d4e3fbc9d324820b310b356f4d2612 5c740a660721173e9e4e45eb701d373ca19ff14d61cdaea309b65871e0deea90 ql/lib/codeql/swift/generated/SynthConstructors.qll a1b3ca33017f82124286ccad317a05484fee144fb9c3cdd2e500ce38e5efcec4 a1b3ca33017f82124286ccad317a05484fee144fb9c3cdd2e500ce38e5efcec4 ql/lib/codeql/swift/generated/UnknownFile.qll 0fcf9beb8de79440bcdfff4bb6ab3dd139bd273e6c32754e05e6a632651e85f6 0fcf9beb8de79440bcdfff4bb6ab3dd139bd273e6c32754e05e6a632651e85f6 @@ -429,7 +428,7 @@ ql/lib/codeql/swift/generated/decl/ProtocolDecl.qll 4b03e3c2a7af66e66e8abc40bd2e ql/lib/codeql/swift/generated/decl/StructDecl.qll 9343b001dfeec83a6b41e88dc1ec75744d39c397e8e48441aa4d01493f10026a 9343b001dfeec83a6b41e88dc1ec75744d39c397e8e48441aa4d01493f10026a ql/lib/codeql/swift/generated/decl/SubscriptDecl.qll 31cb1f90d4c60060f64c432850821969953f1a46e36ce772456c67dfff375ff5 1d0098518c56aed96039b0b660b2cce5ea0db7ac4c9a550af07d758e282d4f61 ql/lib/codeql/swift/generated/decl/TopLevelCodeDecl.qll aececf62fda517bd90b1c56bb112bb3ee2eecac3bb2358a889dc8c4de898346e d8c69935ac88f0343a03f17ea155653b97e9b9feff40586cfa8452ac5232700d -ql/lib/codeql/swift/generated/decl/TypeAliasDecl.qll 15cb5bdbe9d722c403874f744bfb3da85f532e33638a64a593acbbdee2f6095e 15cb5bdbe9d722c403874f744bfb3da85f532e33638a64a593acbbdee2f6095e +ql/lib/codeql/swift/generated/decl/TypeAliasDecl.qll 640912badc9d2278b6d14a746d85ed71b17c52cd1f2006aef46d5a4aeaa544f2 a6cbe000ea9d5d1ccd37eb50c23072e19ee0234d53dcb943fef20e3f553fcf4e ql/lib/codeql/swift/generated/decl/TypeDecl.qll 74bb5f0fe2648d95c84fdce804740f2bba5c7671e15cbea671d8509456bf5c2b 32bc7154c8585c25f27a3587bb4ba039c8d69f09d945725e45d730de44f7a5ae ql/lib/codeql/swift/generated/decl/ValueDecl.qll 7b4e4c9334be676f242857c77099306d8a0a4357b253f8bc68f71328cedf1f58 f18938c47f670f2e0c27ffd7e31e55f291f88fb50d8e576fcea116d5f9e5c66d ql/lib/codeql/swift/generated/decl/VarDecl.qll bdea76fe6c8f721bae52bbc26a2fc1cbd665a19a6920b36097822839158d9d3b 9c91d8159fd7a53cba479d8c8f31f49ad2b1e2617b8cd9e7d1a2cb4796dfa2da diff --git a/swift/ql/lib/codeql/swift/Unit.qll b/swift/ql/lib/codeql/swift/Unit.qll index e9611ed3df4..83a4a03321d 100644 --- a/swift/ql/lib/codeql/swift/Unit.qll +++ b/swift/ql/lib/codeql/swift/Unit.qll @@ -1,10 +1,3 @@ /** Provides the `Unit` class. */ -/** The unit type. */ -private newtype TUnit = TMkUnit() - -/** The trivial type with a single element. */ -class Unit extends TUnit { - /** Gets a textual representation of this element. */ - string toString() { result = "unit" } -} +import codeql.util.Unit diff --git a/swift/ql/lib/codeql/swift/controlflow/CfgNodes.qll b/swift/ql/lib/codeql/swift/controlflow/CfgNodes.qll index 2754f705fa8..b1b93a17e4d 100644 --- a/swift/ql/lib/codeql/swift/controlflow/CfgNodes.qll +++ b/swift/ql/lib/codeql/swift/controlflow/CfgNodes.qll @@ -118,6 +118,16 @@ class ExprCfgNode extends CfgNode { Expr getExpr() { result = e } } +/** A control-flow node that wraps a pattern. */ +class PatternCfgNode extends CfgNode { + Pattern p; + + PatternCfgNode() { p = this.getNode().asAstNode() } + + /** Gets the underlying pattern. */ + Pattern getPattern() { result = p } +} + /** A control-flow node that wraps a property getter. */ class PropertyGetterCfgNode extends CfgNode { override PropertyGetterElement n; diff --git a/swift/ql/lib/codeql/swift/controlflow/internal/Completion.qll b/swift/ql/lib/codeql/swift/controlflow/internal/Completion.qll index 4de54b4b0ec..aa95602fd97 100644 --- a/swift/ql/lib/codeql/swift/controlflow/internal/Completion.qll +++ b/swift/ql/lib/codeql/swift/controlflow/internal/Completion.qll @@ -185,7 +185,7 @@ private predicate switchMatching(SwitchStmt switch, CaseStmt c, AstNode ast) { ( c.getALabel() = ast or - isSubPattern+(c.getALabel().getPattern(), ast) + ast.(Pattern).getImmediateEnclosingPattern+() = c.getALabel().getPattern() ) } @@ -216,27 +216,10 @@ predicate catchMatchingPattern(DoCatchStmt s, CaseStmt c, Pattern pattern) { exists(CaseLabelItem cli | catchMatching(s, c, cli) | cli.getPattern() = pattern or - isSubPattern+(cli.getPattern(), pattern) + pattern.getImmediateEnclosingPattern+() = cli.getPattern() ) } -/** Holds if `sub` is a subpattern of `p`. */ -private predicate isSubPattern(Pattern p, Pattern sub) { - sub = p.(BindingPattern).getSubPattern().getFullyUnresolved() - or - sub = p.(EnumElementPattern).getSubPattern().getFullyUnresolved() - or - sub = p.(IsPattern).getSubPattern().getFullyUnresolved() - or - sub = p.(OptionalSomePattern).getFullyUnresolved() - or - sub = p.(ParenPattern).getResolveStep() - or - sub = p.(TuplePattern).getAnElement().getFullyUnresolved() - or - sub = p.(TypedPattern).getSubPattern().getFullyUnresolved() -} - /** Gets the value of `e` if it is a constant value, disregarding conversions. */ private string getExprValue(Expr e) { result = e.(IntegerLiteralExpr).getStringValue() @@ -260,8 +243,6 @@ private string getPatternValue(Pattern p) { private predicate isIrrefutableMatch(Pattern p) { (p instanceof NamedPattern or p instanceof AnyPattern) or - isIrrefutableMatch(p.(BindingPattern).getSubPattern().getFullyUnresolved()) - or isIrrefutableMatch(p.(TypedPattern).getSubPattern().getFullyUnresolved()) or // A pattern hidden underneath a conversion is also an irrefutable pattern. diff --git a/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImpl.qll b/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImpl.qll index b93e972e6ff..80f07564747 100644 --- a/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImpl.qll +++ b/swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImpl.qll @@ -897,21 +897,12 @@ module Patterns { } } - private class BindingTree extends AstPostOrderTree { + private class BindingTree extends AstStandardPostOrderTree { override BindingPattern ast; - final override predicate propagatesAbnormal(ControlFlowElement n) { - n.asAstNode() = ast.getSubPattern().getFullyUnresolved() - } - - final override predicate first(ControlFlowElement n) { - astFirst(ast.getSubPattern().getFullyUnresolved(), n) - } - - override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) { - astLast(ast.getSubPattern().getFullyUnresolved(), pred, c) and - c.(MatchingCompletion).isMatch() and - succ.asAstNode() = ast + final override ControlFlowElement getChildElement(int i) { + i = 0 and + result.asAstNode() = ast.getResolveStep() } } diff --git a/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll b/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll index 214de0d5455..ab4743dadeb 100644 --- a/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll +++ b/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll @@ -16,7 +16,8 @@ * 1. The `namespace` column selects a package. * 2. The `type` column selects a type within that package. * 3. The `subtypes` is a boolean that indicates whether to jump to an - * arbitrary subtype of that type. + * arbitrary subtype of that type. Set this to `false` if leaving the `type` + * blank (for example, a free function). * 4. The `name` column optionally selects a specific named member of the type. * 5. The `signature` column optionally restricts the named member. If * `signature` is blank then no such filtering is done. The format of the diff --git a/swift/ql/lib/codeql/swift/dataflow/Ssa.qll b/swift/ql/lib/codeql/swift/dataflow/Ssa.qll index ae4b4738a64..16ff1d27924 100644 --- a/swift/ql/lib/codeql/swift/dataflow/Ssa.qll +++ b/swift/ql/lib/codeql/swift/dataflow/Ssa.qll @@ -38,9 +38,9 @@ module Ssa { // if let x5 = optional { ... } // guard let x6 = optional else { ... } // ``` - exists(Pattern pattern | + exists(NamedPattern pattern | bb.getNode(i).getNode().asAstNode() = pattern and - v.getParentPattern() = pattern and + v = pattern.getVarDecl() and certain = true ) or @@ -153,14 +153,10 @@ module Ssa { value.getNode().asAstNode() = a.getSource() ) or - exists( - VarDecl var, SsaInput::BasicBlock bb, int blockIndex, PatternBindingDecl pbd, Expr init - | - this.definesAt(var, bb, blockIndex) and - pbd.getAPattern() = bb.getNode(blockIndex).getNode().asAstNode() and - init = var.getParentInitializer() - | - value.getAst() = init + exists(SsaInput::BasicBlock bb, int blockIndex, NamedPattern np | + this.definesAt(_, bb, blockIndex) and + np = bb.getNode(blockIndex).getNode().asAstNode() and + value.getNode().asAstNode() = np ) or exists(SsaInput::BasicBlock bb, int blockIndex, ConditionElement ce, Expr init | diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlow.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlow.qll index 617362ab4f0..865d7b4d6ce 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlow.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlow.qll @@ -2,7 +2,7 @@ * Provides an implementation of global (interprocedural) data flow. This file * re-exports the local (intraprocedural) data flow analysis from * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Make` and `MakeWithState` modules. + * through the `Global` and `GlobalWithState` modules. */ private import DataFlowImplCommon @@ -73,10 +73,10 @@ signature module ConfigSig { */ default FlowFeature getAFeature() { none() } - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ default predicate sourceGrouping(Node source, string sourceGroup) { none() } - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ default predicate sinkGrouping(Node sink, string sinkGroup) { none() } /** @@ -166,10 +166,10 @@ signature module StateConfigSig { */ default FlowFeature getAFeature() { none() } - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ default predicate sourceGrouping(Node source, string sourceGroup) { none() } - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ default predicate sinkGrouping(Node sink, string sinkGroup) { none() } /** @@ -182,15 +182,15 @@ signature module StateConfigSig { } /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * Gets the exploration limit for `partialFlow` and `partialFlowRev` * measured in approximate number of interprocedural steps. */ signature int explorationLimitSig(); /** - * The output of a data flow computation. + * The output of a global data flow computation. */ -signature module DataFlowSig { +signature module GlobalFlowSig { /** * A `Node` augmented with a call context (except for sinks) and an access path. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. @@ -203,28 +203,28 @@ signature module DataFlowSig { * The corresponding paths are generated from the end-points and the graph * included in the module `PathGraph`. */ - predicate hasFlowPath(PathNode source, PathNode sink); + predicate flowPath(PathNode source, PathNode sink); /** * Holds if data can flow from `source` to `sink`. */ - predicate hasFlow(Node source, Node sink); + predicate flow(Node source, Node sink); /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowTo(Node sink); + predicate flowTo(Node sink); /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowToExpr(DataFlowExpr sink); + predicate flowToExpr(DataFlowExpr sink); } /** - * Constructs a standard data flow computation. + * Constructs a global data flow computation. */ -module Make<ConfigSig Config> implements DataFlowSig { +module Global<ConfigSig Config> implements GlobalFlowSig { private module C implements FullStateConfigSig { import DefaultState<Config> import Config @@ -233,10 +233,15 @@ module Make<ConfigSig Config> implements DataFlowSig { import Impl<C> } +/** DEPRECATED: Use `Global` instead. */ +deprecated module Make<ConfigSig Config> implements GlobalFlowSig { + import Global<Config> +} + /** - * Constructs a data flow computation using flow state. + * Constructs a global data flow computation using flow state. */ -module MakeWithState<StateConfigSig Config> implements DataFlowSig { +module GlobalWithState<StateConfigSig Config> implements GlobalFlowSig { private module C implements FullStateConfigSig { import Config } @@ -244,6 +249,11 @@ module MakeWithState<StateConfigSig Config> implements DataFlowSig { import Impl<C> } +/** DEPRECATED: Use `GlobalWithState` instead. */ +deprecated module MakeWithState<StateConfigSig Config> implements GlobalFlowSig { + import GlobalWithState<Config> +} + signature class PathNodeSig { /** Gets a textual representation of this element. */ string toString(); diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll index c47b0308855..6ea97954bdf 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll @@ -8,6 +8,7 @@ private import DataFlowImplCommon private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommonPublic +private import codeql.util.Unit import DataFlow /** @@ -91,10 +92,10 @@ signature module FullStateConfigSig { */ FlowFeature getAFeature(); - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + /** Holds if sources should be grouped in the result of `flowPath`. */ predicate sourceGrouping(Node source, string sourceGroup); - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + /** Holds if sinks should be grouped in the result of `flowPath`. */ predicate sinkGrouping(Node sink, string sinkGroup); /** @@ -445,11 +446,7 @@ module Impl<FullStateConfigSig Config> { } private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } + class Ap = Unit; private class Cc = boolean; @@ -3633,7 +3630,7 @@ module Impl<FullStateConfigSig Config> { * The corresponding paths are generated from the end-points and the graph * included in the module `PathGraph`. */ - predicate hasFlowPath(PathNode source, PathNode sink) { + predicate flowPath(PathNode source, PathNode sink) { exists(PathNodeImpl flowsource, PathNodeImpl flowsink | source = flowsource and sink = flowsink | @@ -3643,6 +3640,9 @@ module Impl<FullStateConfigSig Config> { ) } + /** DEPRECATED: Use `flowPath` instead. */ + deprecated predicate hasFlowPath = flowPath/2; + private predicate flowsTo(PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink) { flowsource.isSource() and flowsource.getNodeEx().asNode() = source and @@ -3653,17 +3653,26 @@ module Impl<FullStateConfigSig Config> { /** * Holds if data can flow from `source` to `sink`. */ - predicate hasFlow(Node source, Node sink) { flowsTo(_, _, source, sink) } + predicate flow(Node source, Node sink) { flowsTo(_, _, source, sink) } + + /** DEPRECATED: Use `flow` instead. */ + deprecated predicate hasFlow = flow/2; /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + predicate flowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + + /** DEPRECATED: Use `flowTo` instead. */ + deprecated predicate hasFlowTo = flowTo/1; /** * Holds if data can flow from some source to `sink`. */ - predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + predicate flowToExpr(DataFlowExpr sink) { flowTo(exprNode(sink)) } + + /** DEPRECATED: Use `flowToExpr` instead. */ + deprecated predicate hasFlowToExpr = flowToExpr/1; private predicate finalStats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples @@ -4574,7 +4583,7 @@ module Impl<FullStateConfigSig Config> { * * To use this in a `path-problem` query, import the module `PartialPathGraph`. */ - predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { + predicate partialFlow(PartialPathNode source, PartialPathNode node, int dist) { partialFlow(source, node) and dist = node.getSourceDistance() } @@ -4594,7 +4603,7 @@ module Impl<FullStateConfigSig Config> { * Note that reverse flow has slightly lower precision than the corresponding * forward flow, as reverse flow disregards type pruning among other features. */ - predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { + predicate partialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { revPartialFlow(node, sink) and dist = node.getSinkDistance() } diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll index e6bdc74cceb..be70086a93a 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll @@ -1,5 +1,5 @@ /** - * DEPRECATED: Use `Make` and `MakeWithState` instead. + * DEPRECATED: Use `Global` and `GlobalWithState` instead. * * Provides a `Configuration` class backwards-compatible interface to the data * flow library. @@ -11,6 +11,7 @@ import DataFlowImplSpecific::Public private import DataFlowImpl import DataFlowImplCommonPublic import FlowStateString +private import codeql.util.Unit /** * A configuration of interprocedural data flow analysis. This defines @@ -328,7 +329,6 @@ private module Config implements FullStateConfigSig { } private import Impl<Config> as I -import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. @@ -379,6 +379,8 @@ class PathNode instanceof I::PathNode { final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } +module PathGraph = I::PathGraph; + private predicate hasFlow(Node source, Node sink, Configuration config) { exists(PathNode source0, PathNode sink0 | hasFlowPath(source0, sink0, config) and @@ -388,7 +390,7 @@ private predicate hasFlow(Node source, Node sink, Configuration config) { } private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { - hasFlowPath(source, sink) and source.getConfiguration() = config + I::flowPath(source, sink) and source.getConfiguration() = config } private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll index d09fdcfca3e..e6fce328326 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll @@ -140,10 +140,8 @@ private module LambdaFlow { } pragma[nomagic] - private TReturnPositionSimple viableReturnPosLambda( - DataFlowCall call, DataFlowCallOption lastCall, ReturnKind kind - ) { - result = TReturnPositionSimple0(viableCallableLambda(call, lastCall), kind) + private TReturnPositionSimple viableReturnPosLambda(DataFlowCall call, ReturnKind kind) { + result = TReturnPositionSimple0(viableCallableLambda(call, _), kind) } private predicate viableReturnPosOutNonLambda( @@ -155,11 +153,12 @@ private module LambdaFlow { ) } + pragma[nomagic] private predicate viableReturnPosOutLambda( - DataFlowCall call, DataFlowCallOption lastCall, TReturnPositionSimple pos, OutNode out + DataFlowCall call, TReturnPositionSimple pos, OutNode out ) { exists(ReturnKind kind | - pos = viableReturnPosLambda(call, lastCall, kind) and + pos = viableReturnPosLambda(call, kind) and out = getAnOutNode(call, kind) ) } @@ -188,6 +187,7 @@ private module LambdaFlow { else any() } + pragma[assume_small_delta] pragma[nomagic] predicate revLambdaFlow0( DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn, @@ -274,6 +274,7 @@ private module LambdaFlow { ) } + pragma[assume_small_delta] pragma[nomagic] predicate revLambdaFlowOut( DataFlowCall lambdaCall, LambdaCallKind kind, TReturnPositionSimple pos, DataFlowType t, @@ -285,7 +286,7 @@ private module LambdaFlow { or // non-linear recursion revLambdaFlowOutLambdaCall(lambdaCall, kind, out, t, toJump, call, lastCall) and - viableReturnPosOutLambda(call, _, pos, out) + viableReturnPosOutLambda(call, pos, out) ) } diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplSpecific.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplSpecific.qll index 5679ad2ae5d..9244a08582c 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplSpecific.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplSpecific.qll @@ -8,8 +8,6 @@ private import swift as Swift module Private { import DataFlowPrivate import DataFlowDispatch - - class Unit = Swift::Unit; } module Public { diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll index 82d2e3a9e41..25bc8adfccc 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPrivate.qll @@ -40,6 +40,14 @@ private class ExprNodeImpl extends ExprNode, NodeImpl { override DataFlowCallable getEnclosingCallable() { result = TDataFlowFunc(n.getScope()) } } +private class PatternNodeImpl extends PatternNode, NodeImpl { + override Location getLocationImpl() { result = pattern.getLocation() } + + override string toStringImpl() { result = pattern.toString() } + + override DataFlowCallable getEnclosingCallable() { result = TDataFlowFunc(n.getScope()) } +} + private class SsaDefinitionNodeImpl extends SsaDefinitionNode, NodeImpl { override Location getLocationImpl() { result = def.getLocation() } @@ -63,6 +71,7 @@ private module Cached { cached newtype TNode = TExprNode(CfgNode n, Expr e) { hasExprNode(n, e) } or + TPatternNode(CfgNode n, Pattern p) { hasPatternNode(n, p) } or TSsaDefinitionNode(Ssa::Definition def) or TInoutReturnNode(ParamDecl param) { modifiableParam(param) } or TSummaryNode(FlowSummary::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) { @@ -175,6 +184,20 @@ private module Cached { nodeFrom.asExpr() = ie.getBranch(_) ) or + // flow from Expr to Pattern + exists(Expr e, Pattern p | + nodeFrom.asExpr() = e and + nodeTo.asPattern() = p and + p.getImmediateMatchingExpr() = e + ) + or + // flow from Pattern to an identity-preserving sub-Pattern: + nodeTo.asPattern() = + [ + nodeFrom.asPattern().(IsPattern).getSubPattern(), + nodeFrom.asPattern().(TypedPattern).getSubPattern() + ] + or // flow through a flow summary (extension of `SummaryModelCsv`) FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, true) } @@ -201,7 +224,8 @@ private module Cached { cached newtype TContent = TFieldContent(FieldDecl f) or - TTupleContent(int index) { exists(any(TupleExpr te).getElement(index)) } + TTupleContent(int index) { exists(any(TupleExpr te).getElement(index)) } or + TEnumContent(ParamDecl f) { exists(EnumElementDecl d | d.getAParam() = f) } } /** @@ -230,6 +254,11 @@ private predicate hasExprNode(CfgNode n, Expr e) { n.(PropertyObserverCfgNode).getAssignExpr() = e } +private predicate hasPatternNode(PatternCfgNode n, Pattern p) { + n.getPattern() = p and + p = p.resolve() // no need to turn hidden-AST patterns (`let`s, parens) into data flow nodes +} + import Cached /** Holds if `n` should be hidden from path explanations. */ @@ -558,6 +587,29 @@ predicate storeStep(Node node1, ContentSet c, Node node2) { c.isSingleton(any(Content::TupleContent tc | tc.getIndex() = tuple.getIndex())) ) or + // creation of an enum `.variant(v1, v2)` + exists(EnumElementExpr enum, int pos | + node1.asExpr() = enum.getArgument(pos).getExpr() and + node2.asExpr() = enum and + c.isSingleton(any(Content::EnumContent ec | ec.getParam() = enum.getElement().getParam(pos))) + ) + or + // creation of an optional via implicit conversion, + // i.e. from `f(x)` where `x: T` into `f(.some(x))` where the context `f` expects a `T?`. + exists(InjectIntoOptionalExpr e | + e.convertsFrom(node1.asExpr()) and + node2 = node1 and // HACK: we should ideally have a separate Node case for the (hidden) InjectIntoOptionalExpr + c instanceof OptionalSomeContentSet + ) + or + // creation of an optional by returning from a failable initializer (`init?`) + exists(ConstructorDecl init | + node1.asExpr().(CallExpr).getStaticTarget() = init and + node2 = node1 and // HACK: again, we should ideally have a separate Node case here, and not reuse the CallExpr + c instanceof OptionalSomeContentSet and + init.isFailable() + ) + or FlowSummaryImpl::Private::Steps::summaryStoreStep(node1, c, node2) } @@ -578,6 +630,34 @@ predicate readStep(Node node1, ContentSet c, Node node2) { node2.asExpr() = tuple and c.isSingleton(any(Content::TupleContent tc | tc.getIndex() = tuple.getIndex())) ) + or + // read of an enum member via `case let .variant(v1, v2)` pattern matching + exists(EnumElementPattern enumPat, ParamDecl enumParam, Pattern subPat | + node1.asPattern() = enumPat and + node2.asPattern() = subPat and + c.isSingleton(any(Content::EnumContent ec | ec.getParam() = enumParam)) + | + exists(int idx | + enumPat.getElement().getParam(idx) = enumParam and + enumPat.getSubPattern(idx) = subPat + ) + ) + or + // read of a tuple member via `case let (v1, v2)` pattern matching + exists(TuplePattern tupPat, int idx, Pattern subPat | + node1.asPattern() = tupPat and + node2.asPattern() = subPat and + c.isSingleton(any(Content::TupleContent tc | tc.getIndex() = idx)) + | + tupPat.getElement(idx) = subPat + ) + or + // read of an optional .some member via `let x: T = y: T?` pattern matching + exists(OptionalSomePattern pat | + node1.asPattern() = pat and + node2.asPattern() = pat.getSubPattern() and + c instanceof OptionalSomeContentSet + ) } /** @@ -595,6 +675,22 @@ predicate clearsContent(Node n, ContentSet c) { */ predicate expectsContent(Node n, ContentSet c) { none() } +/** + * The global singleton `Optional.some` content set. + */ +private class OptionalSomeContentSet extends ContentSet { + OptionalSomeContentSet() { + exists(EnumDecl optional, EnumElementDecl some | + some.getDeclaringDecl() = optional and + some.getName() = "some" and + optional.getName() = "Optional" and + optional.getModule().getName() = "Swift" + | + this.isSingleton(any(Content::EnumContent ec | ec.getParam() = some.getParam(0))) + ) + } +} + private newtype TDataFlowType = TODO_DataFlowType() class DataFlowType extends TDataFlowType { diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll index 9257c8ccb05..6d3db9c04fa 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll @@ -37,6 +37,11 @@ class Node extends TNode { */ Expr asExpr() { none() } + /** + * Gets this node's underlying pattern, if any. + */ + Pattern asPattern() { none() } + /** * Gets this data flow node's corresponding control flow node. */ @@ -66,6 +71,20 @@ class ExprNode extends Node, TExprNode { override ControlFlowNode getCfgNode() { result = n } } +/** + * A pattern, viewed as a node in a data flow graph. + */ +class PatternNode extends Node, TPatternNode { + CfgNode n; + Pattern pattern; + + PatternNode() { this = TPatternNode(n, pattern) } + + override Pattern asPattern() { result = pattern } + + override ControlFlowNode getCfgNode() { result = n } +} + /** * The value of a parameter at function entry, viewed as a node in a data * flow graph. @@ -171,6 +190,20 @@ module Content { override string toString() { result = "Tuple element at index " + index.toString() } } + + /** A parameter of an enum element. */ + class EnumContent extends Content, TEnumContent { + private ParamDecl p; + + EnumContent() { this = TEnumContent(p) } + + /** Gets the declaration of the enum parameter. */ + ParamDecl getParam() { result = p } + + override string toString() { + exists(EnumElementDecl d, int pos | d.getParam(pos) = p | result = d.toString() + ":" + pos) + } + } } /** diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll b/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll index 478328d90bf..6665e0e7480 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll @@ -10,6 +10,7 @@ private import FlowSummaryImplSpecific private import DataFlowImplSpecific::Private private import DataFlowImplSpecific::Public private import DataFlowImplCommon +private import codeql.util.Unit /** Provides classes and predicates for defining flow summaries. */ module Public { @@ -109,6 +110,7 @@ module Public { } /** Gets the stack obtained by dropping the first `i` elements, if any. */ + pragma[assume_small_delta] SummaryComponentStack drop(int i) { i = 0 and result = this or diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/tainttracking1/TaintTracking.qll b/swift/ql/lib/codeql/swift/dataflow/internal/tainttracking1/TaintTracking.qll index 7f96fe5e6fb..872ac8d4cb8 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/tainttracking1/TaintTracking.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/tainttracking1/TaintTracking.qll @@ -33,9 +33,9 @@ private module AddTaintDefaults<DataFlowInternal::FullStateConfigSig Config> imp } /** - * Constructs a standard taint tracking computation. + * Constructs a global taint tracking computation. */ -module Make<DataFlow::ConfigSig Config> implements DataFlow::DataFlowSig { +module Global<DataFlow::ConfigSig Config> implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import DataFlowInternal::DefaultState<Config> import Config @@ -48,10 +48,15 @@ module Make<DataFlow::ConfigSig Config> implements DataFlow::DataFlowSig { import DataFlowInternal::Impl<C> } +/** DEPRECATED: Use `Global` instead. */ +deprecated module Make<DataFlow::ConfigSig Config> implements DataFlow::GlobalFlowSig { + import Global<Config> +} + /** - * Constructs a taint tracking computation using flow state. + * Constructs a global taint tracking computation using flow state. */ -module MakeWithState<DataFlow::StateConfigSig Config> implements DataFlow::DataFlowSig { +module GlobalWithState<DataFlow::StateConfigSig Config> implements DataFlow::GlobalFlowSig { private module Config0 implements DataFlowInternal::FullStateConfigSig { import Config } @@ -62,3 +67,8 @@ module MakeWithState<DataFlow::StateConfigSig Config> implements DataFlow::DataF import DataFlowInternal::Impl<C> } + +/** DEPRECATED: Use `GlobalWithState` instead. */ +deprecated module MakeWithState<DataFlow::StateConfigSig Config> implements DataFlow::GlobalFlowSig { + import GlobalWithState<Config> +} diff --git a/swift/ql/lib/codeql/swift/elements/decl/ConstructorDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/ConstructorDecl.qll index ea70657abb3..8cb6843744c 100644 --- a/swift/ql/lib/codeql/swift/elements/decl/ConstructorDecl.qll +++ b/swift/ql/lib/codeql/swift/elements/decl/ConstructorDecl.qll @@ -1,9 +1,17 @@ private import codeql.swift.generated.decl.ConstructorDecl private import codeql.swift.elements.decl.MethodDecl +private import codeql.swift.elements.type.FunctionType +private import codeql.swift.elements.type.OptionalType /** * An initializer of a class, struct, enum or protocol. */ class ConstructorDecl extends Generated::ConstructorDecl, MethodDecl { override string toString() { result = this.getSelfParam().getType() + "." + super.toString() } + + /** Holds if this initializer returns an optional type. Failable initializers are written as `init?`. */ + predicate isFailable() { + this.getInterfaceType().(FunctionType).getResult().(FunctionType).getResult() instanceof + OptionalType + } } diff --git a/swift/ql/lib/codeql/swift/elements/decl/TypeDecl.qll b/swift/ql/lib/codeql/swift/elements/decl/TypeDecl.qll index 6c2b446a422..75189283435 100644 --- a/swift/ql/lib/codeql/swift/elements/decl/TypeDecl.qll +++ b/swift/ql/lib/codeql/swift/elements/decl/TypeDecl.qll @@ -28,8 +28,13 @@ class TypeDecl extends Generated::TypeDecl { cached string getFullName() { not this.getEnclosingDecl() instanceof TypeDecl and + not this.getEnclosingDecl() instanceof ExtensionDecl and result = this.getName() or result = this.getEnclosingDecl().(TypeDecl).getFullName() + "." + this.getName() + or + result = + this.getEnclosingDecl().(ExtensionDecl).getExtendedTypeDecl().getFullName() + "." + + this.getName() } } diff --git a/swift/ql/lib/codeql/swift/elements/expr/EnumElementExpr.qll b/swift/ql/lib/codeql/swift/elements/expr/EnumElementExpr.qll new file mode 100644 index 00000000000..4da1297820b --- /dev/null +++ b/swift/ql/lib/codeql/swift/elements/expr/EnumElementExpr.qll @@ -0,0 +1,60 @@ +/** + * `EnumElementExpr` is an expression that constructs a case of an enum. + */ + +private import codeql.swift.elements.expr.Expr +private import codeql.swift.elements.expr.Argument +private import codeql.swift.elements.expr.CallExpr +private import codeql.swift.elements.expr.DeclRefExpr +private import codeql.swift.elements.expr.MethodLookupExpr +private import codeql.swift.elements.decl.EnumElementDecl + +/** + * An expression that constructs a case of an enum. + */ +class EnumElementExpr extends Expr { + EnumElementDecl decl; + + EnumElementExpr() { + this.(NullaryEnumElementExpr).getElement() = decl or + this.(NonNullaryEnumElementExpr).getElement() = decl + } + + /** Gets the declaration of the enum element that this expression creates. */ + EnumElementDecl getElement() { result = decl } + + /** Gets the `i`th argument passed to this enum element expression (0-based). */ + Argument getArgument(int i) { result = this.(NonNullaryEnumElementExpr).getArgument(i) } + + /** Gets an argument passed to this enum element expression, if any. */ + final Argument getAnArgument() { result = this.getArgument(_) } + + /** Gets the number of arguments passed to this enum element expression. */ + final int getNumberOfArguments() { result = count(this.getArgument(_)) } +} + +/** + * An expression that refers to an enum element, either directly in the case of a nullary enum element, + * or referring to the enum element constructor in the case of a non-nullary enum element. + */ +private class EnumElementLookupExpr extends MethodLookupExpr { + EnumElementLookupExpr() { this.getMember() instanceof EnumElementDecl } +} + +/** An expression creating an enum with no arguments */ +private class NullaryEnumElementExpr extends EnumElementLookupExpr { + /** Gets the declaration of the enum element that this expression creates. */ + EnumElementDecl getElement() { this.getMember() = result } + + NullaryEnumElementExpr() { not exists(CallExpr ce | ce.getFunction() = this) } +} + +/** An expression creating an enum with arguments */ +private class NonNullaryEnumElementExpr extends CallExpr { + EnumElementLookupExpr eele; + + /** Gets the declaration of the enum element that this expression creates. */ + EnumElementDecl getElement() { eele.getMember() = result } + + NonNullaryEnumElementExpr() { this.getFunction() = eele } +} diff --git a/swift/ql/lib/codeql/swift/elements/pattern/BindingPattern.qll b/swift/ql/lib/codeql/swift/elements/pattern/BindingPattern.qll index b8422f49dfb..e6c15b51cd8 100644 --- a/swift/ql/lib/codeql/swift/elements/pattern/BindingPattern.qll +++ b/swift/ql/lib/codeql/swift/elements/pattern/BindingPattern.qll @@ -1,5 +1,7 @@ private import codeql.swift.generated.pattern.BindingPattern class BindingPattern extends Generated::BindingPattern { + final override Pattern getResolveStep() { result = getImmediateSubPattern() } + override string toString() { result = "let ..." } } diff --git a/swift/ql/lib/codeql/swift/elements/pattern/EnumElementPattern.qll b/swift/ql/lib/codeql/swift/elements/pattern/EnumElementPattern.qll index b7d97a03a53..7321341abf2 100644 --- a/swift/ql/lib/codeql/swift/elements/pattern/EnumElementPattern.qll +++ b/swift/ql/lib/codeql/swift/elements/pattern/EnumElementPattern.qll @@ -1,6 +1,19 @@ private import codeql.swift.generated.pattern.EnumElementPattern +private import codeql.swift.elements.pattern.TuplePattern class EnumElementPattern extends Generated::EnumElementPattern { + /** + * Gets the `i`th element (0-based) of this enum element's tuple + * sub-pattern, if any, or the sub-pattern itself if it is not a tuple pattern. + */ + Pattern getSubPattern(int i) { + result = this.getSubPattern().(TuplePattern).getElement(i) + or + not this.getSubPattern() instanceof TuplePattern and + result = this.getSubPattern() and + i = 0 + } + override string toString() { if this.hasSubPattern() then result = "." + this.getElement().toString() + "(...)" diff --git a/swift/ql/lib/codeql/swift/elements/pattern/NamedPattern.qll b/swift/ql/lib/codeql/swift/elements/pattern/NamedPattern.qll index 29e77edc5b5..a9964f4370b 100644 --- a/swift/ql/lib/codeql/swift/elements/pattern/NamedPattern.qll +++ b/swift/ql/lib/codeql/swift/elements/pattern/NamedPattern.qll @@ -1,5 +1,27 @@ private import codeql.swift.generated.pattern.NamedPattern +private import codeql.swift.elements.decl.VarDecl +/** + * A pattern that corresponds to a fresh variable binding. + * + * For example, `x` as in `if case let .some(x) = ...` is a `NamedPattern`, + * whereas `y` as in `if case .some(y) = ...` is instead an `ExprPattern`. + */ class NamedPattern extends Generated::NamedPattern { + /** + * Holds if this named pattern has a corresponding `VarDecl`. + * This will be the case as long as the variable is subsequently used. + */ + predicate hasVarDecl() { exists(this.getVarDecl()) } + + /** + * Gets the `VarDecl` bound by this named pattern, if any. + * This will be the case as long as the variable is subsequently used. + */ + VarDecl getVarDecl() { + this.getImmediateEnclosingPattern*() = result.getParentPattern().getFullyUnresolved() and + result.getName() = this.getName() + } + override string toString() { result = this.getName() } } diff --git a/swift/ql/lib/codeql/swift/elements/pattern/Pattern.qll b/swift/ql/lib/codeql/swift/elements/pattern/Pattern.qll index 7388d7836e7..74acce50ee9 100644 --- a/swift/ql/lib/codeql/swift/elements/pattern/Pattern.qll +++ b/swift/ql/lib/codeql/swift/elements/pattern/Pattern.qll @@ -1,4 +1,110 @@ -// generated by codegen/codegen.py, remove this comment if you wish to edit this file private import codeql.swift.generated.pattern.Pattern +private import codeql.swift.elements.pattern.EnumElementPattern +private import codeql.swift.elements.pattern.IsPattern +private import codeql.swift.elements.pattern.OptionalSomePattern +private import codeql.swift.elements.pattern.TypedPattern +private import codeql.swift.elements.pattern.TuplePattern +private import codeql.swift.elements.expr.Expr +private import codeql.swift.elements.expr.TupleExpr +private import codeql.swift.elements.expr.EnumElementExpr +private import codeql.swift.elements.expr.LookupExpr +private import codeql.swift.elements.expr.MethodLookupExpr +private import codeql.swift.elements.expr.DeclRefExpr +private import codeql.swift.elements.stmt.ConditionElement +private import codeql.swift.elements.stmt.SwitchStmt +private import codeql.swift.elements.stmt.CaseStmt +private import codeql.swift.elements.decl.VarDecl +private import codeql.swift.elements.decl.PatternBindingDecl +private import codeql.swift.elements.decl.EnumElementDecl +private import codeql.swift.generated.ParentChild -class Pattern extends Generated::Pattern { } +/** + * A syntactic construct that can be matched against an expression, + * occurring in switch cases, conditions, and variable bindings. + */ +class Pattern extends Generated::Pattern { + /** + * Gets the expression that this top-level pattern is matched against, if any. + * + * For example, in `switch e { case p: ... }`, the pattern `p` + * is immediately matched against the expression `e`. + */ + Expr getImmediateMatchingExpr() { + exists(ConditionElement c | + c.getPattern() = this and + result = c.getInitializer() + ) + or + exists(SwitchStmt s | + s.getExpr() = result and + s.getACase().getALabel().getPattern() = this + ) + or + exists(PatternBindingDecl v, int i | + v.getPattern(i) = pragma[only_bind_out](this) and + result = v.getInit(i) + ) + } + + /** + * Gets the expression that this pattern is matched against, if any. + * The expression and the pattern need not be top-level children of + * a pattern-matching construct, but they must match each other syntactically. + * + * For example, in `switch .some(e) { case let .some(p): ... }`, the pattern `p` + * is matched against the expression `e`. + */ + Expr getMatchingExpr() { + result = this.getImmediateMatchingExpr() + or + exists(Pattern p | p.getMatchingExpr() = result | + this = p.(IsPattern).getSubPattern() + or + this = p.(OptionalSomePattern).getSubPattern() + or + this = p.(TypedPattern).getSubPattern() + ) + or + exists(TuplePattern p, TupleExpr e, int i | + p.getMatchingExpr() = e and + this = p.getElement(i) and + result = e.getElement(i) + ) + or + exists(EnumElementPattern p, EnumElementExpr e, int i | + p.getMatchingExpr() = e and + this = p.getSubPattern(i) and + result = e.getArgument(i).getExpr() and + p.getElement() = e.getElement() + ) + } + + /** Holds if this pattern is matched against an expression. */ + final predicate hasMatchingExpr() { exists(this.getMatchingExpr()) } + + /** + * Gets the parent pattern of this pattern, if any. + */ + final Pattern getEnclosingPattern() { + result = this.getFullyUnresolved().(Pattern).getImmediateEnclosingPattern() + } + + /** + * Gets the parent pattern of this pattern, if any. + */ + Pattern getImmediateEnclosingPattern() { + this = result.(EnumElementPattern).getImmediateSubPattern() + or + this = result.(OptionalSomePattern).getImmediateSubPattern() + or + this = result.(TuplePattern).getImmediateElement(_) + or + this = result.(BindingPattern).getImmediateSubPattern() + or + this = result.(IsPattern).getImmediateSubPattern() + or + this = result.(ParenPattern).getImmediateSubPattern() + or + this = result.(TypedPattern).getImmediateSubPattern() + } +} diff --git a/swift/ql/lib/codeql/swift/elements/type/TypeAliasType.qll b/swift/ql/lib/codeql/swift/elements/type/TypeAliasType.qll index e7763b45e70..b7b3045d9e0 100644 --- a/swift/ql/lib/codeql/swift/elements/type/TypeAliasType.qll +++ b/swift/ql/lib/codeql/swift/elements/type/TypeAliasType.qll @@ -10,7 +10,7 @@ class TypeAliasType extends Generated::TypeAliasType { * typealias MyInt = Int * ``` */ - Type getAliasedType() { none() } // TODO: not yet implemented. + Type getAliasedType() { result = this.getDecl().getAliasedType() } - override Type getUnderlyingType() { result = this } // TODO: not yet implemented. + override Type getUnderlyingType() { result = this.getAliasedType().getUnderlyingType() } } diff --git a/swift/ql/lib/codeql/swift/generated/Raw.qll b/swift/ql/lib/codeql/swift/generated/Raw.qll index 3dad5a302fc..beb035d81c5 100644 --- a/swift/ql/lib/codeql/swift/generated/Raw.qll +++ b/swift/ql/lib/codeql/swift/generated/Raw.qll @@ -660,6 +660,16 @@ module Raw { class TypeAliasDecl extends @type_alias_decl, GenericTypeDecl { override string toString() { result = "TypeAliasDecl" } + + /** + * Gets the aliased type on the right-hand side of this type alias declaration. + * + * For example the aliased type of `MyInt` in the following code is `Int`: + * ``` + * typealias MyInt = Int + * ``` + */ + Type getAliasedType() { type_alias_decls(this, result) } } class ClassDecl extends @class_decl, NominalTypeDecl { diff --git a/swift/ql/lib/codeql/swift/generated/decl/TypeAliasDecl.qll b/swift/ql/lib/codeql/swift/generated/decl/TypeAliasDecl.qll index 1e9dbd7bc46..d7bd1e8538d 100644 --- a/swift/ql/lib/codeql/swift/generated/decl/TypeAliasDecl.qll +++ b/swift/ql/lib/codeql/swift/generated/decl/TypeAliasDecl.qll @@ -2,9 +2,39 @@ private import codeql.swift.generated.Synth private import codeql.swift.generated.Raw import codeql.swift.elements.decl.GenericTypeDecl +import codeql.swift.elements.type.Type module Generated { + /** + * A declaration of a type alias to another type. For example: + * ``` + * typealias MyInt = Int + * ``` + */ class TypeAliasDecl extends Synth::TTypeAliasDecl, GenericTypeDecl { override string getAPrimaryQlClass() { result = "TypeAliasDecl" } + + /** + * Gets the aliased type on the right-hand side of this type alias declaration. + * + * This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the + * behavior of both the `Immediate` and non-`Immediate` versions. + */ + Type getImmediateAliasedType() { + result = + Synth::convertTypeFromRaw(Synth::convertTypeAliasDeclToRaw(this) + .(Raw::TypeAliasDecl) + .getAliasedType()) + } + + /** + * Gets the aliased type on the right-hand side of this type alias declaration. + * + * For example the aliased type of `MyInt` in the following code is `Int`: + * ``` + * typealias MyInt = Int + * ``` + */ + final Type getAliasedType() { result = getImmediateAliasedType().resolve() } } } diff --git a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll index 2bcb006cbb6..e8529ff5d06 100644 --- a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll @@ -48,10 +48,10 @@ private class CoreDataStore extends CleartextStorageDatabaseSink { // example in `coreDataObj.data = sensitive` the post-update node corresponding // with `coreDataObj.data` is a sink. // (ideally this would be only members with the `@NSManaged` attribute) - exists(ClassOrStructDecl cd, Expr e | - cd.getABaseTypeDecl*().getName() = "NSManagedObject" and + exists(NominalType t, Expr e | + t.getABaseType*().getName() = "NSManagedObject" and this.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = e and - e.getFullyConverted().getType() = cd.getType() and + e.getFullyConverted().getType() = t and not e.(DeclRefExpr).getDecl() instanceof SelfParamDecl ) } @@ -66,10 +66,10 @@ private class RealmStore extends CleartextStorageDatabaseSink instanceof DataFlo // any write into a class derived from `RealmSwiftObject` is a sink. For // example in `realmObj.data = sensitive` the post-update node corresponding // with `realmObj.data` is a sink. - exists(ClassOrStructDecl cd, Expr e | - cd.getABaseTypeDecl*().getName() = "RealmSwiftObject" and + exists(NominalType t, Expr e | + t.getABaseType*().getName() = "RealmSwiftObject" and this.getPreUpdateNode().asExpr() = e and - e.getFullyConverted().getType() = cd.getType() and + e.getFullyConverted().getType() = t and not e.(DeclRefExpr).getDecl() instanceof SelfParamDecl ) } @@ -122,15 +122,22 @@ private class CleartextStorageDatabaseEncryptionSanitizer extends CleartextStora /** * An additional taint step for cleartext database storage vulnerabilities. - * Needed until we have proper content flow through arrays. */ private class CleartextStorageDatabaseArrayAdditionalTaintStep extends CleartextStorageDatabaseAdditionalTaintStep { override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + // needed until we have proper content flow through arrays. exists(ArrayExpr arr | nodeFrom.asExpr() = arr.getAnElement() and nodeTo.asExpr() = arr ) + or + // if an object is sensitive, its fields are always sensitive + // (this is needed because the sensitive data sources are in a sense + // approximate; for example we might identify `passwordBox` as a source, + // whereas it is more accurate to say that `passwordBox.textField` is the + // true source). + nodeTo.asExpr().(MemberRefExpr).getBase() = nodeFrom.asExpr() } } diff --git a/swift/ql/lib/codeql/swift/security/StringLengthConflationExtensions.qll b/swift/ql/lib/codeql/swift/security/StringLengthConflationExtensions.qll new file mode 100644 index 00000000000..c4ecebf8d0d --- /dev/null +++ b/swift/ql/lib/codeql/swift/security/StringLengthConflationExtensions.qll @@ -0,0 +1,189 @@ +/** + * Provides classes and predicates for reasoning about string length + * conflation vulnerabilities. + */ + +import swift +import codeql.swift.dataflow.DataFlow +import codeql.swift.dataflow.ExternalFlow + +/** + * A type of Swift string encoding. This class is used as a flow state for + * the string length conflation taint tracking configuration. + */ +class StringType extends string { + string singular; + string equivClass; + string csvLabel; + + StringType() { + this = "String" and + singular = "a String" and + equivClass = "String" and + csvLabel = "string-length" + or + this = "NSString" and + singular = "an NSString" and + equivClass = "NSString" and + csvLabel = "nsstring-length" + or + this = "String.utf8" and + singular = "a String.utf8" and + equivClass = "String.utf8" and + csvLabel = "string-utf8-length" + or + this = "String.utf16" and + singular = "a String.utf16" and + equivClass = "NSString" and + csvLabel = "string-utf16-length" + or + this = "String.unicodeScalars" and + singular = "a String.unicodeScalars" and + equivClass = "String.unicodeScalars" and + csvLabel = "string-unicodescalars-length" + } + + /** + * Gets the equivalence class for this string type. If these are equal, + * they should be treated as equivalent. + */ + string getEquivClass() { result = equivClass } + + /** + * Gets text for the singular form of this string type. + */ + string getSingular() { result = singular } + + /** + * Gets the label for this string type in CSV models. + */ + string getCsvLabel() { result = csvLabel } +} + +/** + * A dataflow source for string length conflation vulnerabilities. That is, + * a `DataFlow::Node` where a string length is generated. + */ +abstract class StringLengthConflationSource extends DataFlow::Node { + /** + * Gets the `StringType` for this source. + */ + abstract StringType getStringType(); +} + +/** + * A dataflow sink for string length conflation vulnerabilities. That is, + * a `DataFlow::Node` where a string length is used. + */ +abstract class StringLengthConflationSink extends DataFlow::Node { + /** + * Gets the correct `StringType` for this sink. + */ + abstract StringType getCorrectStringType(); +} + +/** + * A sanitizer for string length conflation vulnerabilities. + */ +abstract class StringLengthConflationSanitizer extends DataFlow::Node { } + +/** + * A unit class for adding additional taint steps. + */ +class StringLengthConflationAdditionalTaintStep extends Unit { + /** + * Holds if the step from `node1` to `node2` should be considered a taint + * step for paths related to string length conflation vulnerabilities. + */ + abstract predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo); +} + +/** + * A source defined in a CSV model. + */ +private class DefaultStringLengthConflationSource extends StringLengthConflationSource { + StringType stringType; + + DefaultStringLengthConflationSource() { sourceNode(this, stringType.getCsvLabel()) } + + override StringType getStringType() { result = stringType } +} + +private class StringLengthConflationSources extends SourceModelCsv { + override predicate row(string row) { + row = + [ + ";String;true;count;;;;string-length", ";NSString;true;length;;;;nsstring-length", + ";NSMutableString;true;length;;;;nsstring-length", + ] + } +} + +/** + * An extra source that don't currently fit into the CSV scheme. + */ +private class ExtraStringLengthConflationSource extends StringLengthConflationSource { + StringType stringType; + + ExtraStringLengthConflationSource() { + exists(MemberRefExpr memberRef, string typeName | + ( + // result of a call to `String.utf8.count` + typeName = "String.UTF8View" and + stringType = "String.utf8" + or + // result of a call to `String.utf16.count` + typeName = "String.UTF16View" and + stringType = "String.utf16" + or + // result of a call to `String.unicodeScalars.count` + typeName = "String.UnicodeScalarView" and + stringType = "String.unicodeScalars" + ) and + memberRef.getBase().getType().(NominalType).getName() = typeName and + memberRef.getMember().(VarDecl).getName() = "count" and + this.asExpr() = memberRef + ) + } + + override StringType getStringType() { result = stringType } +} + +/** + * A sink defined in a CSV model. + */ +private class DefaultStringLengthConflationSink extends StringLengthConflationSink { + StringType stringType; + + DefaultStringLengthConflationSink() { sinkNode(this, stringType.getCsvLabel()) } + + override StringType getCorrectStringType() { result = stringType } +} + +private class StringLengthConflationSinks extends SinkModelCsv { + override predicate row(string row) { + row = + [ + ";Sequence;true;dropFirst(_:);;;Argument[0];string-length", + ";Sequence;true;dropLast(_:);;;Argument[0];string-length", + ";Sequence;true;prefix(_:);;;Argument[0];string-length", + ";Sequence;true;suffix(_:);;;Argument[0];string-length", + ";Collection;true;formIndex(_:offsetBy:);;;Argument[0..1];string-length", + ";Collection;true;formIndex(_:offsetBy:limitBy:);;;Argument[0..1];string-length", + ";Collection;true;removeFirst(_:);;;Argument[0];string-length", + ";RangeReplaceableCollection;true;removeLast(_:);;;Argument[0];string-length", + ";String;true;index(_:offsetBy:);;;Argument[0..1];string-length", + ";String;true;index(_:offsetBy:limitBy:);;;Argument[0..1];string-length", + ";String.Index;true;init(encodedOffset:);;;Argument[0];string-length", + ";NSRange;true;init(location:length:);;;Argument[0..1];nsstring-length", + ";NSString;true;character(at:);;;Argument[0];nsstring-length", + ";NSString;true;substring(from:);;;Argument[0];nsstring-length", + ";NSString;true;substring(to:);;;Argument[0];nsstring-length", + ";NSMutableString;true;character(at:);;;Argument[0];nsstring-length", + ";NSMutableString;true;substring(from:);;;Argument[0];nsstring-length", + ";NSMutableString;true;substring(to:);;;Argument[0];nsstring-length", + ";NSMutableString;true;insert(_:at:);;;Argument[1];nsstring-length", + ";;false;NSMakeRange(_:_:);;;Argument[0..1];nsstring-length", + ] + } +} diff --git a/swift/ql/lib/codeql/swift/security/StringLengthConflationQuery.qll b/swift/ql/lib/codeql/swift/security/StringLengthConflationQuery.qll new file mode 100644 index 00000000000..79de491af2b --- /dev/null +++ b/swift/ql/lib/codeql/swift/security/StringLengthConflationQuery.qll @@ -0,0 +1,39 @@ +/** + * Provides a taint-tracking configuration for reasoning about string length + * conflation vulnerabilities. + */ + +import swift +import codeql.swift.dataflow.DataFlow +import codeql.swift.dataflow.TaintTracking +import codeql.swift.security.StringLengthConflationExtensions + +/** + * A configuration for tracking string lengths originating from source that is + * a `String` or an `NSString` object, to a sink of a different kind that + * expects an incompatible measure of length. + */ +class StringLengthConflationConfiguration extends TaintTracking::Configuration { + StringLengthConflationConfiguration() { this = "StringLengthConflationConfiguration" } + + override predicate isSource(DataFlow::Node node, string flowstate) { + flowstate = node.(StringLengthConflationSource).getStringType() + } + + override predicate isSink(DataFlow::Node node, string flowstate) { + // Permit any *incorrect* flowstate, as those are the results the query + // should report. + exists(string correctFlowState | + correctFlowState = node.(StringLengthConflationSink).getCorrectStringType() and + flowstate.(StringType).getEquivClass() != correctFlowState.(StringType).getEquivClass() + ) + } + + override predicate isSanitizer(DataFlow::Node sanitizer) { + sanitizer instanceof StringLengthConflationSanitizer + } + + override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + any(StringLengthConflationAdditionalTaintStep s).step(nodeFrom, nodeTo) + } +} diff --git a/swift/ql/lib/qlpack.yml b/swift/ql/lib/qlpack.yml index 66c3bc0094d..3d3f00eb029 100644 --- a/swift/ql/lib/qlpack.yml +++ b/swift/ql/lib/qlpack.yml @@ -8,3 +8,4 @@ library: true dependencies: codeql/ssa: ${workspace} codeql/tutorial: ${workspace} + codeql/util: ${workspace} diff --git a/swift/ql/lib/swift.dbscheme b/swift/ql/lib/swift.dbscheme index c2f01f2beb6..e646f9e0308 100644 --- a/swift/ql/lib/swift.dbscheme +++ b/swift/ql/lib/swift.dbscheme @@ -670,7 +670,8 @@ param_decl_property_wrapper_local_wrapped_vars( //dir=decl ); type_alias_decls( //dir=decl - unique int id: @type_alias_decl + unique int id: @type_alias_decl, + int aliased_type: @type_or_none ref ); class_decls( //dir=decl diff --git a/swift/ql/lib/swift.qll b/swift/ql/lib/swift.qll index 897bbf9b2f7..819f14e16eb 100644 --- a/swift/ql/lib/swift.qll +++ b/swift/ql/lib/swift.qll @@ -8,6 +8,7 @@ import codeql.swift.elements.expr.InitializerLookupExpr import codeql.swift.elements.expr.MethodCallExpr import codeql.swift.elements.expr.InitializerCallExpr import codeql.swift.elements.expr.SelfRefExpr +import codeql.swift.elements.expr.EnumElementExpr import codeql.swift.elements.decl.MethodDecl import codeql.swift.elements.decl.ClassOrStructDecl import codeql.swift.elements.type.NumericType diff --git a/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/old.dbscheme b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/old.dbscheme new file mode 100644 index 00000000000..c2f01f2beb6 --- /dev/null +++ b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/old.dbscheme @@ -0,0 +1,2601 @@ +// generated by codegen/codegen.py + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @callable +| @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@callable = + @abstract_closure_expr +| @abstract_function_decl +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @case_label_item +| @condition_element +| @decl +| @expr +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @abstract_function_decl +| @extension_decl +| @generic_type_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_function_decl +| @abstract_storage_decl +| @enum_element_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_function_decl = + @constructor_decl +| @destructor_decl +| @func_decl +; + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessor_decls( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor_decl: @accessor_decl_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_base_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int base_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +constructor_decls( //dir=decl + unique int id: @constructor_decl +); + +destructor_decls( //dir=decl + unique int id: @destructor_decl +); + +@func_decl = + @accessor_decl +| @concrete_func_decl +; + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id, index] +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessor_decls( //dir=decl + unique int id: @accessor_decl +); + +#keyset[id] +accessor_decl_is_getter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_setter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_will_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_did_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_read( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_modify( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_address( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_mutable_address( //dir=decl + int id: @accessor_decl ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_func_decls( //dir=decl + unique int id: @concrete_func_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @abstract_closure_expr +| @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @collection_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initializer_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_constructor_decl_ref_expr +| @overloaded_decl_ref_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_constructor_expr +| @sequence_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@abstract_closure_expr = + @auto_closure_expr +| @closure_expr +; + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@collection_expr = + @array_expr +| @dictionary_expr +; + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id] +key_path_expr_parsed_paths( //dir=expr + int id: @key_path_expr ref, + int parsed_path: @expr_or_none ref +); + +lazy_initializer_exprs( //dir=expr + unique int id: @lazy_initializer_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @abstract_function_decl_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_constructor_decl_ref_exprs( //dir=expr + unique int id: @other_constructor_decl_ref_expr, + int constructor_decl: @constructor_decl_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_constructor_exprs( //dir=expr + unique int id: @rebind_self_in_constructor_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +closure_exprs( //dir=expr + unique int id: @closure_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_count_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int literal_capacity_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @constructor_ref_call_expr +| @dot_syntax_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +constructor_ref_call_exprs( //dir=expr + unique int id: @constructor_ref_call_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + string name: string ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int sequence: @expr_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @opaque_type_archetype_type +| @opened_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@abstract_function_decl_or_none = + @abstract_function_decl +| @unspecified_element +; + +@accessor_decl_or_none = + @accessor_decl +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@constructor_decl_or_none = + @constructor_decl +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/swift.dbscheme b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/swift.dbscheme new file mode 100644 index 00000000000..e646f9e0308 --- /dev/null +++ b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/swift.dbscheme @@ -0,0 +1,2602 @@ +// generated by codegen/codegen.py + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @callable +| @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@callable = + @abstract_closure_expr +| @abstract_function_decl +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @case_label_item +| @condition_element +| @decl +| @expr +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @abstract_function_decl +| @extension_decl +| @generic_type_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_function_decl +| @abstract_storage_decl +| @enum_element_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_function_decl = + @constructor_decl +| @destructor_decl +| @func_decl +; + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessor_decls( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor_decl: @accessor_decl_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_base_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int base_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +constructor_decls( //dir=decl + unique int id: @constructor_decl +); + +destructor_decls( //dir=decl + unique int id: @destructor_decl +); + +@func_decl = + @accessor_decl +| @concrete_func_decl +; + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id, index] +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessor_decls( //dir=decl + unique int id: @accessor_decl +); + +#keyset[id] +accessor_decl_is_getter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_setter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_will_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_did_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_read( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_modify( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_address( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_mutable_address( //dir=decl + int id: @accessor_decl ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_func_decls( //dir=decl + unique int id: @concrete_func_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl, + int aliased_type: @type_or_none ref +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @abstract_closure_expr +| @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @collection_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initializer_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_constructor_decl_ref_expr +| @overloaded_decl_ref_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_constructor_expr +| @sequence_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@abstract_closure_expr = + @auto_closure_expr +| @closure_expr +; + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@collection_expr = + @array_expr +| @dictionary_expr +; + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id] +key_path_expr_parsed_paths( //dir=expr + int id: @key_path_expr ref, + int parsed_path: @expr_or_none ref +); + +lazy_initializer_exprs( //dir=expr + unique int id: @lazy_initializer_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @abstract_function_decl_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_constructor_decl_ref_exprs( //dir=expr + unique int id: @other_constructor_decl_ref_expr, + int constructor_decl: @constructor_decl_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_constructor_exprs( //dir=expr + unique int id: @rebind_self_in_constructor_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +closure_exprs( //dir=expr + unique int id: @closure_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_count_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int literal_capacity_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @constructor_ref_call_expr +| @dot_syntax_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +constructor_ref_call_exprs( //dir=expr + unique int id: @constructor_ref_call_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + string name: string ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int sequence: @expr_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @opaque_type_archetype_type +| @opened_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@abstract_function_decl_or_none = + @abstract_function_decl +| @unspecified_element +; + +@accessor_decl_or_none = + @accessor_decl +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@constructor_decl_or_none = + @constructor_decl +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/type_alias_decls.ql b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/type_alias_decls.ql new file mode 100644 index 00000000000..4b5ecd00925 --- /dev/null +++ b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/type_alias_decls.ql @@ -0,0 +1,14 @@ +class TypeAliasDecl extends @type_alias_decl { + string toString() { result = "TypeAliasDecl" } +} + +class Type extends @type_or_none { + string toString() { result = "Type" } +} + +// use the canonical type as an approximation of the aliased type +from TypeAliasDecl td, Type t, Type canonical +where + type_alias_types(t, td) and // td is the declaration of t + types(t, _, canonical) // canonical is the canonical type of t +select td, canonical diff --git a/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/upgrade.properties b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/upgrade.properties new file mode 100644 index 00000000000..301f7bb8899 --- /dev/null +++ b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/upgrade.properties @@ -0,0 +1,3 @@ +description: Add TypeAliasDecl.getAliasedType() +compatibility: backwards +type_alias_decls.rel: run type_alias_decls.qlo diff --git a/swift/ql/src/queries/Security/CWE-1204/StaticInitializationVector.ql b/swift/ql/src/queries/Security/CWE-1204/StaticInitializationVector.ql index 0324be01da9..e624c9efd2e 100644 --- a/swift/ql/src/queries/Security/CWE-1204/StaticInitializationVector.ql +++ b/swift/ql/src/queries/Security/CWE-1204/StaticInitializationVector.ql @@ -14,7 +14,7 @@ import swift import codeql.swift.dataflow.DataFlow import codeql.swift.dataflow.TaintTracking -import DataFlow::PathGraph +import StaticInitializationVectorFlow::PathGraph /** * A static IV is created through either a byte array or string literals. @@ -56,23 +56,21 @@ class EncryptionInitializationSink extends Expr { * A dataflow configuration from the source of a static IV to expressions that use * it to initialize a cipher. */ -class StaticInitializationVectorConfig extends TaintTracking::Configuration { - StaticInitializationVectorConfig() { this = "StaticInitializationVectorConfig" } - - override predicate isSource(DataFlow::Node node) { +module StaticInitializationVectorConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node.asExpr() instanceof StaticInitializationVectorSource } - override predicate isSink(DataFlow::Node node) { - node.asExpr() instanceof EncryptionInitializationSink - } + predicate isSink(DataFlow::Node node) { node.asExpr() instanceof EncryptionInitializationSink } } +module StaticInitializationVectorFlow = TaintTracking::Global<StaticInitializationVectorConfig>; + // The query itself from - StaticInitializationVectorConfig config, DataFlow::PathNode sourceNode, - DataFlow::PathNode sinkNode -where config.hasFlowPath(sourceNode, sinkNode) + StaticInitializationVectorFlow::PathNode sourceNode, + StaticInitializationVectorFlow::PathNode sinkNode +where StaticInitializationVectorFlow::flowPath(sourceNode, sinkNode) select sinkNode.getNode(), sourceNode, sinkNode, "The static value '" + sourceNode.getNode().toString() + "' is used as an initialization vector for encryption." diff --git a/swift/ql/src/queries/Security/CWE-135/StringLengthConflation.ql b/swift/ql/src/queries/Security/CWE-135/StringLengthConflation.ql index 70446bf61f2..ddc5f9201f5 100644 --- a/swift/ql/src/queries/Security/CWE-135/StringLengthConflation.ql +++ b/swift/ql/src/queries/Security/CWE-135/StringLengthConflation.ql @@ -12,183 +12,17 @@ import swift import codeql.swift.dataflow.DataFlow -import codeql.swift.dataflow.TaintTracking +import codeql.swift.security.StringLengthConflationQuery import DataFlow::PathGraph -/** - * A flow state for this query, which is a type of Swift string encoding. - */ -class StringLengthConflationFlowState extends string { - string equivClass; - string singular; - - StringLengthConflationFlowState() { - this = "String" and singular = "a String" and equivClass = "String" - or - this = "NSString" and singular = "an NSString" and equivClass = "NSString" - or - this = "String.utf8" and singular = "a String.utf8" and equivClass = "String.utf8" - or - this = "String.utf16" and singular = "a String.utf16" and equivClass = "NSString" - or - this = "String.unicodeScalars" and - singular = "a String.unicodeScalars" and - equivClass = "String.unicodeScalars" - } - - /** - * Gets the equivalence class for this flow state. If these are equal, - * they should be treated as equivalent. - */ - string getEquivClass() { result = equivClass } - - /** - * Gets text for the singular form of this flow state. - */ - string getSingular() { result = singular } -} - -/** - * A configuration for tracking string lengths originating from source that is - * a `String` or an `NSString` object, to a sink of a different kind that - * expects an incompatible measure of length. - */ -class StringLengthConflationConfiguration extends TaintTracking::Configuration { - StringLengthConflationConfiguration() { this = "StringLengthConflationConfiguration" } - - override predicate isSource(DataFlow::Node node, string flowstate) { - exists(MemberRefExpr memberRef, string className, string varName | - memberRef.getBase().getType().(NominalType).getABaseType*().getName() = className and - memberRef.getMember().(VarDecl).getName() = varName and - node.asExpr() = memberRef and - ( - // result of a call to `String.count` - className = "String" and - varName = "count" and - flowstate = "String" - or - // result of a call to `NSString.length` - className = ["NSString", "NSMutableString"] and - varName = "length" and - flowstate = "NSString" - or - // result of a call to `String.utf8.count` - className = "String.UTF8View" and - varName = "count" and - flowstate = "String.utf8" - or - // result of a call to `String.utf16.count` - className = "String.UTF16View" and - varName = "count" and - flowstate = "String.utf16" - or - // result of a call to `String.unicodeScalars.count` - className = "String.UnicodeScalarView" and - varName = "count" and - flowstate = "String.unicodeScalars" - ) - ) - } - - /** - * Holds if `node` is a sink and `flowstate` is the *correct* flow state for - * that sink. We actually want to report incorrect flow states. - */ - predicate isSinkImpl(DataFlow::Node node, string flowstate) { - exists(AbstractFunctionDecl funcDecl, CallExpr call, string funcName, int arg | - ( - // arguments to method calls... - exists(string className, ClassOrStructDecl c | - ( - // `NSRange.init` - className = "NSRange" and - funcName = "init(location:length:)" and - arg = [0, 1] - or - // `NSString.character` - className = ["NSString", "NSMutableString"] and - funcName = "character(at:)" and - arg = 0 - or - // `NSString.character` - className = ["NSString", "NSMutableString"] and - funcName = "substring(from:)" and - arg = 0 - or - // `NSString.character` - className = ["NSString", "NSMutableString"] and - funcName = "substring(to:)" and - arg = 0 - or - // `NSMutableString.insert` - className = "NSMutableString" and - funcName = "insert(_:at:)" and - arg = 1 - ) and - c.getName() = className and - c.getABaseTypeDecl*().(ClassOrStructDecl).getAMember() = funcDecl and - call.getStaticTarget() = funcDecl and - flowstate = "NSString" - ) - or - // arguments to function calls... - // `NSMakeRange` - funcName = "NSMakeRange(_:_:)" and - arg = [0, 1] and - call.getStaticTarget() = funcDecl and - flowstate = "NSString" - or - // arguments to method calls... - ( - // `String.dropFirst`, `String.dropLast`, `String.removeFirst`, `String.removeLast` - funcName = ["dropFirst(_:)", "dropLast(_:)", "removeFirst(_:)", "removeLast(_:)"] and - arg = 0 - or - // `String.prefix`, `String.suffix` - funcName = ["prefix(_:)", "suffix(_:)"] and - arg = 0 - or - // `String.Index.init` - funcName = "init(encodedOffset:)" and - arg = 0 - or - // `String.index` - funcName = ["index(_:offsetBy:)", "index(_:offsetBy:limitBy:)"] and - arg = [0, 1] - or - // `String.formIndex` - funcName = ["formIndex(_:offsetBy:)", "formIndex(_:offsetBy:limitBy:)"] and - arg = [0, 1] - ) and - call.getStaticTarget() = funcDecl and - flowstate = "String" - ) and - // match up `funcName`, `arg`, `node`. - funcDecl.getName() = funcName and - call.getArgument(arg).getExpr() = node.asExpr() - ) - } - - override predicate isSink(DataFlow::Node node, string flowstate) { - // Permit any *incorrect* flowstate, as those are the results the query - // should report. - exists(string correctFlowState | - isSinkImpl(node, correctFlowState) and - flowstate.(StringLengthConflationFlowState).getEquivClass() != - correctFlowState.(StringLengthConflationFlowState).getEquivClass() - ) - } -} - from StringLengthConflationConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink, - StringLengthConflationFlowState sourceFlowState, StringLengthConflationFlowState sinkFlowstate, - string message + StringType sourceType, StringType sinkType, string message where config.hasFlowPath(source, sink) and - config.isSource(source.getNode(), sourceFlowState) and - config.isSinkImpl(sink.getNode(), sinkFlowstate) and + config.isSource(source.getNode(), sourceType) and + sinkType = sink.getNode().(StringLengthConflationSink).getCorrectStringType() and message = - "This " + sourceFlowState + " length is used in " + sinkFlowstate.getSingular() + + "This " + sourceType + " length is used in " + sinkType.getSingular() + ", but it may not be equivalent." select sink.getNode(), source, sink, message diff --git a/swift/ql/src/queries/Security/CWE-259/ConstantPassword.ql b/swift/ql/src/queries/Security/CWE-259/ConstantPassword.ql index d7fd2e187de..fa3500ccf9b 100644 --- a/swift/ql/src/queries/Security/CWE-259/ConstantPassword.ql +++ b/swift/ql/src/queries/Security/CWE-259/ConstantPassword.ql @@ -14,7 +14,7 @@ import swift import codeql.swift.dataflow.DataFlow import codeql.swift.dataflow.TaintTracking import codeql.swift.dataflow.FlowSteps -import DataFlow::PathGraph +import ConstantPasswordFlow::PathGraph /** * A constant password is created through either a byte array or string literals. @@ -33,7 +33,7 @@ class ConstantPasswordSink extends Expr { ConstantPasswordSink() { // `password` arg in `init` is a sink exists(ClassOrStructDecl c, ConstructorDecl f, CallExpr call | - c.getFullName() = ["HKDF", "PBKDF1", "PBKDF2", "Scrypt"] and + c.getName() = ["HKDF", "PBKDF1", "PBKDF2", "Scrypt"] and c.getAMember() = f and call.getStaticTarget() = f and call.getArgumentWithLabel("password").getExpr() = this @@ -41,7 +41,7 @@ class ConstantPasswordSink extends Expr { or // RNCryptor (labelled arguments) exists(ClassOrStructDecl c, MethodDecl f, CallExpr call | - c.getFullName() = ["RNCryptor", "RNEncryptor", "RNDecryptor"] and + c.getName() = ["RNCryptor", "RNEncryptor", "RNDecryptor"] and c.getAMember() = f and call.getStaticTarget() = f and call.getArgumentWithLabel(["password", "withPassword", "forPassword"]).getExpr() = this @@ -60,18 +60,16 @@ class ConstantPasswordSink extends Expr { * A taint configuration from the source of constants passwords to expressions that use * them to initialize password-based encryption keys. */ -class ConstantPasswordConfig extends TaintTracking::Configuration { - ConstantPasswordConfig() { this = "ConstantPasswordConfig" } +module ConstantPasswordConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node.asExpr() instanceof ConstantPasswordSource } - override predicate isSource(DataFlow::Node node) { - node.asExpr() instanceof ConstantPasswordSource - } - - override predicate isSink(DataFlow::Node node) { node.asExpr() instanceof ConstantPasswordSink } + predicate isSink(DataFlow::Node node) { node.asExpr() instanceof ConstantPasswordSink } } +module ConstantPasswordFlow = TaintTracking::Global<ConstantPasswordConfig>; + // The query itself -from ConstantPasswordConfig config, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode -where config.hasFlowPath(sourceNode, sinkNode) +from ConstantPasswordFlow::PathNode sourceNode, ConstantPasswordFlow::PathNode sinkNode +where ConstantPasswordFlow::flowPath(sourceNode, sinkNode) select sinkNode.getNode(), sourceNode, sinkNode, "The value '" + sourceNode.getNode().toString() + "' is used as a constant password." diff --git a/swift/ql/src/queries/Security/CWE-311/CleartextStorageDatabase.ql b/swift/ql/src/queries/Security/CWE-311/CleartextStorageDatabase.ql index 4052a335663..f38d93d30d5 100644 --- a/swift/ql/src/queries/Security/CWE-311/CleartextStorageDatabase.ql +++ b/swift/ql/src/queries/Security/CWE-311/CleartextStorageDatabase.ql @@ -26,9 +26,13 @@ DataFlow::Node cleanupNode(DataFlow::Node n) { result = n } -from CleartextStorageConfig config, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode -where config.hasFlowPath(sourceNode, sinkNode) -select cleanupNode(sinkNode.getNode()), sourceNode, sinkNode, - "This operation stores '" + sinkNode.getNode().toString() + +from + CleartextStorageConfig config, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode, + DataFlow::Node cleanSink +where + config.hasFlowPath(sourceNode, sinkNode) and + cleanSink = cleanupNode(sinkNode.getNode()) +select cleanSink, sourceNode, sinkNode, + "This operation stores '" + cleanSink.toString() + "' in a database. It may contain unencrypted sensitive data from $@.", sourceNode, sourceNode.getNode().toString() diff --git a/swift/ql/src/queries/Security/CWE-312/CleartextStoragePreferences.ql b/swift/ql/src/queries/Security/CWE-312/CleartextStoragePreferences.ql index 051b7afb9aa..25944e293a0 100644 --- a/swift/ql/src/queries/Security/CWE-312/CleartextStoragePreferences.ql +++ b/swift/ql/src/queries/Security/CWE-312/CleartextStoragePreferences.ql @@ -25,10 +25,14 @@ DataFlow::Node cleanupNode(DataFlow::Node n) { result = n } -from CleartextStorageConfig config, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode -where config.hasFlowPath(sourceNode, sinkNode) -select cleanupNode(sinkNode.getNode()), sourceNode, sinkNode, - "This operation stores '" + sinkNode.getNode().toString() + "' in " + +from + CleartextStorageConfig config, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode, + DataFlow::Node cleanSink +where + config.hasFlowPath(sourceNode, sinkNode) and + cleanSink = cleanupNode(sinkNode.getNode()) +select cleanSink, sourceNode, sinkNode, + "This operation stores '" + cleanSink.toString() + "' in " + sinkNode.getNode().(CleartextStoragePreferencesSink).getStoreName() + ". It may contain unencrypted sensitive data from $@.", sourceNode, sourceNode.getNode().toString() diff --git a/swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.ql b/swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.ql index 4782d13dd14..d44e6a3187b 100644 --- a/swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.ql +++ b/swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.ql @@ -13,7 +13,7 @@ import swift import codeql.swift.dataflow.DataFlow import codeql.swift.dataflow.TaintTracking -import DataFlow::PathGraph +import HardcodedKeyFlow::PathGraph /** * An `Expr` that is used to initialize a key. @@ -62,17 +62,17 @@ class EncryptionKeySink extends Expr { * A taint configuration from the key source to expressions that use * it to initialize a cipher. */ -class HardcodedKeyConfig extends TaintTracking::Configuration { - HardcodedKeyConfig() { this = "HardcodedKeyConfig" } +module HardcodedKeyConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node.asExpr() instanceof KeySource } - override predicate isSource(DataFlow::Node node) { node.asExpr() instanceof KeySource } - - override predicate isSink(DataFlow::Node node) { node.asExpr() instanceof EncryptionKeySink } + predicate isSink(DataFlow::Node node) { node.asExpr() instanceof EncryptionKeySink } } +module HardcodedKeyFlow = TaintTracking::Global<HardcodedKeyConfig>; + // The query itself -from HardcodedKeyConfig config, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode -where config.hasFlowPath(sourceNode, sinkNode) +from HardcodedKeyFlow::PathNode sourceNode, HardcodedKeyFlow::PathNode sinkNode +where HardcodedKeyFlow::flowPath(sourceNode, sinkNode) select sinkNode.getNode(), sourceNode, sinkNode, "The key '" + sinkNode.getNode().toString() + "' has been initialized with hard-coded values from $@.", sourceNode, diff --git a/swift/ql/src/queries/Security/CWE-327/ECBEncryption.ql b/swift/ql/src/queries/Security/CWE-327/ECBEncryption.ql index d9a47a139f8..f5c66684fea 100644 --- a/swift/ql/src/queries/Security/CWE-327/ECBEncryption.ql +++ b/swift/ql/src/queries/Security/CWE-327/ECBEncryption.ql @@ -13,7 +13,7 @@ import swift import codeql.swift.dataflow.DataFlow import codeql.swift.dataflow.TaintTracking -import DataFlow::PathGraph +import EcbEncryptionFlow::PathGraph /** * An `Expr` that is used to initialize the block mode of a cipher. @@ -54,22 +54,22 @@ class Blowfish extends BlockMode { * A taint configuration from the constructor of ECB mode to expressions that use * it to initialize a cipher. */ -class EcbEncryptionConfig extends DataFlow::Configuration { - EcbEncryptionConfig() { this = "EcbEncryptionConfig" } - - override predicate isSource(DataFlow::Node node) { +module EcbEncryptionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { exists(CallExpr call | call.getStaticTarget().(MethodDecl).hasQualifiedName("ECB", "init()") and node.asExpr() = call ) } - override predicate isSink(DataFlow::Node node) { node.asExpr() instanceof BlockMode } + predicate isSink(DataFlow::Node node) { node.asExpr() instanceof BlockMode } } +module EcbEncryptionFlow = DataFlow::Global<EcbEncryptionConfig>; + // The query itself -from EcbEncryptionConfig config, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode -where config.hasFlowPath(sourceNode, sinkNode) +from EcbEncryptionFlow::PathNode sourceNode, EcbEncryptionFlow::PathNode sinkNode +where EcbEncryptionFlow::flowPath(sourceNode, sinkNode) select sinkNode.getNode(), sourceNode, sinkNode, "The initialization of the cipher '" + sinkNode.getNode().toString() + "' uses the insecure ECB block mode from $@.", sourceNode, sourceNode.getNode().toString() diff --git a/swift/ql/src/queries/Security/CWE-328/WeakSensitiveDataHashing.ql b/swift/ql/src/queries/Security/CWE-328/WeakSensitiveDataHashing.ql index 5a6fc396257..a5c884bd081 100755 --- a/swift/ql/src/queries/Security/CWE-328/WeakSensitiveDataHashing.ql +++ b/swift/ql/src/queries/Security/CWE-328/WeakSensitiveDataHashing.ql @@ -15,17 +15,17 @@ import swift import codeql.swift.security.SensitiveExprs import codeql.swift.dataflow.DataFlow import codeql.swift.dataflow.TaintTracking -import DataFlow::PathGraph +import WeakHashingFlow::PathGraph -class WeakHashingConfig extends TaintTracking::Configuration { - WeakHashingConfig() { this = "WeakHashingConfig" } +module WeakHashingConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node instanceof WeakHashingConfigImpl::Source } - override predicate isSource(DataFlow::Node node) { node instanceof WeakHashingConfig::Source } - - override predicate isSink(DataFlow::Node node) { node instanceof WeakHashingConfig::Sink } + predicate isSink(DataFlow::Node node) { node instanceof WeakHashingConfigImpl::Sink } } -module WeakHashingConfig { +module WeakHashingFlow = TaintTracking::Global<WeakHashingConfig>; + +module WeakHashingConfigImpl { class Source extends DataFlow::Node { Source() { this.asExpr() instanceof SensitiveExpr } } @@ -52,11 +52,11 @@ module WeakHashingConfig { } from - WeakHashingConfig config, DataFlow::PathNode source, DataFlow::PathNode sink, string algorithm, + WeakHashingFlow::PathNode source, WeakHashingFlow::PathNode sink, string algorithm, SensitiveExpr expr where - config.hasFlowPath(source, sink) and - algorithm = sink.getNode().(WeakHashingConfig::Sink).getAlgorithm() and + WeakHashingFlow::flowPath(source, sink) and + algorithm = sink.getNode().(WeakHashingConfigImpl::Sink).getAlgorithm() and expr = source.getNode().asExpr() select sink.getNode(), source, sink, "Insecure hashing algorithm (" + algorithm + ") depends on $@.", source.getNode(), diff --git a/swift/ql/src/queries/Security/CWE-757/InsecureTLS.ql b/swift/ql/src/queries/Security/CWE-757/InsecureTLS.ql index 537b0844295..62cb0db697e 100644 --- a/swift/ql/src/queries/Security/CWE-757/InsecureTLS.ql +++ b/swift/ql/src/queries/Security/CWE-757/InsecureTLS.ql @@ -14,18 +14,16 @@ import swift import codeql.swift.dataflow.DataFlow import codeql.swift.dataflow.TaintTracking import codeql.swift.dataflow.FlowSources -import DataFlow::PathGraph +import InsecureTlsFlow::PathGraph /** * A taint config to detect insecure configuration of `NSURLSessionConfiguration` */ -class InsecureTlsConfig extends TaintTracking::Configuration { - InsecureTlsConfig() { this = "InsecureTLSConfig" } - +module InsecureTlsConfig implements DataFlow::ConfigSig { /** * Holds for enum values that represent an insecure version of TLS */ - override predicate isSource(DataFlow::Node node) { + predicate isSource(DataFlow::Node node) { node.asExpr().(MethodLookupExpr).getMember().(EnumElementDecl).getName() = ["TLSv10", "TLSv11", "tlsProtocol10", "tlsProtocol11"] } @@ -33,7 +31,7 @@ class InsecureTlsConfig extends TaintTracking::Configuration { /** * Holds for assignment of TLS-related properties of `NSURLSessionConfiguration` */ - override predicate isSink(DataFlow::Node node) { + predicate isSink(DataFlow::Node node) { exists(AssignExpr assign | assign.getSource() = node.asExpr() and assign.getDest().(MemberRefExpr).getMember().(ConcreteVarDecl).getName() = @@ -45,6 +43,8 @@ class InsecureTlsConfig extends TaintTracking::Configuration { } } -from InsecureTlsConfig config, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode -where config.hasFlowPath(sourceNode, sinkNode) +module InsecureTlsFlow = TaintTracking::Global<InsecureTlsConfig>; + +from InsecureTlsFlow::PathNode sourceNode, InsecureTlsFlow::PathNode sinkNode +where InsecureTlsFlow::flowPath(sourceNode, sinkNode) select sinkNode.getNode(), sourceNode, sinkNode, "This TLS configuration is insecure." diff --git a/swift/ql/src/queries/Security/CWE-760/ConstantSalt.ql b/swift/ql/src/queries/Security/CWE-760/ConstantSalt.ql index 71f379a77ad..3b519527f41 100644 --- a/swift/ql/src/queries/Security/CWE-760/ConstantSalt.ql +++ b/swift/ql/src/queries/Security/CWE-760/ConstantSalt.ql @@ -14,7 +14,7 @@ import swift import codeql.swift.dataflow.DataFlow import codeql.swift.dataflow.TaintTracking import codeql.swift.dataflow.FlowSteps -import DataFlow::PathGraph +import ConstantSaltFlow::PathGraph /** * A constant salt is created through either a byte array or string literals. @@ -34,7 +34,7 @@ class ConstantSaltSink extends Expr { ConstantSaltSink() { // `salt` arg in `init` is a sink exists(ClassOrStructDecl c, ConstructorDecl f, CallExpr call | - c.getFullName() = ["HKDF", "PBKDF1", "PBKDF2", "Scrypt"] and + c.getName() = ["HKDF", "PBKDF1", "PBKDF2", "Scrypt"] and c.getAMember() = f and call.getStaticTarget() = f and call.getArgumentWithLabel("salt").getExpr() = this @@ -42,7 +42,7 @@ class ConstantSaltSink extends Expr { or // RNCryptor exists(ClassOrStructDecl c, MethodDecl f, CallExpr call | - c.getFullName() = ["RNCryptor", "RNEncryptor", "RNDecryptor"] and + c.getName() = ["RNCryptor", "RNEncryptor", "RNDecryptor"] and c.getAMember() = f and call.getStaticTarget() = f and call.getArgumentWithLabel(["salt", "encryptionSalt", "hmacSalt", "HMACSalt"]).getExpr() = this @@ -52,19 +52,19 @@ class ConstantSaltSink extends Expr { /** * A taint configuration from the source of constants salts to expressions that use - * them to initialize password-based enecryption keys. + * them to initialize password-based encryption keys. */ -class ConstantSaltConfig extends TaintTracking::Configuration { - ConstantSaltConfig() { this = "ConstantSaltConfig" } +module ConstantSaltConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node.asExpr() instanceof ConstantSaltSource } - override predicate isSource(DataFlow::Node node) { node.asExpr() instanceof ConstantSaltSource } - - override predicate isSink(DataFlow::Node node) { node.asExpr() instanceof ConstantSaltSink } + predicate isSink(DataFlow::Node node) { node.asExpr() instanceof ConstantSaltSink } } +module ConstantSaltFlow = TaintTracking::Global<ConstantSaltConfig>; + // The query itself -from ConstantSaltConfig config, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode -where config.hasFlowPath(sourceNode, sinkNode) +from ConstantSaltFlow::PathNode sourceNode, ConstantSaltFlow::PathNode sinkNode +where ConstantSaltFlow::flowPath(sourceNode, sinkNode) select sinkNode.getNode(), sourceNode, sinkNode, "The value '" + sourceNode.getNode().toString() + "' is used as a constant salt, which is insecure for hashing passwords." diff --git a/swift/ql/src/queries/Security/CWE-916/InsufficientHashIterations.ql b/swift/ql/src/queries/Security/CWE-916/InsufficientHashIterations.ql index d8cb049ea50..7111ac61ed7 100644 --- a/swift/ql/src/queries/Security/CWE-916/InsufficientHashIterations.ql +++ b/swift/ql/src/queries/Security/CWE-916/InsufficientHashIterations.ql @@ -13,7 +13,7 @@ import swift import codeql.swift.dataflow.DataFlow import codeql.swift.dataflow.TaintTracking -import DataFlow::PathGraph +import InsufficientHashIterationsFlow::PathGraph /** * An `Expr` that is used to initialize a password-based encryption key. @@ -34,7 +34,7 @@ class InsufficientHashIterationsSink extends Expr { InsufficientHashIterationsSink() { // `iterations` arg in `init` is a sink exists(ClassOrStructDecl c, ConstructorDecl f, CallExpr call | - c.getFullName() = ["PBKDF1", "PBKDF2"] and + c.getName() = ["PBKDF1", "PBKDF2"] and c.getAMember() = f and call.getStaticTarget() = f and call.getArgumentWithLabel("iterations").getExpr() = this @@ -46,21 +46,19 @@ class InsufficientHashIterationsSink extends Expr { * A dataflow configuration from the hash iterations source to expressions that use * it to initialize hash functions. */ -class InsufficientHashIterationsConfig extends TaintTracking::Configuration { - InsufficientHashIterationsConfig() { this = "InsufficientHashIterationsConfig" } +module InsufficientHashIterationsConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node.asExpr() instanceof IterationsSource } - override predicate isSource(DataFlow::Node node) { node.asExpr() instanceof IterationsSource } - - override predicate isSink(DataFlow::Node node) { - node.asExpr() instanceof InsufficientHashIterationsSink - } + predicate isSink(DataFlow::Node node) { node.asExpr() instanceof InsufficientHashIterationsSink } } +module InsufficientHashIterationsFlow = TaintTracking::Global<InsufficientHashIterationsConfig>; + // The query itself from - InsufficientHashIterationsConfig config, DataFlow::PathNode sourceNode, - DataFlow::PathNode sinkNode -where config.hasFlowPath(sourceNode, sinkNode) + InsufficientHashIterationsFlow::PathNode sourceNode, + InsufficientHashIterationsFlow::PathNode sinkNode +where InsufficientHashIterationsFlow::flowPath(sourceNode, sinkNode) select sinkNode.getNode(), sourceNode, sinkNode, "The value '" + sourceNode.getNode().toString() + "' is an insufficient number of iterations for secure password hashing." diff --git a/swift/ql/src/queries/Summary/SummaryStats.ql b/swift/ql/src/queries/Summary/SummaryStats.ql index 10dcc0c5199..444c4da2ca2 100644 --- a/swift/ql/src/queries/Summary/SummaryStats.ql +++ b/swift/ql/src/queries/Summary/SummaryStats.ql @@ -21,12 +21,12 @@ module TaintReachConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node node) { any() } } -module TaintReachFlow = TaintTracking::Make<TaintReachConfig>; +module TaintReachFlow = TaintTracking::Global<TaintReachConfig>; /** * Gets the total number of dataflow nodes that taint reaches (from any source). */ -int taintedNodesCount() { result = count(DataFlow::Node n | TaintReachFlow::hasFlowTo(n)) } +int taintedNodesCount() { result = count(DataFlow::Node n | TaintReachFlow::flowTo(n)) } /** * Gets the proportion of dataflow nodes that taint reaches (from any source), diff --git a/swift/ql/test/extractor-tests/declarations/all.expected b/swift/ql/test/extractor-tests/declarations/all.expected index 73027f2a857..f892820f41e 100644 --- a/swift/ql/test/extractor-tests/declarations/all.expected +++ b/swift/ql/test/extractor-tests/declarations/all.expected @@ -272,5 +272,5 @@ | declarations.swift:182:7:182:7 | B.init() | | | declarations.swift:182:7:182:7 | self | | | declarations.swift:182:7:182:7 | self | | -| declarations.swift:183:1:183:15 | A | | -| declarations.swift:184:1:184:18 | C | | +| declarations.swift:183:1:183:15 | A | getAliasedType:B | +| declarations.swift:184:1:184:18 | C | getAliasedType:Int? | diff --git a/swift/ql/test/extractor-tests/declarations/all.ql b/swift/ql/test/extractor-tests/declarations/all.ql index bf36129f58a..1580a8e6002 100644 --- a/swift/ql/test/extractor-tests/declarations/all.ql +++ b/swift/ql/test/extractor-tests/declarations/all.ql @@ -1,8 +1,7 @@ import swift string describe(Decl decl) { - //result = "getAliasedType:" + decl.(TypeAliasDecl).getAliasedType().toString() TODO: not yet implemented - none() + result = "getAliasedType:" + decl.(TypeAliasDecl).getAliasedType().toString() } from Decl decl diff --git a/swift/ql/test/extractor-tests/patterns/all.expected b/swift/ql/test/extractor-tests/patterns/all.expected index 0e63cbec501..bf339e77303 100644 --- a/swift/ql/test/extractor-tests/patterns/all.expected +++ b/swift/ql/test/extractor-tests/patterns/all.expected @@ -39,3 +39,161 @@ | patterns.swift:46:9:46:9 | b | | patterns.swift:49:10:49:10 | true | | patterns.swift:50:10:50:10 | false | +| patterns.swift:55:9:55:9 | a | +| patterns.swift:55:16:55:16 | b | +| patterns.swift:55:23:55:23 | c | +| patterns.swift:55:23:55:26 | ... as ... | +| patterns.swift:57:8:57:20 | let ... | +| patterns.swift:57:8:57:20 | let ...? | +| patterns.swift:57:12:57:20 | (...) | +| patterns.swift:57:13:57:13 | a | +| patterns.swift:57:16:57:16 | b | +| patterns.swift:57:19:57:19 | c | +| patterns.swift:58:13:58:29 | (...) | +| patterns.swift:58:14:58:14 | =~ ... | +| patterns.swift:58:17:58:21 | let ... | +| patterns.swift:58:21:58:21 | b | +| patterns.swift:58:24:58:28 | let ... | +| patterns.swift:58:28:58:28 | c | +| patterns.swift:61:14:61:14 | =~ ... | +| patterns.swift:62:14:62:18 | let ... | +| patterns.swift:62:18:62:18 | c | +| patterns.swift:63:9:63:9 | _ | +| patterns.swift:78:9:78:9 | a | +| patterns.swift:78:9:78:13 | ... as ... | +| patterns.swift:81:10:81:11 | .myNone | +| patterns.swift:83:10:83:25 | .mySingle(...) | +| patterns.swift:83:19:83:25 | (...) | +| patterns.swift:83:20:83:24 | let ... | +| patterns.swift:83:24:83:24 | a | +| patterns.swift:85:10:85:30 | .myPair(...) | +| patterns.swift:85:17:85:30 | (...) | +| patterns.swift:85:18:85:22 | let ... | +| patterns.swift:85:22:85:22 | a | +| patterns.swift:85:25:85:29 | let ... | +| patterns.swift:85:29:85:29 | b | +| patterns.swift:88:10:88:26 | let ... | +| patterns.swift:88:14:88:26 | .myCons(...) | +| patterns.swift:88:21:88:26 | (...) | +| patterns.swift:88:22:88:22 | a | +| patterns.swift:88:25:88:25 | _ | +| patterns.swift:92:13:92:28 | .mySingle(...) | +| patterns.swift:92:22:92:28 | (...) | +| patterns.swift:92:23:92:27 | let ... | +| patterns.swift:92:27:92:27 | x | +| patterns.swift:95:13:95:33 | .myPair(...) | +| patterns.swift:95:20:95:33 | (...) | +| patterns.swift:95:21:95:25 | let ... | +| patterns.swift:95:25:95:25 | x | +| patterns.swift:95:28:95:32 | let ... | +| patterns.swift:95:32:95:32 | y | +| patterns.swift:103:10:103:11 | .myNone | +| patterns.swift:105:10:105:25 | .mySingle(...) | +| patterns.swift:105:19:105:25 | (...) | +| patterns.swift:105:20:105:24 | let ... | +| patterns.swift:105:24:105:24 | a | +| patterns.swift:107:10:107:30 | .myPair(...) | +| patterns.swift:107:17:107:30 | (...) | +| patterns.swift:107:18:107:22 | let ... | +| patterns.swift:107:22:107:22 | a | +| patterns.swift:107:25:107:29 | let ... | +| patterns.swift:107:29:107:29 | b | +| patterns.swift:110:10:110:26 | let ... | +| patterns.swift:110:14:110:26 | .myCons(...) | +| patterns.swift:110:21:110:26 | (...) | +| patterns.swift:110:22:110:22 | a | +| patterns.swift:110:25:110:25 | _ | +| patterns.swift:114:13:114:28 | .mySingle(...) | +| patterns.swift:114:22:114:28 | (...) | +| patterns.swift:114:23:114:27 | let ... | +| patterns.swift:114:27:114:27 | x | +| patterns.swift:117:13:117:33 | .myPair(...) | +| patterns.swift:117:20:117:33 | (...) | +| patterns.swift:117:21:117:25 | let ... | +| patterns.swift:117:25:117:25 | x | +| patterns.swift:117:28:117:32 | let ... | +| patterns.swift:117:32:117:32 | y | +| patterns.swift:125:10:125:11 | .myNone | +| patterns.swift:127:10:127:25 | .mySingle(...) | +| patterns.swift:127:19:127:25 | (...) | +| patterns.swift:127:20:127:24 | let ... | +| patterns.swift:127:24:127:24 | a | +| patterns.swift:129:10:129:30 | .myPair(...) | +| patterns.swift:129:17:129:30 | (...) | +| patterns.swift:129:18:129:22 | let ... | +| patterns.swift:129:22:129:22 | a | +| patterns.swift:129:25:129:29 | let ... | +| patterns.swift:129:29:129:29 | b | +| patterns.swift:132:10:132:26 | let ... | +| patterns.swift:132:14:132:26 | .myCons(...) | +| patterns.swift:132:21:132:26 | (...) | +| patterns.swift:132:22:132:22 | a | +| patterns.swift:132:25:132:25 | _ | +| patterns.swift:136:13:136:28 | .mySingle(...) | +| patterns.swift:136:22:136:28 | (...) | +| patterns.swift:136:23:136:27 | let ... | +| patterns.swift:136:27:136:27 | x | +| patterns.swift:139:13:139:33 | .myPair(...) | +| patterns.swift:139:20:139:33 | (...) | +| patterns.swift:139:21:139:25 | let ... | +| patterns.swift:139:25:139:25 | x | +| patterns.swift:139:28:139:32 | let ... | +| patterns.swift:139:32:139:32 | y | +| patterns.swift:144:9:144:9 | b | +| patterns.swift:144:9:144:12 | ... as ... | +| patterns.swift:147:10:147:11 | .myNone | +| patterns.swift:149:10:149:25 | .mySingle(...) | +| patterns.swift:149:19:149:25 | (...) | +| patterns.swift:149:20:149:24 | let ... | +| patterns.swift:149:24:149:24 | a | +| patterns.swift:151:10:151:30 | .myPair(...) | +| patterns.swift:151:17:151:30 | (...) | +| patterns.swift:151:18:151:22 | let ... | +| patterns.swift:151:22:151:22 | a | +| patterns.swift:151:25:151:29 | let ... | +| patterns.swift:151:29:151:29 | b | +| patterns.swift:154:10:154:38 | let ... | +| patterns.swift:154:14:154:38 | .myCons(...) | +| patterns.swift:154:21:154:38 | (...) | +| patterns.swift:154:22:154:22 | a | +| patterns.swift:154:25:154:37 | .myPair(...) | +| patterns.swift:154:32:154:37 | (...) | +| patterns.swift:154:33:154:33 | b | +| patterns.swift:154:36:154:36 | c | +| patterns.swift:158:10:158:26 | let ... | +| patterns.swift:158:14:158:26 | .myCons(...) | +| patterns.swift:158:21:158:26 | (...) | +| patterns.swift:158:22:158:22 | a | +| patterns.swift:158:25:158:25 | _ | +| patterns.swift:162:13:162:28 | .mySingle(...) | +| patterns.swift:162:22:162:28 | (...) | +| patterns.swift:162:23:162:27 | let ... | +| patterns.swift:162:27:162:27 | x | +| patterns.swift:165:13:165:39 | .myPair(...) | +| patterns.swift:165:26:165:39 | (...) | +| patterns.swift:165:27:165:31 | let ... | +| patterns.swift:165:31:165:31 | x | +| patterns.swift:165:34:165:38 | let ... | +| patterns.swift:165:38:165:38 | y | +| patterns.swift:169:13:169:41 | let ... | +| patterns.swift:169:17:169:41 | .myCons(...) | +| patterns.swift:169:24:169:41 | (...) | +| patterns.swift:169:25:169:25 | _ | +| patterns.swift:169:28:169:40 | .myPair(...) | +| patterns.swift:169:35:169:40 | (...) | +| patterns.swift:169:36:169:36 | _ | +| patterns.swift:169:39:169:39 | c | +| patterns.swift:174:10:174:55 | let ... | +| patterns.swift:174:14:174:55 | (...) | +| patterns.swift:174:15:174:27 | .myPair(...) | +| patterns.swift:174:22:174:27 | (...) | +| patterns.swift:174:23:174:23 | a | +| patterns.swift:174:26:174:26 | b | +| patterns.swift:174:30:174:54 | .myCons(...) | +| patterns.swift:174:37:174:54 | (...) | +| patterns.swift:174:38:174:38 | c | +| patterns.swift:174:41:174:53 | .myPair(...) | +| patterns.swift:174:48:174:53 | (...) | +| patterns.swift:174:49:174:49 | d | +| patterns.swift:174:52:174:52 | e | +| patterns.swift:180:5:180:5 | _ | diff --git a/swift/ql/test/extractor-tests/patterns/bound_and_unbound.expected b/swift/ql/test/extractor-tests/patterns/bound_and_unbound.expected new file mode 100644 index 00000000000..80ae00d4850 --- /dev/null +++ b/swift/ql/test/extractor-tests/patterns/bound_and_unbound.expected @@ -0,0 +1,66 @@ +bound +| patterns.swift:2:9:2:9 | an_int | +| patterns.swift:3:9:3:9 | a_string | +| patterns.swift:4:10:4:10 | x | +| patterns.swift:4:13:4:13 | y | +| patterns.swift:4:16:4:16 | z | +| patterns.swift:10:9:10:9 | point | +| patterns.swift:12:15:12:15 | xx | +| patterns.swift:12:19:12:19 | yy | +| patterns.swift:24:9:24:9 | v | +| patterns.swift:28:19:28:19 | i | +| patterns.swift:28:22:28:22 | s | +| patterns.swift:31:9:31:9 | w | +| patterns.swift:34:14:34:14 | n | +| patterns.swift:38:9:38:9 | a | +| patterns.swift:42:14:42:14 | x | +| patterns.swift:46:9:46:9 | b | +| patterns.swift:55:9:55:9 | a | +| patterns.swift:55:16:55:16 | b | +| patterns.swift:55:23:55:23 | c | +| patterns.swift:57:13:57:13 | a | +| patterns.swift:57:19:57:19 | c | +| patterns.swift:58:21:58:21 | b | +| patterns.swift:62:18:62:18 | c | +| patterns.swift:78:9:78:9 | a | +| patterns.swift:83:24:83:24 | a | +| patterns.swift:85:22:85:22 | a | +| patterns.swift:85:29:85:29 | b | +| patterns.swift:88:22:88:22 | a | +| patterns.swift:92:27:92:27 | x | +| patterns.swift:95:25:95:25 | x | +| patterns.swift:95:32:95:32 | y | +| patterns.swift:105:24:105:24 | a | +| patterns.swift:107:22:107:22 | a | +| patterns.swift:107:29:107:29 | b | +| patterns.swift:110:22:110:22 | a | +| patterns.swift:114:27:114:27 | x | +| patterns.swift:117:25:117:25 | x | +| patterns.swift:117:32:117:32 | y | +| patterns.swift:127:24:127:24 | a | +| patterns.swift:129:22:129:22 | a | +| patterns.swift:129:29:129:29 | b | +| patterns.swift:132:22:132:22 | a | +| patterns.swift:136:27:136:27 | x | +| patterns.swift:139:25:139:25 | x | +| patterns.swift:139:32:139:32 | y | +| patterns.swift:144:9:144:9 | b | +| patterns.swift:149:24:149:24 | a | +| patterns.swift:151:22:151:22 | a | +| patterns.swift:151:29:151:29 | b | +| patterns.swift:154:22:154:22 | a | +| patterns.swift:154:33:154:33 | b | +| patterns.swift:154:36:154:36 | c | +| patterns.swift:158:22:158:22 | a | +| patterns.swift:162:27:162:27 | x | +| patterns.swift:165:31:165:31 | x | +| patterns.swift:165:38:165:38 | y | +| patterns.swift:169:39:169:39 | c | +| patterns.swift:174:23:174:23 | a | +| patterns.swift:174:26:174:26 | b | +| patterns.swift:174:38:174:38 | c | +| patterns.swift:174:49:174:49 | d | +| patterns.swift:174:52:174:52 | e | +unbound +| patterns.swift:57:16:57:16 | b | +| patterns.swift:58:28:58:28 | c | diff --git a/swift/ql/test/extractor-tests/patterns/bound_and_unbound.ql b/swift/ql/test/extractor-tests/patterns/bound_and_unbound.ql new file mode 100644 index 00000000000..192938fea66 --- /dev/null +++ b/swift/ql/test/extractor-tests/patterns/bound_and_unbound.ql @@ -0,0 +1,11 @@ +import swift + +query predicate bound(NamedPattern p) { + p.getFile().getBaseName() = "patterns.swift" and + p.hasVarDecl() +} + +query predicate unbound(NamedPattern p) { + p.getFile().getBaseName() = "patterns.swift" and + not p.hasVarDecl() +} diff --git a/swift/ql/test/extractor-tests/patterns/matching_expr.expected b/swift/ql/test/extractor-tests/patterns/matching_expr.expected new file mode 100644 index 00000000000..46f5d675df9 --- /dev/null +++ b/swift/ql/test/extractor-tests/patterns/matching_expr.expected @@ -0,0 +1,80 @@ +| patterns.swift:2:9:2:9 | an_int | patterns.swift:2:18:2:18 | 42 | +| patterns.swift:3:9:3:9 | a_string | patterns.swift:3:28:3:28 | here | +| patterns.swift:3:9:3:19 | ... as ... | patterns.swift:3:28:3:28 | here | +| patterns.swift:4:9:4:17 | (...) | patterns.swift:4:21:4:29 | (...) | +| patterns.swift:4:10:4:10 | x | patterns.swift:4:22:4:22 | 1 | +| patterns.swift:4:13:4:13 | y | patterns.swift:4:25:4:25 | 2 | +| patterns.swift:4:16:4:16 | z | patterns.swift:4:28:4:28 | 3 | +| patterns.swift:5:9:5:9 | _ | patterns.swift:5:13:5:13 | any | +| patterns.swift:6:10:6:10 | _ | patterns.swift:6:15:6:15 | paren | +| patterns.swift:10:9:10:9 | point | patterns.swift:10:17:10:22 | (...) | +| patterns.swift:12:14:12:21 | (...) | patterns.swift:11:12:11:12 | point | +| patterns.swift:16:10:16:14 | =~ ... | patterns.swift:15:12:15:12 | 3 | +| patterns.swift:17:10:17:10 | _ | patterns.swift:15:12:15:12 | 3 | +| patterns.swift:24:9:24:9 | v | patterns.swift:24:18:24:19 | .bar | +| patterns.swift:24:9:24:12 | ... as ... | patterns.swift:24:18:24:19 | .bar | +| patterns.swift:27:10:27:11 | .bar | patterns.swift:26:12:26:12 | v | +| patterns.swift:28:14:28:23 | .baz(...) | patterns.swift:26:12:26:12 | v | +| patterns.swift:31:9:31:9 | w | patterns.swift:31:19:31:19 | nil | +| patterns.swift:31:9:31:15 | ... as ... | patterns.swift:31:19:31:19 | nil | +| patterns.swift:34:14:34:14 | n | patterns.swift:33:12:33:12 | w | +| patterns.swift:34:14:34:15 | let ...? | patterns.swift:33:12:33:12 | w | +| patterns.swift:35:10:35:10 | _ | patterns.swift:33:12:33:12 | w | +| patterns.swift:38:9:38:9 | a | patterns.swift:38:18:38:18 | any | +| patterns.swift:38:9:38:12 | ... as ... | patterns.swift:38:18:38:18 | any | +| patterns.swift:41:10:41:13 | ... is ... | patterns.swift:40:12:40:12 | a | +| patterns.swift:42:14:42:14 | x | patterns.swift:40:12:40:12 | a | +| patterns.swift:42:14:42:19 | ... is ... | patterns.swift:40:12:40:12 | a | +| patterns.swift:43:10:43:10 | _ | patterns.swift:40:12:40:12 | a | +| patterns.swift:46:9:46:9 | b | patterns.swift:46:13:46:13 | true | +| patterns.swift:49:10:49:10 | true | patterns.swift:48:12:48:12 | b | +| patterns.swift:50:10:50:10 | false | patterns.swift:48:12:48:12 | b | +| patterns.swift:55:9:55:9 | a | patterns.swift:55:13:55:13 | 1 | +| patterns.swift:55:16:55:16 | b | patterns.swift:55:20:55:20 | 2 | +| patterns.swift:55:23:55:23 | c | patterns.swift:55:32:55:32 | 3 | +| patterns.swift:55:23:55:26 | ... as ... | patterns.swift:55:32:55:32 | 3 | +| patterns.swift:57:8:57:20 | let ...? | patterns.swift:57:24:57:47 | call to ... | +| patterns.swift:57:12:57:20 | (...) | patterns.swift:57:24:57:47 | call to ... | +| patterns.swift:58:13:58:29 | (...) | patterns.swift:58:33:58:41 | (...) | +| patterns.swift:58:14:58:14 | =~ ... | patterns.swift:58:34:58:34 | a | +| patterns.swift:58:21:58:21 | b | patterns.swift:58:37:58:37 | b | +| patterns.swift:58:28:58:28 | c | patterns.swift:58:40:58:40 | c | +| patterns.swift:61:14:61:14 | =~ ... | patterns.swift:60:12:60:12 | a | +| patterns.swift:62:18:62:18 | c | patterns.swift:60:12:60:12 | a | +| patterns.swift:63:9:63:9 | _ | patterns.swift:60:12:60:12 | a | +| patterns.swift:78:9:78:9 | a | patterns.swift:78:22:78:23 | .myNone | +| patterns.swift:78:9:78:13 | ... as ... | patterns.swift:78:22:78:23 | .myNone | +| patterns.swift:81:10:81:11 | .myNone | patterns.swift:80:12:80:12 | a | +| patterns.swift:83:10:83:25 | .mySingle(...) | patterns.swift:80:12:80:12 | a | +| patterns.swift:85:10:85:30 | .myPair(...) | patterns.swift:80:12:80:12 | a | +| patterns.swift:88:14:88:26 | .myCons(...) | patterns.swift:80:12:80:12 | a | +| patterns.swift:92:13:92:28 | .mySingle(...) | patterns.swift:92:32:92:32 | a | +| patterns.swift:95:13:95:33 | .myPair(...) | patterns.swift:95:37:95:37 | a | +| patterns.swift:103:10:103:11 | .myNone | patterns.swift:102:12:102:12 | a | +| patterns.swift:105:10:105:25 | .mySingle(...) | patterns.swift:102:12:102:12 | a | +| patterns.swift:107:10:107:30 | .myPair(...) | patterns.swift:102:12:102:12 | a | +| patterns.swift:110:14:110:26 | .myCons(...) | patterns.swift:102:12:102:12 | a | +| patterns.swift:114:13:114:28 | .mySingle(...) | patterns.swift:114:32:114:32 | a | +| patterns.swift:117:13:117:33 | .myPair(...) | patterns.swift:117:37:117:37 | a | +| patterns.swift:125:10:125:11 | .myNone | patterns.swift:124:12:124:12 | a | +| patterns.swift:127:10:127:25 | .mySingle(...) | patterns.swift:124:12:124:12 | a | +| patterns.swift:129:10:129:30 | .myPair(...) | patterns.swift:124:12:124:12 | a | +| patterns.swift:132:14:132:26 | .myCons(...) | patterns.swift:124:12:124:12 | a | +| patterns.swift:136:13:136:28 | .mySingle(...) | patterns.swift:136:32:136:32 | a | +| patterns.swift:139:13:139:33 | .myPair(...) | patterns.swift:139:37:139:37 | a | +| patterns.swift:144:9:144:9 | b | patterns.swift:144:21:144:34 | call to ... | +| patterns.swift:144:9:144:12 | ... as ... | patterns.swift:144:21:144:34 | call to ... | +| patterns.swift:147:10:147:11 | .myNone | patterns.swift:146:12:146:12 | b | +| patterns.swift:149:10:149:25 | .mySingle(...) | patterns.swift:146:12:146:12 | b | +| patterns.swift:151:10:151:30 | .myPair(...) | patterns.swift:146:12:146:12 | b | +| patterns.swift:154:14:154:38 | .myCons(...) | patterns.swift:146:12:146:12 | b | +| patterns.swift:158:14:158:26 | .myCons(...) | patterns.swift:146:12:146:12 | b | +| patterns.swift:162:13:162:28 | .mySingle(...) | patterns.swift:162:32:162:57 | call to ... | +| patterns.swift:165:13:165:39 | .myPair(...) | patterns.swift:165:43:165:62 | call to ... | +| patterns.swift:165:31:165:31 | x | patterns.swift:165:51:165:58 | call to source() | +| patterns.swift:165:38:165:38 | y | patterns.swift:165:61:165:61 | 0 | +| patterns.swift:169:17:169:41 | .myCons(...) | patterns.swift:169:45:169:45 | b | +| patterns.swift:174:14:174:55 | (...) | patterns.swift:173:12:173:17 | (...) | +| patterns.swift:174:15:174:27 | .myPair(...) | patterns.swift:173:13:173:13 | a | +| patterns.swift:174:30:174:54 | .myCons(...) | patterns.swift:173:16:173:16 | b | +| patterns.swift:180:5:180:5 | _ | patterns.swift:173:12:173:17 | (...) | diff --git a/swift/ql/test/extractor-tests/patterns/matching_expr.ql b/swift/ql/test/extractor-tests/patterns/matching_expr.ql new file mode 100644 index 00000000000..ea01332aaeb --- /dev/null +++ b/swift/ql/test/extractor-tests/patterns/matching_expr.ql @@ -0,0 +1,5 @@ +import swift + +from Pattern p, Expr e +where p.getMatchingExpr() = e +select p, e diff --git a/swift/ql/test/extractor-tests/patterns/patterns.swift b/swift/ql/test/extractor-tests/patterns/patterns.swift index ebc369310c9..95f3bfb17b6 100644 --- a/swift/ql/test/extractor-tests/patterns/patterns.swift +++ b/swift/ql/test/extractor-tests/patterns/patterns.swift @@ -50,3 +50,134 @@ func switch_patterns() { case false: "false" } } + +func bound_and_unbound() { + let a = 1, b = 2, c: Int = 3 + + if let (a, b, c) = Optional.some((a, b, c)) { _ = (a, c) } + if case (a, let b, let c) = (a, b, c) { _ = (b) } + + switch a { + case c: "equals c" + case let c: "binds c" + default: "default" + } +} + +func source() -> Int { 0 } +func sink(arg: Int) { } + +indirect enum MyEnum { + case myNone + case mySingle(Int) + case myPair(Int, Int) + case myCons(Int, MyEnum) +} + +func test_enums() { + var a : MyEnum = .myNone + + switch a { + case .myNone: + () + case .mySingle(let a): + sink(arg: a) + case .myPair(let a, let b): + sink(arg: a) + sink(arg: b) + case let .myCons(a, _): + sink(arg: a) + } + + if case .mySingle(let x) = a { + sink(arg: x) + } + if case .myPair(let x, let y) = a { + sink(arg: x) + sink(arg: y) + } + + a = .mySingle(source()) + + switch a { + case .myNone: + () + case .mySingle(let a): + sink(arg: a) + case .myPair(let a, let b): + sink(arg: a) + sink(arg: b) + case let .myCons(a, _): + sink(arg: a) + } + + if case .mySingle(let x) = a { + sink(arg: x) + } + if case .myPair(let x, let y) = a { + sink(arg: x) + sink(arg: y) + } + + a = MyEnum.myPair(0, source()) + + switch a { + case .myNone: + () + case .mySingle(let a): + sink(arg: a) + case .myPair(let a, let b): + sink(arg: a) + sink(arg: b) + case let .myCons(a, _): + sink(arg: a) + } + + if case .mySingle(let x) = a { + sink(arg: x) + } + if case .myPair(let x, let y) = a { + sink(arg: x) + sink(arg: y) + } + + let b: MyEnum = .myCons(42, a) + + switch b { + case .myNone: + () + case .mySingle(let a): + sink(arg: a) + case .myPair(let a, let b): + sink(arg: a) + sink(arg: b) + case let .myCons(a, .myPair(b, c)): + sink(arg: a) + sink(arg: b) + sink(arg: c) + case let .myCons(a, _): + sink(arg: a) + } + + if case .mySingle(let x) = MyEnum.myPair(source(), 0) { + sink(arg: x) + } + if case MyEnum.myPair(let x, let y) = .myPair(source(), 0) { + sink(arg: x) + sink(arg: y) + } + if case let .myCons(_, .myPair(_, c)) = b { + sink(arg: c) + } + + switch (a, b) { + case let (.myPair(a, b), .myCons(c, .myPair(d, e))): + sink(arg: a) + sink(arg: b) + sink(arg: c) + sink(arg: d) + sink(arg: e) + default: + () + } +} diff --git a/swift/ql/test/extractor-tests/statements/ConditionElements.expected b/swift/ql/test/extractor-tests/statements/ConditionElements.expected index e7f18b329d8..c8a1d23c5fe 100644 --- a/swift/ql/test/extractor-tests/statements/ConditionElements.expected +++ b/swift/ql/test/extractor-tests/statements/ConditionElements.expected @@ -1,7 +1,7 @@ | statements.swift:3:8:3:13 | ... .==(_:_:) ... | statements.swift:3:8:3:13 | ... .==(_:_:) ... | | statements.swift:10:17:10:24 | ... .<(_:_:) ... | statements.swift:10:18:10:22 | ... .<(_:_:) ... | | statements.swift:39:9:39:14 | ... .!=(_:_:) ... | statements.swift:39:9:39:14 | ... .!=(_:_:) ... | -| statements.swift:65:4:65:19 | let ... = ... | statements.swift:65:9:65:15 | let ... | -| statements.swift:65:4:65:19 | let ... = ... | statements.swift:65:19:65:19 | x | +| statements.swift:65:4:65:19 | let ...? = ... | statements.swift:65:13:65:15 | let ...? | +| statements.swift:65:4:65:19 | let ...? = ... | statements.swift:65:19:65:19 | x | | statements.swift:67:4:67:20 | .some(...) = ... | statements.swift:67:9:67:16 | .some(...) | | statements.swift:67:4:67:20 | .some(...) = ... | statements.swift:67:20:67:20 | x | diff --git a/swift/ql/test/library-tests/ast/PrintAst.expected b/swift/ql/test/library-tests/ast/PrintAst.expected index a09e72df54c..dc06c2810cd 100644 --- a/swift/ql/test/library-tests/ast/PrintAst.expected +++ b/swift/ql/test/library-tests/ast/PrintAst.expected @@ -180,8 +180,8 @@ cfg.swift: # 35| getPattern(): [IsPattern] ... is ... # 35| getSubPattern(): [EnumElementPattern] .error3(...) # 35| getSubPattern(): [TuplePattern] (...) -# 35| getElement(0): [BindingPattern] let ... -# 35| getSubPattern(): [NamedPattern] withParam +# 35| getElement(0): [NamedPattern] withParam +# 35| getElement(0).getFullyUnresolved(): [BindingPattern] let ... # 37| getCatch(2): [CaseStmt] case ... # 37| getBody(): [BraceStmt] { ... } # 38| getElement(0): [CallExpr] call to print(_:separator:terminator:) @@ -239,9 +239,9 @@ cfg.swift: # 40| getExpr(): [DefaultArgumentExpr] default separator # 40| getArgument(2): [Argument] terminator: default terminator # 40| getExpr(): [DefaultArgumentExpr] default terminator -# 39| getLabel(0): [CaseLabelItem] let ... -# 39| getPattern(): [BindingPattern] let ... -# 39| getSubPattern(): [NamedPattern] error +# 39| getLabel(0): [CaseLabelItem] error +# 39| getPattern(): [NamedPattern] error +# 39| getPattern().getFullyUnresolved(): [BindingPattern] let ... # 42| getElement(1): [ReturnStmt] return ... # 42| getResult(): [IntegerLiteralExpr] 0 # 35| [ConcreteVarDecl] withParam @@ -803,9 +803,9 @@ cfg.swift: # 156| getCondition(): [StmtCondition] StmtCondition # 156| getElement(0): [ConditionElement] .some(...) = ... # 156| getPattern(): [EnumElementPattern] .some(...) -# 156| getSubPattern(): [BindingPattern] let ... -# 156| getSubPattern(): [NamedPattern] x +# 156| getSubPattern(): [NamedPattern] x # 156| getSubPattern().getFullyUnresolved(): [ParenPattern] (...) +# 156| getImmediateSubPattern(): [BindingPattern] let ... # 156| getInitializer(): [DeclRefExpr] xOptional # 156| getThen(): [BraceStmt] { ... } # 157| getElement(0): [ReturnStmt] return ... @@ -5375,11 +5375,11 @@ patterns.swift: # 12| getCase(0): [CaseStmt] case ... # 12| getBody(): [BraceStmt] { ... } # 12| getElement(0): [StringLiteralExpr] binding -# 12| getLabel(0): [CaseLabelItem] let ... -# 12| getPattern(): [BindingPattern] let ... -# 12| getSubPattern(): [TuplePattern] (...) -# 12| getElement(0): [NamedPattern] xx -# 12| getElement(1): [NamedPattern] yy +# 12| getLabel(0): [CaseLabelItem] (...) +# 12| getPattern(): [TuplePattern] (...) +# 12| getElement(0): [NamedPattern] xx +# 12| getElement(1): [NamedPattern] yy +# 12| getPattern().getFullyUnresolved(): [BindingPattern] let ... # 15| getElement(3): [SwitchStmt] switch 3 { ... } # 15| getExpr(): [IntegerLiteralExpr] 3 # 16| getCase(0): [CaseStmt] case ... @@ -5424,12 +5424,12 @@ patterns.swift: # 28| getCase(1): [CaseStmt] case ... # 28| getBody(): [BraceStmt] { ... } # 28| getElement(0): [DeclRefExpr] i -# 28| getLabel(0): [CaseLabelItem] let ... -# 28| getPattern(): [BindingPattern] let ... -# 28| getSubPattern(): [EnumElementPattern] .baz(...) -# 28| getSubPattern(): [TuplePattern] (...) -# 28| getElement(0): [NamedPattern] i -# 28| getElement(1): [NamedPattern] s +# 28| getLabel(0): [CaseLabelItem] .baz(...) +# 28| getPattern(): [EnumElementPattern] .baz(...) +# 28| getSubPattern(): [TuplePattern] (...) +# 28| getElement(0): [NamedPattern] i +# 28| getElement(1): [NamedPattern] s +# 28| getPattern().getFullyUnresolved(): [BindingPattern] let ... # 31| getElement(8): [PatternBindingDecl] var ... = ... # 31| getInit(0): [NilLiteralExpr] nil # 31| getPattern(0): [TypedPattern] ... as ... @@ -5442,10 +5442,10 @@ patterns.swift: # 34| getCase(0): [CaseStmt] case ... # 34| getBody(): [BraceStmt] { ... } # 34| getElement(0): [DeclRefExpr] n -# 34| getLabel(0): [CaseLabelItem] let ... -# 34| getPattern(): [BindingPattern] let ... -# 34| getSubPattern(): [OptionalSomePattern] let ...? -# 34| getSubPattern(): [NamedPattern] n +# 34| getLabel(0): [CaseLabelItem] let ...? +# 34| getPattern(): [OptionalSomePattern] let ...? +# 34| getSubPattern(): [NamedPattern] n +# 34| getPattern().getFullyUnresolved(): [BindingPattern] let ... # 35| getCase(1): [CaseStmt] case ... # 35| getBody(): [BraceStmt] { ... } # 35| getElement(0): [StringLiteralExpr] none @@ -5470,11 +5470,11 @@ patterns.swift: # 42| getCase(1): [CaseStmt] case ... # 42| getBody(): [BraceStmt] { ... } # 42| getElement(0): [StringLiteralExpr] as pattern -# 42| getLabel(0): [CaseLabelItem] let ... -# 42| getPattern(): [BindingPattern] let ... -# 42| getSubPattern(): [IsPattern] ... is ... -# 42| getCastTypeRepr(): [TypeRepr] String -# 42| getSubPattern(): [NamedPattern] x +# 42| getLabel(0): [CaseLabelItem] ... is ... +# 42| getPattern(): [IsPattern] ... is ... +# 42| getCastTypeRepr(): [TypeRepr] String +# 42| getSubPattern(): [NamedPattern] x +# 42| getPattern().getFullyUnresolved(): [BindingPattern] let ... # 43| getCase(2): [CaseStmt] case ... # 43| getBody(): [BraceStmt] { ... } # 43| getElement(0): [StringLiteralExpr] other @@ -5509,6 +5509,678 @@ patterns.swift: # 34| Type = Int # 42| [ConcreteVarDecl] x # 42| Type = String +# 54| [ConcreteFuncDecl] bound_and_unbound() +# 54| InterfaceType = () -> () +# 54| getBody(): [BraceStmt] { ... } +# 55| getElement(0): [PatternBindingDecl] var ... = ... +# 55| getInit(0): [IntegerLiteralExpr] 1 +# 55| getInit(1): [IntegerLiteralExpr] 2 +# 55| getInit(2): [IntegerLiteralExpr] 3 +# 55| getPattern(0): [NamedPattern] a +# 55| getPattern(1): [NamedPattern] b +# 55| getPattern(2): [TypedPattern] ... as ... +# 55| getSubPattern(): [NamedPattern] c +# 55| getTypeRepr(): [TypeRepr] Int +# 55| getElement(1): [ConcreteVarDecl] a +# 55| Type = Int +# 55| getElement(2): [ConcreteVarDecl] b +# 55| Type = Int +# 55| getElement(3): [ConcreteVarDecl] c +# 55| Type = Int +# 57| getElement(4): [IfStmt] if ... then { ... } +# 57| getCondition(): [StmtCondition] StmtCondition +# 57| getElement(0): [ConditionElement] let ...? = ... +# 57| getPattern(): [OptionalSomePattern] let ...? +# 57| getSubPattern(): [TuplePattern] (...) +# 57| getElement(0): [NamedPattern] a +# 57| getElement(1): [NamedPattern] b +# 57| getElement(2): [NamedPattern] c +# 57| getSubPattern().getFullyUnresolved(): [BindingPattern] let ... +# 57| getInitializer(): [CallExpr] call to ... +# 57| getFunction(): [MethodLookupExpr] .some +# 57| getBase(): [TypeExpr] Optional<(Int, Int, Int)>.Type +# 57| getTypeRepr(): [TypeRepr] Optional<(Int, Int, Int)> +# 57| getMethodRef(): [DeclRefExpr] some +# 57| getArgument(0): [Argument] : (...) +# 57| getExpr(): [TupleExpr] (...) +# 57| getElement(0): [DeclRefExpr] a +# 57| getElement(1): [DeclRefExpr] b +# 57| getElement(2): [DeclRefExpr] c +# 57| getThen(): [BraceStmt] { ... } +# 57| getElement(0): [AssignExpr] ... = ... +# 57| getDest(): [DiscardAssignmentExpr] _ +# 57| getSource(): [TupleExpr] (...) +# 57| getElement(0): [DeclRefExpr] a +# 57| getElement(1): [DeclRefExpr] c +# 58| getElement(5): [IfStmt] if ... then { ... } +# 58| getCondition(): [StmtCondition] StmtCondition +# 58| getElement(0): [ConditionElement] (...) = ... +# 58| getPattern(): [TuplePattern] (...) +# 58| getElement(0): [ExprPattern] =~ ... +# 58| getSubExpr(): [DeclRefExpr] a +# 58| getElement(1): [NamedPattern] b +# 58| getElement(1).getFullyUnresolved(): [BindingPattern] let ... +# 58| getElement(2): [NamedPattern] c +# 58| getElement(2).getFullyUnresolved(): [BindingPattern] let ... +# 58| getInitializer(): [TupleExpr] (...) +# 58| getElement(0): [DeclRefExpr] a +# 58| getElement(1): [DeclRefExpr] b +# 58| getElement(2): [DeclRefExpr] c +# 58| getThen(): [BraceStmt] { ... } +# 58| getElement(0): [AssignExpr] ... = ... +# 58| getDest(): [DiscardAssignmentExpr] _ +# 58| getSource(): [DeclRefExpr] b +# 58| getSource().getFullyConverted(): [ParenExpr] (...) +# 60| getElement(6): [SwitchStmt] switch a { ... } +# 60| getExpr(): [DeclRefExpr] a +# 61| getCase(0): [CaseStmt] case ... +# 61| getBody(): [BraceStmt] { ... } +# 61| getElement(0): [StringLiteralExpr] equals c +# 61| getLabel(0): [CaseLabelItem] =~ ... +# 61| getPattern(): [ExprPattern] =~ ... +# 61| getSubExpr(): [DeclRefExpr] c +# 62| getCase(1): [CaseStmt] case ... +# 62| getBody(): [BraceStmt] { ... } +# 62| getElement(0): [StringLiteralExpr] binds c +# 62| getLabel(0): [CaseLabelItem] c +# 62| getPattern(): [NamedPattern] c +# 62| getPattern().getFullyUnresolved(): [BindingPattern] let ... +# 63| getCase(2): [CaseStmt] case ... +# 63| getBody(): [BraceStmt] { ... } +# 63| getElement(0): [StringLiteralExpr] default +# 63| getLabel(0): [CaseLabelItem] _ +# 63| getPattern(): [AnyPattern] _ +# 57| [ConcreteVarDecl] a +# 57| Type = Int +# 57| [ConcreteVarDecl] c +# 57| Type = Int +# 58| [ConcreteVarDecl] b +# 58| Type = Int +# 62| [ConcreteVarDecl] c +# 62| Type = Int +# 67| [ConcreteFuncDecl] source() +# 67| InterfaceType = () -> Int +# 67| getBody(): [BraceStmt] { ... } +# 67| getElement(0): [ReturnStmt] return ... +# 67| getResult(): [IntegerLiteralExpr] 0 +# 68| [ConcreteFuncDecl] sink(arg:) +# 68| InterfaceType = (Int) -> () +# 68| getParam(0): [ParamDecl] arg +# 68| Type = Int +# 68| getBody(): [BraceStmt] { ... } +# 70| [EnumDecl] MyEnum +# 71| getMember(0): [EnumCaseDecl] case ... +# 71| getMember(1): [EnumElementDecl] myNone +# 72| getMember(2): [EnumCaseDecl] case ... +# 72| getMember(3): [EnumElementDecl] mySingle +# 72| getParam(0): [ParamDecl] _ +# 72| Type = Int +# 73| getMember(4): [EnumCaseDecl] case ... +# 73| getMember(5): [EnumElementDecl] myPair +# 73| getParam(0): [ParamDecl] _ +# 73| Type = Int +# 73| getParam(1): [ParamDecl] _ +# 73| Type = Int +# 74| getMember(6): [EnumCaseDecl] case ... +# 74| getMember(7): [EnumElementDecl] myCons +# 74| getParam(0): [ParamDecl] _ +# 74| Type = Int +# 74| getParam(1): [ParamDecl] _ +# 74| Type = MyEnum +# 77| [ConcreteFuncDecl] test_enums() +# 77| InterfaceType = () -> () +# 77| getBody(): [BraceStmt] { ... } +# 78| getElement(0): [PatternBindingDecl] var ... = ... +# 78| getInit(0): [MethodLookupExpr] .myNone +# 78| getBase(): [TypeExpr] MyEnum.Type +# 78| getTypeRepr(): [TypeRepr] MyEnum +# 78| getMethodRef(): [DeclRefExpr] myNone +# 78| getPattern(0): [TypedPattern] ... as ... +# 78| getSubPattern(): [NamedPattern] a +# 78| getTypeRepr(): [TypeRepr] MyEnum +# 78| getElement(1): [ConcreteVarDecl] a +# 78| Type = MyEnum +# 80| getElement(2): [SwitchStmt] switch a { ... } +# 80| getExpr(): [DeclRefExpr] a +# 80| getExpr().getFullyConverted(): [LoadExpr] (MyEnum) ... +# 81| getCase(0): [CaseStmt] case ... +# 82| getBody(): [BraceStmt] { ... } +# 82| getElement(0): [TupleExpr] (...) +# 81| getLabel(0): [CaseLabelItem] .myNone +# 81| getPattern(): [EnumElementPattern] .myNone +# 83| getCase(1): [CaseStmt] case ... +# 84| getBody(): [BraceStmt] { ... } +# 84| getElement(0): [CallExpr] call to sink(arg:) +# 84| getFunction(): [DeclRefExpr] sink(arg:) +# 84| getArgument(0): [Argument] arg: a +# 84| getExpr(): [DeclRefExpr] a +# 83| getLabel(0): [CaseLabelItem] .mySingle(...) +# 83| getPattern(): [EnumElementPattern] .mySingle(...) +# 83| getSubPattern(): [NamedPattern] a +# 83| getSubPattern().getFullyUnresolved(): [ParenPattern] (...) +# 83| getImmediateSubPattern(): [BindingPattern] let ... +# 85| getCase(2): [CaseStmt] case ... +# 86| getBody(): [BraceStmt] { ... } +# 86| getElement(0): [CallExpr] call to sink(arg:) +# 86| getFunction(): [DeclRefExpr] sink(arg:) +# 86| getArgument(0): [Argument] arg: a +# 86| getExpr(): [DeclRefExpr] a +# 87| getElement(1): [CallExpr] call to sink(arg:) +# 87| getFunction(): [DeclRefExpr] sink(arg:) +# 87| getArgument(0): [Argument] arg: b +# 87| getExpr(): [DeclRefExpr] b +# 85| getLabel(0): [CaseLabelItem] .myPair(...) +# 85| getPattern(): [EnumElementPattern] .myPair(...) +# 85| getSubPattern(): [TuplePattern] (...) +# 85| getElement(0): [NamedPattern] a +# 85| getElement(0).getFullyUnresolved(): [BindingPattern] let ... +# 85| getElement(1): [NamedPattern] b +# 85| getElement(1).getFullyUnresolved(): [BindingPattern] let ... +# 88| getCase(3): [CaseStmt] case ... +# 89| getBody(): [BraceStmt] { ... } +# 89| getElement(0): [CallExpr] call to sink(arg:) +# 89| getFunction(): [DeclRefExpr] sink(arg:) +# 89| getArgument(0): [Argument] arg: a +# 89| getExpr(): [DeclRefExpr] a +# 88| getLabel(0): [CaseLabelItem] .myCons(...) +# 88| getPattern(): [EnumElementPattern] .myCons(...) +# 88| getSubPattern(): [TuplePattern] (...) +# 88| getElement(0): [NamedPattern] a +# 88| getElement(1): [AnyPattern] _ +# 88| getPattern().getFullyUnresolved(): [BindingPattern] let ... +# 92| getElement(3): [IfStmt] if ... then { ... } +# 92| getCondition(): [StmtCondition] StmtCondition +# 92| getElement(0): [ConditionElement] .mySingle(...) = ... +# 92| getPattern(): [EnumElementPattern] .mySingle(...) +# 92| getSubPattern(): [NamedPattern] x +# 92| getSubPattern().getFullyUnresolved(): [ParenPattern] (...) +# 92| getImmediateSubPattern(): [BindingPattern] let ... +# 92| getInitializer(): [DeclRefExpr] a +# 92| getInitializer().getFullyConverted(): [LoadExpr] (MyEnum) ... +# 92| getThen(): [BraceStmt] { ... } +# 93| getElement(0): [CallExpr] call to sink(arg:) +# 93| getFunction(): [DeclRefExpr] sink(arg:) +# 93| getArgument(0): [Argument] arg: x +# 93| getExpr(): [DeclRefExpr] x +# 95| getElement(4): [IfStmt] if ... then { ... } +# 95| getCondition(): [StmtCondition] StmtCondition +# 95| getElement(0): [ConditionElement] .myPair(...) = ... +# 95| getPattern(): [EnumElementPattern] .myPair(...) +# 95| getSubPattern(): [TuplePattern] (...) +# 95| getElement(0): [NamedPattern] x +# 95| getElement(0).getFullyUnresolved(): [BindingPattern] let ... +# 95| getElement(1): [NamedPattern] y +# 95| getElement(1).getFullyUnresolved(): [BindingPattern] let ... +# 95| getInitializer(): [DeclRefExpr] a +# 95| getInitializer().getFullyConverted(): [LoadExpr] (MyEnum) ... +# 95| getThen(): [BraceStmt] { ... } +# 96| getElement(0): [CallExpr] call to sink(arg:) +# 96| getFunction(): [DeclRefExpr] sink(arg:) +# 96| getArgument(0): [Argument] arg: x +# 96| getExpr(): [DeclRefExpr] x +# 97| getElement(1): [CallExpr] call to sink(arg:) +# 97| getFunction(): [DeclRefExpr] sink(arg:) +# 97| getArgument(0): [Argument] arg: y +# 97| getExpr(): [DeclRefExpr] y +# 100| getElement(5): [AssignExpr] ... = ... +# 100| getDest(): [DeclRefExpr] a +# 100| getSource(): [CallExpr] call to ... +# 100| getFunction(): [MethodLookupExpr] .mySingle +# 100| getBase(): [TypeExpr] MyEnum.Type +# 100| getTypeRepr(): [TypeRepr] MyEnum +# 100| getMethodRef(): [DeclRefExpr] mySingle +# 100| getArgument(0): [Argument] : call to source() +# 100| getExpr(): [CallExpr] call to source() +# 100| getFunction(): [DeclRefExpr] source() +# 102| getElement(6): [SwitchStmt] switch a { ... } +# 102| getExpr(): [DeclRefExpr] a +# 102| getExpr().getFullyConverted(): [LoadExpr] (MyEnum) ... +# 103| getCase(0): [CaseStmt] case ... +# 104| getBody(): [BraceStmt] { ... } +# 104| getElement(0): [TupleExpr] (...) +# 103| getLabel(0): [CaseLabelItem] .myNone +# 103| getPattern(): [EnumElementPattern] .myNone +# 105| getCase(1): [CaseStmt] case ... +# 106| getBody(): [BraceStmt] { ... } +# 106| getElement(0): [CallExpr] call to sink(arg:) +# 106| getFunction(): [DeclRefExpr] sink(arg:) +# 106| getArgument(0): [Argument] arg: a +# 106| getExpr(): [DeclRefExpr] a +# 105| getLabel(0): [CaseLabelItem] .mySingle(...) +# 105| getPattern(): [EnumElementPattern] .mySingle(...) +# 105| getSubPattern(): [NamedPattern] a +# 105| getSubPattern().getFullyUnresolved(): [ParenPattern] (...) +# 105| getImmediateSubPattern(): [BindingPattern] let ... +# 107| getCase(2): [CaseStmt] case ... +# 108| getBody(): [BraceStmt] { ... } +# 108| getElement(0): [CallExpr] call to sink(arg:) +# 108| getFunction(): [DeclRefExpr] sink(arg:) +# 108| getArgument(0): [Argument] arg: a +# 108| getExpr(): [DeclRefExpr] a +# 109| getElement(1): [CallExpr] call to sink(arg:) +# 109| getFunction(): [DeclRefExpr] sink(arg:) +# 109| getArgument(0): [Argument] arg: b +# 109| getExpr(): [DeclRefExpr] b +# 107| getLabel(0): [CaseLabelItem] .myPair(...) +# 107| getPattern(): [EnumElementPattern] .myPair(...) +# 107| getSubPattern(): [TuplePattern] (...) +# 107| getElement(0): [NamedPattern] a +# 107| getElement(0).getFullyUnresolved(): [BindingPattern] let ... +# 107| getElement(1): [NamedPattern] b +# 107| getElement(1).getFullyUnresolved(): [BindingPattern] let ... +# 110| getCase(3): [CaseStmt] case ... +# 111| getBody(): [BraceStmt] { ... } +# 111| getElement(0): [CallExpr] call to sink(arg:) +# 111| getFunction(): [DeclRefExpr] sink(arg:) +# 111| getArgument(0): [Argument] arg: a +# 111| getExpr(): [DeclRefExpr] a +# 110| getLabel(0): [CaseLabelItem] .myCons(...) +# 110| getPattern(): [EnumElementPattern] .myCons(...) +# 110| getSubPattern(): [TuplePattern] (...) +# 110| getElement(0): [NamedPattern] a +# 110| getElement(1): [AnyPattern] _ +# 110| getPattern().getFullyUnresolved(): [BindingPattern] let ... +# 114| getElement(7): [IfStmt] if ... then { ... } +# 114| getCondition(): [StmtCondition] StmtCondition +# 114| getElement(0): [ConditionElement] .mySingle(...) = ... +# 114| getPattern(): [EnumElementPattern] .mySingle(...) +# 114| getSubPattern(): [NamedPattern] x +# 114| getSubPattern().getFullyUnresolved(): [ParenPattern] (...) +# 114| getImmediateSubPattern(): [BindingPattern] let ... +# 114| getInitializer(): [DeclRefExpr] a +# 114| getInitializer().getFullyConverted(): [LoadExpr] (MyEnum) ... +# 114| getThen(): [BraceStmt] { ... } +# 115| getElement(0): [CallExpr] call to sink(arg:) +# 115| getFunction(): [DeclRefExpr] sink(arg:) +# 115| getArgument(0): [Argument] arg: x +# 115| getExpr(): [DeclRefExpr] x +# 117| getElement(8): [IfStmt] if ... then { ... } +# 117| getCondition(): [StmtCondition] StmtCondition +# 117| getElement(0): [ConditionElement] .myPair(...) = ... +# 117| getPattern(): [EnumElementPattern] .myPair(...) +# 117| getSubPattern(): [TuplePattern] (...) +# 117| getElement(0): [NamedPattern] x +# 117| getElement(0).getFullyUnresolved(): [BindingPattern] let ... +# 117| getElement(1): [NamedPattern] y +# 117| getElement(1).getFullyUnresolved(): [BindingPattern] let ... +# 117| getInitializer(): [DeclRefExpr] a +# 117| getInitializer().getFullyConverted(): [LoadExpr] (MyEnum) ... +# 117| getThen(): [BraceStmt] { ... } +# 118| getElement(0): [CallExpr] call to sink(arg:) +# 118| getFunction(): [DeclRefExpr] sink(arg:) +# 118| getArgument(0): [Argument] arg: x +# 118| getExpr(): [DeclRefExpr] x +# 119| getElement(1): [CallExpr] call to sink(arg:) +# 119| getFunction(): [DeclRefExpr] sink(arg:) +# 119| getArgument(0): [Argument] arg: y +# 119| getExpr(): [DeclRefExpr] y +# 122| getElement(9): [AssignExpr] ... = ... +# 122| getDest(): [DeclRefExpr] a +# 122| getSource(): [CallExpr] call to ... +# 122| getFunction(): [MethodLookupExpr] .myPair +# 122| getBase(): [TypeExpr] MyEnum.Type +# 122| getTypeRepr(): [TypeRepr] MyEnum +# 122| getMethodRef(): [DeclRefExpr] myPair +# 122| getArgument(0): [Argument] : 0 +# 122| getExpr(): [IntegerLiteralExpr] 0 +# 122| getArgument(1): [Argument] : call to source() +# 122| getExpr(): [CallExpr] call to source() +# 122| getFunction(): [DeclRefExpr] source() +# 124| getElement(10): [SwitchStmt] switch a { ... } +# 124| getExpr(): [DeclRefExpr] a +# 124| getExpr().getFullyConverted(): [LoadExpr] (MyEnum) ... +# 125| getCase(0): [CaseStmt] case ... +# 126| getBody(): [BraceStmt] { ... } +# 126| getElement(0): [TupleExpr] (...) +# 125| getLabel(0): [CaseLabelItem] .myNone +# 125| getPattern(): [EnumElementPattern] .myNone +# 127| getCase(1): [CaseStmt] case ... +# 128| getBody(): [BraceStmt] { ... } +# 128| getElement(0): [CallExpr] call to sink(arg:) +# 128| getFunction(): [DeclRefExpr] sink(arg:) +# 128| getArgument(0): [Argument] arg: a +# 128| getExpr(): [DeclRefExpr] a +# 127| getLabel(0): [CaseLabelItem] .mySingle(...) +# 127| getPattern(): [EnumElementPattern] .mySingle(...) +# 127| getSubPattern(): [NamedPattern] a +# 127| getSubPattern().getFullyUnresolved(): [ParenPattern] (...) +# 127| getImmediateSubPattern(): [BindingPattern] let ... +# 129| getCase(2): [CaseStmt] case ... +# 130| getBody(): [BraceStmt] { ... } +# 130| getElement(0): [CallExpr] call to sink(arg:) +# 130| getFunction(): [DeclRefExpr] sink(arg:) +# 130| getArgument(0): [Argument] arg: a +# 130| getExpr(): [DeclRefExpr] a +# 131| getElement(1): [CallExpr] call to sink(arg:) +# 131| getFunction(): [DeclRefExpr] sink(arg:) +# 131| getArgument(0): [Argument] arg: b +# 131| getExpr(): [DeclRefExpr] b +# 129| getLabel(0): [CaseLabelItem] .myPair(...) +# 129| getPattern(): [EnumElementPattern] .myPair(...) +# 129| getSubPattern(): [TuplePattern] (...) +# 129| getElement(0): [NamedPattern] a +# 129| getElement(0).getFullyUnresolved(): [BindingPattern] let ... +# 129| getElement(1): [NamedPattern] b +# 129| getElement(1).getFullyUnresolved(): [BindingPattern] let ... +# 132| getCase(3): [CaseStmt] case ... +# 133| getBody(): [BraceStmt] { ... } +# 133| getElement(0): [CallExpr] call to sink(arg:) +# 133| getFunction(): [DeclRefExpr] sink(arg:) +# 133| getArgument(0): [Argument] arg: a +# 133| getExpr(): [DeclRefExpr] a +# 132| getLabel(0): [CaseLabelItem] .myCons(...) +# 132| getPattern(): [EnumElementPattern] .myCons(...) +# 132| getSubPattern(): [TuplePattern] (...) +# 132| getElement(0): [NamedPattern] a +# 132| getElement(1): [AnyPattern] _ +# 132| getPattern().getFullyUnresolved(): [BindingPattern] let ... +# 136| getElement(11): [IfStmt] if ... then { ... } +# 136| getCondition(): [StmtCondition] StmtCondition +# 136| getElement(0): [ConditionElement] .mySingle(...) = ... +# 136| getPattern(): [EnumElementPattern] .mySingle(...) +# 136| getSubPattern(): [NamedPattern] x +# 136| getSubPattern().getFullyUnresolved(): [ParenPattern] (...) +# 136| getImmediateSubPattern(): [BindingPattern] let ... +# 136| getInitializer(): [DeclRefExpr] a +# 136| getInitializer().getFullyConverted(): [LoadExpr] (MyEnum) ... +# 136| getThen(): [BraceStmt] { ... } +# 137| getElement(0): [CallExpr] call to sink(arg:) +# 137| getFunction(): [DeclRefExpr] sink(arg:) +# 137| getArgument(0): [Argument] arg: x +# 137| getExpr(): [DeclRefExpr] x +# 139| getElement(12): [IfStmt] if ... then { ... } +# 139| getCondition(): [StmtCondition] StmtCondition +# 139| getElement(0): [ConditionElement] .myPair(...) = ... +# 139| getPattern(): [EnumElementPattern] .myPair(...) +# 139| getSubPattern(): [TuplePattern] (...) +# 139| getElement(0): [NamedPattern] x +# 139| getElement(0).getFullyUnresolved(): [BindingPattern] let ... +# 139| getElement(1): [NamedPattern] y +# 139| getElement(1).getFullyUnresolved(): [BindingPattern] let ... +# 139| getInitializer(): [DeclRefExpr] a +# 139| getInitializer().getFullyConverted(): [LoadExpr] (MyEnum) ... +# 139| getThen(): [BraceStmt] { ... } +# 140| getElement(0): [CallExpr] call to sink(arg:) +# 140| getFunction(): [DeclRefExpr] sink(arg:) +# 140| getArgument(0): [Argument] arg: x +# 140| getExpr(): [DeclRefExpr] x +# 141| getElement(1): [CallExpr] call to sink(arg:) +# 141| getFunction(): [DeclRefExpr] sink(arg:) +# 141| getArgument(0): [Argument] arg: y +# 141| getExpr(): [DeclRefExpr] y +# 144| getElement(13): [PatternBindingDecl] var ... = ... +# 144| getInit(0): [CallExpr] call to ... +# 144| getFunction(): [MethodLookupExpr] .myCons +# 144| getBase(): [TypeExpr] MyEnum.Type +# 144| getTypeRepr(): [TypeRepr] MyEnum +# 144| getMethodRef(): [DeclRefExpr] myCons +# 144| getArgument(0): [Argument] : 42 +# 144| getExpr(): [IntegerLiteralExpr] 42 +# 144| getArgument(1): [Argument] : a +# 144| getExpr(): [DeclRefExpr] a +# 144| getExpr().getFullyConverted(): [LoadExpr] (MyEnum) ... +# 144| getPattern(0): [TypedPattern] ... as ... +# 144| getSubPattern(): [NamedPattern] b +# 144| getTypeRepr(): [TypeRepr] MyEnum +# 144| getElement(14): [ConcreteVarDecl] b +# 144| Type = MyEnum +# 146| getElement(15): [SwitchStmt] switch b { ... } +# 146| getExpr(): [DeclRefExpr] b +# 147| getCase(0): [CaseStmt] case ... +# 148| getBody(): [BraceStmt] { ... } +# 148| getElement(0): [TupleExpr] (...) +# 147| getLabel(0): [CaseLabelItem] .myNone +# 147| getPattern(): [EnumElementPattern] .myNone +# 149| getCase(1): [CaseStmt] case ... +# 150| getBody(): [BraceStmt] { ... } +# 150| getElement(0): [CallExpr] call to sink(arg:) +# 150| getFunction(): [DeclRefExpr] sink(arg:) +# 150| getArgument(0): [Argument] arg: a +# 150| getExpr(): [DeclRefExpr] a +# 149| getLabel(0): [CaseLabelItem] .mySingle(...) +# 149| getPattern(): [EnumElementPattern] .mySingle(...) +# 149| getSubPattern(): [NamedPattern] a +# 149| getSubPattern().getFullyUnresolved(): [ParenPattern] (...) +# 149| getImmediateSubPattern(): [BindingPattern] let ... +# 151| getCase(2): [CaseStmt] case ... +# 152| getBody(): [BraceStmt] { ... } +# 152| getElement(0): [CallExpr] call to sink(arg:) +# 152| getFunction(): [DeclRefExpr] sink(arg:) +# 152| getArgument(0): [Argument] arg: a +# 152| getExpr(): [DeclRefExpr] a +# 153| getElement(1): [CallExpr] call to sink(arg:) +# 153| getFunction(): [DeclRefExpr] sink(arg:) +# 153| getArgument(0): [Argument] arg: b +# 153| getExpr(): [DeclRefExpr] b +# 151| getLabel(0): [CaseLabelItem] .myPair(...) +# 151| getPattern(): [EnumElementPattern] .myPair(...) +# 151| getSubPattern(): [TuplePattern] (...) +# 151| getElement(0): [NamedPattern] a +# 151| getElement(0).getFullyUnresolved(): [BindingPattern] let ... +# 151| getElement(1): [NamedPattern] b +# 151| getElement(1).getFullyUnresolved(): [BindingPattern] let ... +# 154| getCase(3): [CaseStmt] case ... +# 155| getBody(): [BraceStmt] { ... } +# 155| getElement(0): [CallExpr] call to sink(arg:) +# 155| getFunction(): [DeclRefExpr] sink(arg:) +# 155| getArgument(0): [Argument] arg: a +# 155| getExpr(): [DeclRefExpr] a +# 156| getElement(1): [CallExpr] call to sink(arg:) +# 156| getFunction(): [DeclRefExpr] sink(arg:) +# 156| getArgument(0): [Argument] arg: b +# 156| getExpr(): [DeclRefExpr] b +# 157| getElement(2): [CallExpr] call to sink(arg:) +# 157| getFunction(): [DeclRefExpr] sink(arg:) +# 157| getArgument(0): [Argument] arg: c +# 157| getExpr(): [DeclRefExpr] c +# 154| getLabel(0): [CaseLabelItem] .myCons(...) +# 154| getPattern(): [EnumElementPattern] .myCons(...) +# 154| getSubPattern(): [TuplePattern] (...) +# 154| getElement(0): [NamedPattern] a +# 154| getElement(1): [EnumElementPattern] .myPair(...) +# 154| getSubPattern(): [TuplePattern] (...) +# 154| getElement(0): [NamedPattern] b +# 154| getElement(1): [NamedPattern] c +# 154| getPattern().getFullyUnresolved(): [BindingPattern] let ... +# 158| getCase(4): [CaseStmt] case ... +# 159| getBody(): [BraceStmt] { ... } +# 159| getElement(0): [CallExpr] call to sink(arg:) +# 159| getFunction(): [DeclRefExpr] sink(arg:) +# 159| getArgument(0): [Argument] arg: a +# 159| getExpr(): [DeclRefExpr] a +# 158| getLabel(0): [CaseLabelItem] .myCons(...) +# 158| getPattern(): [EnumElementPattern] .myCons(...) +# 158| getSubPattern(): [TuplePattern] (...) +# 158| getElement(0): [NamedPattern] a +# 158| getElement(1): [AnyPattern] _ +# 158| getPattern().getFullyUnresolved(): [BindingPattern] let ... +# 162| getElement(16): [IfStmt] if ... then { ... } +# 162| getCondition(): [StmtCondition] StmtCondition +# 162| getElement(0): [ConditionElement] .mySingle(...) = ... +# 162| getPattern(): [EnumElementPattern] .mySingle(...) +# 162| getSubPattern(): [NamedPattern] x +# 162| getSubPattern().getFullyUnresolved(): [ParenPattern] (...) +# 162| getImmediateSubPattern(): [BindingPattern] let ... +# 162| getInitializer(): [CallExpr] call to ... +# 162| getFunction(): [MethodLookupExpr] .myPair +# 162| getBase(): [TypeExpr] MyEnum.Type +# 162| getTypeRepr(): [TypeRepr] MyEnum +# 162| getMethodRef(): [DeclRefExpr] myPair +# 162| getArgument(0): [Argument] : call to source() +# 162| getExpr(): [CallExpr] call to source() +# 162| getFunction(): [DeclRefExpr] source() +# 162| getArgument(1): [Argument] : 0 +# 162| getExpr(): [IntegerLiteralExpr] 0 +# 162| getThen(): [BraceStmt] { ... } +# 163| getElement(0): [CallExpr] call to sink(arg:) +# 163| getFunction(): [DeclRefExpr] sink(arg:) +# 163| getArgument(0): [Argument] arg: x +# 163| getExpr(): [DeclRefExpr] x +# 165| getElement(17): [IfStmt] if ... then { ... } +# 165| getCondition(): [StmtCondition] StmtCondition +# 165| getElement(0): [ConditionElement] .myPair(...) = ... +# 165| getPattern(): [EnumElementPattern] .myPair(...) +# 165| getSubPattern(): [TuplePattern] (...) +# 165| getElement(0): [NamedPattern] x +# 165| getElement(0).getFullyUnresolved(): [BindingPattern] let ... +# 165| getElement(1): [NamedPattern] y +# 165| getElement(1).getFullyUnresolved(): [BindingPattern] let ... +# 165| getInitializer(): [CallExpr] call to ... +# 165| getFunction(): [MethodLookupExpr] .myPair +# 165| getBase(): [TypeExpr] MyEnum.Type +# 165| getTypeRepr(): [TypeRepr] MyEnum +# 165| getMethodRef(): [DeclRefExpr] myPair +# 165| getArgument(0): [Argument] : call to source() +# 165| getExpr(): [CallExpr] call to source() +# 165| getFunction(): [DeclRefExpr] source() +# 165| getArgument(1): [Argument] : 0 +# 165| getExpr(): [IntegerLiteralExpr] 0 +# 165| getThen(): [BraceStmt] { ... } +# 166| getElement(0): [CallExpr] call to sink(arg:) +# 166| getFunction(): [DeclRefExpr] sink(arg:) +# 166| getArgument(0): [Argument] arg: x +# 166| getExpr(): [DeclRefExpr] x +# 167| getElement(1): [CallExpr] call to sink(arg:) +# 167| getFunction(): [DeclRefExpr] sink(arg:) +# 167| getArgument(0): [Argument] arg: y +# 167| getExpr(): [DeclRefExpr] y +# 169| getElement(18): [IfStmt] if ... then { ... } +# 169| getCondition(): [StmtCondition] StmtCondition +# 169| getElement(0): [ConditionElement] .myCons(...) = ... +# 169| getPattern(): [EnumElementPattern] .myCons(...) +# 169| getSubPattern(): [TuplePattern] (...) +# 169| getElement(0): [AnyPattern] _ +# 169| getElement(1): [EnumElementPattern] .myPair(...) +# 169| getSubPattern(): [TuplePattern] (...) +# 169| getElement(0): [AnyPattern] _ +# 169| getElement(1): [NamedPattern] c +# 169| getPattern().getFullyUnresolved(): [BindingPattern] let ... +# 169| getInitializer(): [DeclRefExpr] b +# 169| getThen(): [BraceStmt] { ... } +# 170| getElement(0): [CallExpr] call to sink(arg:) +# 170| getFunction(): [DeclRefExpr] sink(arg:) +# 170| getArgument(0): [Argument] arg: c +# 170| getExpr(): [DeclRefExpr] c +# 173| getElement(19): [SwitchStmt] switch (...) { ... } +# 173| getExpr(): [TupleExpr] (...) +# 173| getElement(0): [DeclRefExpr] a +# 173| getElement(0).getFullyConverted(): [LoadExpr] (MyEnum) ... +# 173| getElement(1): [DeclRefExpr] b +# 174| getCase(0): [CaseStmt] case ... +# 175| getBody(): [BraceStmt] { ... } +# 175| getElement(0): [CallExpr] call to sink(arg:) +# 175| getFunction(): [DeclRefExpr] sink(arg:) +# 175| getArgument(0): [Argument] arg: a +# 175| getExpr(): [DeclRefExpr] a +# 176| getElement(1): [CallExpr] call to sink(arg:) +# 176| getFunction(): [DeclRefExpr] sink(arg:) +# 176| getArgument(0): [Argument] arg: b +# 176| getExpr(): [DeclRefExpr] b +# 177| getElement(2): [CallExpr] call to sink(arg:) +# 177| getFunction(): [DeclRefExpr] sink(arg:) +# 177| getArgument(0): [Argument] arg: c +# 177| getExpr(): [DeclRefExpr] c +# 178| getElement(3): [CallExpr] call to sink(arg:) +# 178| getFunction(): [DeclRefExpr] sink(arg:) +# 178| getArgument(0): [Argument] arg: d +# 178| getExpr(): [DeclRefExpr] d +# 179| getElement(4): [CallExpr] call to sink(arg:) +# 179| getFunction(): [DeclRefExpr] sink(arg:) +# 179| getArgument(0): [Argument] arg: e +# 179| getExpr(): [DeclRefExpr] e +# 174| getLabel(0): [CaseLabelItem] (...) +# 174| getPattern(): [TuplePattern] (...) +# 174| getElement(0): [EnumElementPattern] .myPair(...) +# 174| getSubPattern(): [TuplePattern] (...) +# 174| getElement(0): [NamedPattern] a +# 174| getElement(1): [NamedPattern] b +# 174| getElement(1): [EnumElementPattern] .myCons(...) +# 174| getSubPattern(): [TuplePattern] (...) +# 174| getElement(0): [NamedPattern] c +# 174| getElement(1): [EnumElementPattern] .myPair(...) +# 174| getSubPattern(): [TuplePattern] (...) +# 174| getElement(0): [NamedPattern] d +# 174| getElement(1): [NamedPattern] e +# 174| getPattern().getFullyUnresolved(): [BindingPattern] let ... +# 180| getCase(1): [CaseStmt] case ... +# 181| getBody(): [BraceStmt] { ... } +# 181| getElement(0): [TupleExpr] (...) +# 180| getLabel(0): [CaseLabelItem] _ +# 180| getPattern(): [AnyPattern] _ +# 83| [ConcreteVarDecl] a +# 83| Type = (Int) +# 85| [ConcreteVarDecl] a +# 85| Type = Int +# 85| [ConcreteVarDecl] b +# 85| Type = Int +# 88| [ConcreteVarDecl] a +# 88| Type = Int +# 92| [ConcreteVarDecl] x +# 92| Type = (Int) +# 95| [ConcreteVarDecl] x +# 95| Type = Int +# 95| [ConcreteVarDecl] y +# 95| Type = Int +# 105| [ConcreteVarDecl] a +# 105| Type = (Int) +# 107| [ConcreteVarDecl] a +# 107| Type = Int +# 107| [ConcreteVarDecl] b +# 107| Type = Int +# 110| [ConcreteVarDecl] a +# 110| Type = Int +# 114| [ConcreteVarDecl] x +# 114| Type = (Int) +# 117| [ConcreteVarDecl] x +# 117| Type = Int +# 117| [ConcreteVarDecl] y +# 117| Type = Int +# 127| [ConcreteVarDecl] a +# 127| Type = (Int) +# 129| [ConcreteVarDecl] a +# 129| Type = Int +# 129| [ConcreteVarDecl] b +# 129| Type = Int +# 132| [ConcreteVarDecl] a +# 132| Type = Int +# 136| [ConcreteVarDecl] x +# 136| Type = (Int) +# 139| [ConcreteVarDecl] x +# 139| Type = Int +# 139| [ConcreteVarDecl] y +# 139| Type = Int +# 149| [ConcreteVarDecl] a +# 149| Type = (Int) +# 151| [ConcreteVarDecl] a +# 151| Type = Int +# 151| [ConcreteVarDecl] b +# 151| Type = Int +# 154| [ConcreteVarDecl] a +# 154| Type = Int +# 154| [ConcreteVarDecl] b +# 154| Type = Int +# 154| [ConcreteVarDecl] c +# 154| Type = Int +# 158| [ConcreteVarDecl] a +# 158| Type = Int +# 162| [ConcreteVarDecl] x +# 162| Type = (Int) +# 165| [ConcreteVarDecl] x +# 165| Type = Int +# 165| [ConcreteVarDecl] y +# 165| Type = Int +# 169| [ConcreteVarDecl] c +# 169| Type = Int +# 174| [ConcreteVarDecl] a +# 174| Type = Int +# 174| [ConcreteVarDecl] b +# 174| Type = Int +# 174| [ConcreteVarDecl] c +# 174| Type = Int +# 174| [ConcreteVarDecl] d +# 174| Type = Int +# 174| [ConcreteVarDecl] e +# 174| Type = Int statements.swift: # 1| [ConcreteFuncDecl] loop() # 1| InterfaceType = () -> () @@ -5621,9 +6293,9 @@ statements.swift: # 22| getExpr(): [DefaultArgumentExpr] default separator # 22| getArgument(2): [Argument] terminator: default terminator # 22| getExpr(): [DefaultArgumentExpr] default terminator -# 21| getLabel(0): [CaseLabelItem] let ... -# 21| getPattern(): [BindingPattern] let ... -# 21| getSubPattern(): [NamedPattern] error +# 21| getLabel(0): [CaseLabelItem] error +# 21| getPattern(): [NamedPattern] error +# 21| getPattern().getFullyUnresolved(): [BindingPattern] let ... # 25| getElement(7): [DoCatchStmt] do { ... } catch { ... } # 25| getBody(): [BraceStmt] { ... } # 26| getElement(0): [TryExpr] try ... @@ -5660,9 +6332,9 @@ statements.swift: # 30| getExpr(): [DefaultArgumentExpr] default separator # 30| getArgument(2): [Argument] terminator: default terminator # 30| getExpr(): [DefaultArgumentExpr] default terminator -# 29| getLabel(0): [CaseLabelItem] let ... -# 29| getPattern(): [BindingPattern] let ... -# 29| getSubPattern(): [NamedPattern] error +# 29| getLabel(0): [CaseLabelItem] error +# 29| getPattern(): [NamedPattern] error +# 29| getPattern().getFullyUnresolved(): [BindingPattern] let ... # 2| [ConcreteVarDecl] i # 2| Type = Int # 21| [ConcreteVarDecl] error @@ -5884,10 +6556,10 @@ statements.swift: # 65| getBody(): [BraceStmt] { ... } # 65| getElement(0): [IfStmt] if ... then { ... } # 65| getCondition(): [StmtCondition] StmtCondition -# 65| getElement(0): [ConditionElement] let ... = ... -# 65| getPattern(): [BindingPattern] let ... -# 65| getSubPattern(): [OptionalSomePattern] let ...? -# 65| getSubPattern(): [NamedPattern] xx +# 65| getElement(0): [ConditionElement] let ...? = ... +# 65| getPattern(): [OptionalSomePattern] let ...? +# 65| getSubPattern(): [NamedPattern] xx +# 65| getPattern().getFullyUnresolved(): [BindingPattern] let ... # 65| getInitializer(): [DeclRefExpr] x # 65| getThen(): [BraceStmt] { ... } # 67| [TopLevelCodeDecl] { ... } diff --git a/swift/ql/test/library-tests/ast/patterns.swift b/swift/ql/test/library-tests/ast/patterns.swift index ebc369310c9..95f3bfb17b6 100644 --- a/swift/ql/test/library-tests/ast/patterns.swift +++ b/swift/ql/test/library-tests/ast/patterns.swift @@ -50,3 +50,134 @@ func switch_patterns() { case false: "false" } } + +func bound_and_unbound() { + let a = 1, b = 2, c: Int = 3 + + if let (a, b, c) = Optional.some((a, b, c)) { _ = (a, c) } + if case (a, let b, let c) = (a, b, c) { _ = (b) } + + switch a { + case c: "equals c" + case let c: "binds c" + default: "default" + } +} + +func source() -> Int { 0 } +func sink(arg: Int) { } + +indirect enum MyEnum { + case myNone + case mySingle(Int) + case myPair(Int, Int) + case myCons(Int, MyEnum) +} + +func test_enums() { + var a : MyEnum = .myNone + + switch a { + case .myNone: + () + case .mySingle(let a): + sink(arg: a) + case .myPair(let a, let b): + sink(arg: a) + sink(arg: b) + case let .myCons(a, _): + sink(arg: a) + } + + if case .mySingle(let x) = a { + sink(arg: x) + } + if case .myPair(let x, let y) = a { + sink(arg: x) + sink(arg: y) + } + + a = .mySingle(source()) + + switch a { + case .myNone: + () + case .mySingle(let a): + sink(arg: a) + case .myPair(let a, let b): + sink(arg: a) + sink(arg: b) + case let .myCons(a, _): + sink(arg: a) + } + + if case .mySingle(let x) = a { + sink(arg: x) + } + if case .myPair(let x, let y) = a { + sink(arg: x) + sink(arg: y) + } + + a = MyEnum.myPair(0, source()) + + switch a { + case .myNone: + () + case .mySingle(let a): + sink(arg: a) + case .myPair(let a, let b): + sink(arg: a) + sink(arg: b) + case let .myCons(a, _): + sink(arg: a) + } + + if case .mySingle(let x) = a { + sink(arg: x) + } + if case .myPair(let x, let y) = a { + sink(arg: x) + sink(arg: y) + } + + let b: MyEnum = .myCons(42, a) + + switch b { + case .myNone: + () + case .mySingle(let a): + sink(arg: a) + case .myPair(let a, let b): + sink(arg: a) + sink(arg: b) + case let .myCons(a, .myPair(b, c)): + sink(arg: a) + sink(arg: b) + sink(arg: c) + case let .myCons(a, _): + sink(arg: a) + } + + if case .mySingle(let x) = MyEnum.myPair(source(), 0) { + sink(arg: x) + } + if case MyEnum.myPair(let x, let y) = .myPair(source(), 0) { + sink(arg: x) + sink(arg: y) + } + if case let .myCons(_, .myPair(_, c)) = b { + sink(arg: c) + } + + switch (a, b) { + case let (.myPair(a, b), .myCons(c, .myPair(d, e))): + sink(arg: a) + sink(arg: b) + sink(arg: c) + sink(arg: d) + sink(arg: e) + default: + () + } +} diff --git a/swift/ql/test/library-tests/controlflow/graph/Cfg.expected b/swift/ql/test/library-tests/controlflow/graph/Cfg.expected index f6a98546a9b..ae67debf690 100644 --- a/swift/ql/test/library-tests/controlflow/graph/Cfg.expected +++ b/swift/ql/test/library-tests/controlflow/graph/Cfg.expected @@ -334,7 +334,10 @@ cfg.swift: #-----| -> default separator # 39| case ... -#-----| -> let ... +#-----| -> error + +# 39| error +#-----| -> error # 39| error #-----| match -> let ... @@ -342,9 +345,6 @@ cfg.swift: # 39| let ... #-----| match -> print(_:separator:terminator:) -# 39| let ... -#-----| -> error - # 40| print(_:separator:terminator:) # 40| call to print(_:separator:terminator:) diff --git a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected index b7d32099952..0eea49ff838 100644 --- a/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected +++ b/swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected @@ -1,11 +1,12 @@ edges | file://:0:0:0:0 | [summary param] this in signum() : | file://:0:0:0:0 | [summary] to write: return (return) in signum() : | +| file://:0:0:0:0 | [summary param] this in signum() [some:0] : | file://:0:0:0:0 | [summary] to write: return (return) in signum() [some:0] : | | file://:0:0:0:0 | self [a, x] : | file://:0:0:0:0 | .a [x] : | | file://:0:0:0:0 | self [str] : | file://:0:0:0:0 | .str : | -| file://:0:0:0:0 | self [x] : | file://:0:0:0:0 | .x : | +| file://:0:0:0:0 | self [x, some:0] : | file://:0:0:0:0 | .x [some:0] : | | file://:0:0:0:0 | self [x] : | file://:0:0:0:0 | .x : | | file://:0:0:0:0 | value : | file://:0:0:0:0 | [post] self [x] : | -| file://:0:0:0:0 | value : | file://:0:0:0:0 | [post] self [x] : | +| file://:0:0:0:0 | value [some:0] : | file://:0:0:0:0 | [post] self [x, some:0] : | | test.swift:6:19:6:26 | call to source() : | test.swift:7:15:7:15 | t1 | | test.swift:6:19:6:26 | call to source() : | test.swift:9:15:9:15 | t1 | | test.swift:6:19:6:26 | call to source() : | test.swift:10:15:10:15 | t2 | @@ -102,9 +103,11 @@ edges | test.swift:219:13:219:15 | .a [x] : | test.swift:219:13:219:17 | .x | | test.swift:225:14:225:21 | call to source() : | test.swift:235:13:235:15 | .source_value | | test.swift:225:14:225:21 | call to source() : | test.swift:238:13:238:15 | .source_value | +| test.swift:259:12:259:19 | call to source() : | test.swift:259:12:259:19 | call to source() [some:0] : | | test.swift:259:12:259:19 | call to source() : | test.swift:263:13:263:28 | call to optionalSource() : | -| test.swift:259:12:259:19 | call to source() : | test.swift:439:13:439:28 | call to optionalSource() : | -| test.swift:259:12:259:19 | call to source() : | test.swift:466:13:466:28 | call to optionalSource() : | +| test.swift:259:12:259:19 | call to source() [some:0] : | test.swift:263:13:263:28 | call to optionalSource() [some:0] : | +| test.swift:259:12:259:19 | call to source() [some:0] : | test.swift:486:13:486:28 | call to optionalSource() [some:0] : | +| test.swift:259:12:259:19 | call to source() [some:0] : | test.swift:513:13:513:28 | call to optionalSource() [some:0] : | | test.swift:263:13:263:28 | call to optionalSource() : | test.swift:265:15:265:15 | x | | test.swift:263:13:263:28 | call to optionalSource() : | test.swift:267:15:267:16 | ...! | | test.swift:263:13:263:28 | call to optionalSource() : | test.swift:271:15:271:16 | ...? : | @@ -112,11 +115,13 @@ edges | test.swift:263:13:263:28 | call to optionalSource() : | test.swift:275:15:275:27 | ... ??(_:_:) ... | | test.swift:263:13:263:28 | call to optionalSource() : | test.swift:279:15:279:31 | ... ? ... : ... | | test.swift:263:13:263:28 | call to optionalSource() : | test.swift:280:15:280:38 | ... ? ... : ... | -| test.swift:263:13:263:28 | call to optionalSource() : | test.swift:285:19:285:19 | z | | test.swift:263:13:263:28 | call to optionalSource() : | test.swift:291:16:291:17 | ...? : | -| test.swift:263:13:263:28 | call to optionalSource() : | test.swift:300:15:300:15 | z1 | | test.swift:263:13:263:28 | call to optionalSource() : | test.swift:303:15:303:16 | ...! : | -| test.swift:263:13:263:28 | call to optionalSource() : | test.swift:307:19:307:19 | z | +| test.swift:263:13:263:28 | call to optionalSource() [some:0] : | test.swift:284:8:284:12 | let ...? [some:0] : | +| test.swift:263:13:263:28 | call to optionalSource() [some:0] : | test.swift:291:16:291:17 | ...? [some:0] : | +| test.swift:263:13:263:28 | call to optionalSource() [some:0] : | test.swift:298:11:298:15 | let ...? [some:0] : | +| test.swift:263:13:263:28 | call to optionalSource() [some:0] : | test.swift:306:13:306:24 | .some(...) [some:0] : | +| test.swift:263:13:263:28 | call to optionalSource() [some:0] : | test.swift:314:10:314:21 | .some(...) [some:0] : | | test.swift:270:15:270:22 | call to source() : | file://:0:0:0:0 | [summary param] this in signum() : | | test.swift:270:15:270:22 | call to source() : | test.swift:270:15:270:31 | call to signum() | | test.swift:271:15:271:16 | ...? : | file://:0:0:0:0 | [summary param] this in signum() : | @@ -124,69 +129,141 @@ edges | test.swift:271:15:271:25 | call to signum() : | test.swift:271:15:271:25 | OptionalEvaluationExpr | | test.swift:280:31:280:38 | call to source() : | test.swift:280:15:280:38 | ... ? ... : ... | | test.swift:282:31:282:38 | call to source() : | test.swift:282:15:282:38 | ... ? ... : ... | +| test.swift:284:8:284:12 | let ...? [some:0] : | test.swift:284:12:284:12 | z : | +| test.swift:284:12:284:12 | z : | test.swift:285:19:285:19 | z | +| test.swift:291:8:291:12 | let ...? [some:0] : | test.swift:291:12:291:12 | z : | +| test.swift:291:12:291:12 | z : | test.swift:292:19:292:19 | z | | test.swift:291:16:291:17 | ...? : | file://:0:0:0:0 | [summary param] this in signum() : | | test.swift:291:16:291:17 | ...? : | test.swift:291:16:291:26 | call to signum() : | -| test.swift:291:16:291:26 | call to signum() : | test.swift:292:19:292:19 | z | +| test.swift:291:16:291:17 | ...? [some:0] : | file://:0:0:0:0 | [summary param] this in signum() [some:0] : | +| test.swift:291:16:291:17 | ...? [some:0] : | test.swift:291:16:291:26 | call to signum() [some:0] : | +| test.swift:291:16:291:26 | call to signum() : | test.swift:291:16:291:26 | call to signum() [some:0] : | +| test.swift:291:16:291:26 | call to signum() [some:0] : | test.swift:291:8:291:12 | let ...? [some:0] : | +| test.swift:298:11:298:15 | let ...? [some:0] : | test.swift:298:15:298:15 | z1 : | +| test.swift:298:15:298:15 | z1 : | test.swift:300:15:300:15 | z1 | | test.swift:303:15:303:16 | ...! : | file://:0:0:0:0 | [summary param] this in signum() : | | test.swift:303:15:303:16 | ...! : | test.swift:303:15:303:25 | call to signum() | +| test.swift:306:13:306:24 | .some(...) [some:0] : | test.swift:306:23:306:23 | z : | +| test.swift:306:23:306:23 | z : | test.swift:307:19:307:19 | z | +| test.swift:314:10:314:21 | .some(...) [some:0] : | test.swift:314:20:314:20 | z : | +| test.swift:314:20:314:20 | z : | test.swift:315:19:315:19 | z | | test.swift:331:14:331:26 | (...) [Tuple element at index 1] : | test.swift:335:15:335:15 | t1 [Tuple element at index 1] : | | test.swift:331:18:331:25 | call to source() : | test.swift:331:14:331:26 | (...) [Tuple element at index 1] : | | test.swift:335:15:335:15 | t1 [Tuple element at index 1] : | test.swift:335:15:335:18 | .1 | | test.swift:343:5:343:5 | [post] t1 [Tuple element at index 0] : | test.swift:346:15:346:15 | t1 [Tuple element at index 0] : | | test.swift:343:12:343:19 | call to source() : | test.swift:343:5:343:5 | [post] t1 [Tuple element at index 0] : | | test.swift:346:15:346:15 | t1 [Tuple element at index 0] : | test.swift:346:15:346:18 | .0 | +| test.swift:351:14:351:45 | (...) [Tuple element at index 0] : | test.swift:353:9:353:17 | (...) [Tuple element at index 0] : | | test.swift:351:14:351:45 | (...) [Tuple element at index 0] : | test.swift:356:15:356:15 | t1 [Tuple element at index 0] : | | test.swift:351:14:351:45 | (...) [Tuple element at index 0] : | test.swift:360:15:360:15 | t2 [Tuple element at index 0] : | +| test.swift:351:14:351:45 | (...) [Tuple element at index 1] : | test.swift:353:9:353:17 | (...) [Tuple element at index 1] : | | test.swift:351:14:351:45 | (...) [Tuple element at index 1] : | test.swift:357:15:357:15 | t1 [Tuple element at index 1] : | | test.swift:351:14:351:45 | (...) [Tuple element at index 1] : | test.swift:361:15:361:15 | t2 [Tuple element at index 1] : | | test.swift:351:18:351:25 | call to source() : | test.swift:351:14:351:45 | (...) [Tuple element at index 0] : | | test.swift:351:31:351:38 | call to source() : | test.swift:351:14:351:45 | (...) [Tuple element at index 1] : | +| test.swift:353:9:353:17 | (...) [Tuple element at index 0] : | test.swift:353:10:353:10 | a : | +| test.swift:353:9:353:17 | (...) [Tuple element at index 1] : | test.swift:353:13:353:13 | b : | +| test.swift:353:10:353:10 | a : | test.swift:363:15:363:15 | a | +| test.swift:353:13:353:13 | b : | test.swift:364:15:364:15 | b | | test.swift:356:15:356:15 | t1 [Tuple element at index 0] : | test.swift:356:15:356:18 | .0 | | test.swift:357:15:357:15 | t1 [Tuple element at index 1] : | test.swift:357:15:357:18 | .1 | | test.swift:360:15:360:15 | t2 [Tuple element at index 0] : | test.swift:360:15:360:18 | .0 | | test.swift:361:15:361:15 | t2 [Tuple element at index 1] : | test.swift:361:15:361:18 | .1 | -| test.swift:439:13:439:28 | call to optionalSource() : | test.swift:442:19:442:19 | a | -| test.swift:462:9:462:9 | self [x] : | file://:0:0:0:0 | self [x] : | -| test.swift:462:9:462:9 | value : | file://:0:0:0:0 | value : | -| test.swift:466:13:466:28 | call to optionalSource() : | test.swift:468:12:468:12 | x : | -| test.swift:468:5:468:5 | [post] cx [x] : | test.swift:472:20:472:20 | cx [x] : | -| test.swift:468:12:468:12 | x : | test.swift:462:9:462:9 | value : | -| test.swift:468:12:468:12 | x : | test.swift:468:5:468:5 | [post] cx [x] : | -| test.swift:472:20:472:20 | cx [x] : | test.swift:462:9:462:9 | self [x] : | -| test.swift:472:20:472:20 | cx [x] : | test.swift:472:20:472:23 | .x : | -| test.swift:472:20:472:23 | .x : | test.swift:473:15:473:15 | z1 | -| test.swift:479:14:479:21 | call to source() : | test.swift:479:13:479:21 | call to +(_:) | -| test.swift:488:9:488:9 | self [str] : | file://:0:0:0:0 | self [str] : | -| test.swift:489:10:489:13 | s : | test.swift:490:13:490:13 | s : | -| test.swift:490:7:490:7 | [post] self [str] : | test.swift:489:5:491:5 | self[return] [str] : | -| test.swift:490:13:490:13 | s : | test.swift:490:7:490:7 | [post] self [str] : | -| test.swift:495:17:498:5 | self[return] [str] : | test.swift:503:13:503:41 | call to Self.init(contentsOfFile:) [str] : | -| test.swift:496:7:496:7 | [post] self [str] : | test.swift:495:17:498:5 | self[return] [str] : | -| test.swift:496:7:496:7 | [post] self [str] : | test.swift:497:17:497:17 | self [str] : | -| test.swift:496:20:496:28 | call to source3() : | test.swift:489:10:489:13 | s : | -| test.swift:496:20:496:28 | call to source3() : | test.swift:496:7:496:7 | [post] self [str] : | -| test.swift:497:17:497:17 | self [str] : | test.swift:497:17:497:17 | .str | -| test.swift:502:13:502:33 | call to MyClass.init(s:) [str] : | test.swift:488:9:488:9 | self [str] : | -| test.swift:502:13:502:33 | call to MyClass.init(s:) [str] : | test.swift:502:13:502:35 | .str | -| test.swift:502:24:502:32 | call to source3() : | test.swift:489:10:489:13 | s : | -| test.swift:502:24:502:32 | call to source3() : | test.swift:502:13:502:33 | call to MyClass.init(s:) [str] : | -| test.swift:503:13:503:41 | call to Self.init(contentsOfFile:) [str] : | test.swift:488:9:488:9 | self [str] : | -| test.swift:503:13:503:41 | call to Self.init(contentsOfFile:) [str] : | test.swift:503:13:503:43 | .str | +| test.swift:398:9:398:27 | call to ... [mySingle:0] : | test.swift:403:10:403:25 | .mySingle(...) [mySingle:0] : | +| test.swift:398:9:398:27 | call to ... [mySingle:0] : | test.swift:412:13:412:28 | .mySingle(...) [mySingle:0] : | +| test.swift:398:19:398:26 | call to source() : | test.swift:398:9:398:27 | call to ... [mySingle:0] : | +| test.swift:403:10:403:25 | .mySingle(...) [mySingle:0] : | test.swift:403:24:403:24 | a : | +| test.swift:403:24:403:24 | a : | test.swift:404:19:404:19 | a | +| test.swift:412:13:412:28 | .mySingle(...) [mySingle:0] : | test.swift:412:27:412:27 | x : | +| test.swift:412:27:412:27 | x : | test.swift:413:19:413:19 | x | +| test.swift:420:9:420:34 | call to ... [myPair:1] : | test.swift:427:10:427:30 | .myPair(...) [myPair:1] : | +| test.swift:420:9:420:34 | call to ... [myPair:1] : | test.swift:437:13:437:33 | .myPair(...) [myPair:1] : | +| test.swift:420:9:420:34 | call to ... [myPair:1] : | test.swift:442:33:442:33 | a [myPair:1] : | +| test.swift:420:9:420:34 | call to ... [myPair:1] : | test.swift:471:13:471:13 | a [myPair:1] : | +| test.swift:420:26:420:33 | call to source() : | test.swift:420:9:420:34 | call to ... [myPair:1] : | +| test.swift:427:10:427:30 | .myPair(...) [myPair:1] : | test.swift:427:29:427:29 | b : | +| test.swift:427:29:427:29 | b : | test.swift:429:19:429:19 | b | +| test.swift:437:13:437:33 | .myPair(...) [myPair:1] : | test.swift:437:32:437:32 | y : | +| test.swift:437:32:437:32 | y : | test.swift:439:19:439:19 | y | +| test.swift:442:21:442:34 | call to ... [myCons:1, myPair:1] : | test.swift:452:14:452:38 | .myCons(...) [myCons:1, myPair:1] : | +| test.swift:442:21:442:34 | call to ... [myCons:1, myPair:1] : | test.swift:467:17:467:41 | .myCons(...) [myCons:1, myPair:1] : | +| test.swift:442:21:442:34 | call to ... [myCons:1, myPair:1] : | test.swift:471:16:471:16 | b [myCons:1, myPair:1] : | +| test.swift:442:33:442:33 | a [myPair:1] : | test.swift:442:21:442:34 | call to ... [myCons:1, myPair:1] : | +| test.swift:452:14:452:38 | .myCons(...) [myCons:1, myPair:1] : | test.swift:452:25:452:37 | .myPair(...) [myPair:1] : | +| test.swift:452:25:452:37 | .myPair(...) [myPair:1] : | test.swift:452:36:452:36 | c : | +| test.swift:452:36:452:36 | c : | test.swift:455:19:455:19 | c | +| test.swift:463:13:463:39 | .myPair(...) [myPair:0] : | test.swift:463:31:463:31 | x : | +| test.swift:463:31:463:31 | x : | test.swift:464:19:464:19 | x | +| test.swift:463:43:463:62 | call to ... [myPair:0] : | test.swift:463:13:463:39 | .myPair(...) [myPair:0] : | +| test.swift:463:51:463:58 | call to source() : | test.swift:463:43:463:62 | call to ... [myPair:0] : | +| test.swift:467:17:467:41 | .myCons(...) [myCons:1, myPair:1] : | test.swift:467:28:467:40 | .myPair(...) [myPair:1] : | +| test.swift:467:28:467:40 | .myPair(...) [myPair:1] : | test.swift:467:39:467:39 | c : | +| test.swift:467:39:467:39 | c : | test.swift:468:19:468:19 | c | +| test.swift:471:12:471:17 | (...) [Tuple element at index 0, myPair:1] : | test.swift:472:14:472:55 | (...) [Tuple element at index 0, myPair:1] : | +| test.swift:471:12:471:17 | (...) [Tuple element at index 1, myCons:1, myPair:1] : | test.swift:472:14:472:55 | (...) [Tuple element at index 1, myCons:1, myPair:1] : | +| test.swift:471:13:471:13 | a [myPair:1] : | test.swift:471:12:471:17 | (...) [Tuple element at index 0, myPair:1] : | +| test.swift:471:16:471:16 | b [myCons:1, myPair:1] : | test.swift:471:12:471:17 | (...) [Tuple element at index 1, myCons:1, myPair:1] : | +| test.swift:472:14:472:55 | (...) [Tuple element at index 0, myPair:1] : | test.swift:472:15:472:27 | .myPair(...) [myPair:1] : | +| test.swift:472:14:472:55 | (...) [Tuple element at index 1, myCons:1, myPair:1] : | test.swift:472:30:472:54 | .myCons(...) [myCons:1, myPair:1] : | +| test.swift:472:15:472:27 | .myPair(...) [myPair:1] : | test.swift:472:26:472:26 | b : | +| test.swift:472:26:472:26 | b : | test.swift:474:19:474:19 | b | +| test.swift:472:30:472:54 | .myCons(...) [myCons:1, myPair:1] : | test.swift:472:41:472:53 | .myPair(...) [myPair:1] : | +| test.swift:472:41:472:53 | .myPair(...) [myPair:1] : | test.swift:472:52:472:52 | e : | +| test.swift:472:52:472:52 | e : | test.swift:477:19:477:19 | e | +| test.swift:486:13:486:28 | call to optionalSource() [some:0] : | test.swift:488:8:488:12 | let ...? [some:0] : | +| test.swift:486:13:486:28 | call to optionalSource() [some:0] : | test.swift:493:19:493:19 | x [some:0] : | +| test.swift:488:8:488:12 | let ...? [some:0] : | test.swift:488:12:488:12 | a : | +| test.swift:488:12:488:12 | a : | test.swift:489:19:489:19 | a | +| test.swift:493:18:493:23 | (...) [Tuple element at index 0, some:0] : | test.swift:495:10:495:37 | (...) [Tuple element at index 0, some:0] : | +| test.swift:493:19:493:19 | x [some:0] : | test.swift:493:18:493:23 | (...) [Tuple element at index 0, some:0] : | +| test.swift:495:10:495:37 | (...) [Tuple element at index 0, some:0] : | test.swift:495:11:495:22 | .some(...) [some:0] : | +| test.swift:495:11:495:22 | .some(...) [some:0] : | test.swift:495:21:495:21 | a : | +| test.swift:495:21:495:21 | a : | test.swift:496:19:496:19 | a | +| test.swift:509:9:509:9 | self [x, some:0] : | file://:0:0:0:0 | self [x, some:0] : | +| test.swift:509:9:509:9 | value [some:0] : | file://:0:0:0:0 | value [some:0] : | +| test.swift:513:13:513:28 | call to optionalSource() [some:0] : | test.swift:515:12:515:12 | x [some:0] : | +| test.swift:515:5:515:5 | [post] cx [x, some:0] : | test.swift:519:20:519:20 | cx [x, some:0] : | +| test.swift:515:12:515:12 | x [some:0] : | test.swift:509:9:509:9 | value [some:0] : | +| test.swift:515:12:515:12 | x [some:0] : | test.swift:515:5:515:5 | [post] cx [x, some:0] : | +| test.swift:519:11:519:15 | let ...? [some:0] : | test.swift:519:15:519:15 | z1 : | +| test.swift:519:15:519:15 | z1 : | test.swift:520:15:520:15 | z1 | +| test.swift:519:20:519:20 | cx [x, some:0] : | test.swift:509:9:509:9 | self [x, some:0] : | +| test.swift:519:20:519:20 | cx [x, some:0] : | test.swift:519:20:519:23 | .x [some:0] : | +| test.swift:519:20:519:23 | .x [some:0] : | test.swift:519:11:519:15 | let ...? [some:0] : | +| test.swift:526:14:526:21 | call to source() : | test.swift:526:13:526:21 | call to +(_:) | +| test.swift:535:9:535:9 | self [str] : | file://:0:0:0:0 | self [str] : | +| test.swift:536:10:536:13 | s : | test.swift:537:13:537:13 | s : | +| test.swift:537:7:537:7 | [post] self [str] : | test.swift:536:5:538:5 | self[return] [str] : | +| test.swift:537:13:537:13 | s : | test.swift:537:7:537:7 | [post] self [str] : | +| test.swift:542:17:545:5 | self[return] [str] : | test.swift:550:13:550:41 | call to Self.init(contentsOfFile:) [str] : | +| test.swift:543:7:543:7 | [post] self [str] : | test.swift:542:17:545:5 | self[return] [str] : | +| test.swift:543:7:543:7 | [post] self [str] : | test.swift:544:17:544:17 | self [str] : | +| test.swift:543:20:543:28 | call to source3() : | test.swift:536:10:536:13 | s : | +| test.swift:543:20:543:28 | call to source3() : | test.swift:543:7:543:7 | [post] self [str] : | +| test.swift:544:17:544:17 | self [str] : | test.swift:544:17:544:17 | .str | +| test.swift:549:13:549:33 | call to MyClass.init(s:) [str] : | test.swift:535:9:535:9 | self [str] : | +| test.swift:549:13:549:33 | call to MyClass.init(s:) [str] : | test.swift:549:13:549:35 | .str | +| test.swift:549:24:549:32 | call to source3() : | test.swift:536:10:536:13 | s : | +| test.swift:549:24:549:32 | call to source3() : | test.swift:549:13:549:33 | call to MyClass.init(s:) [str] : | +| test.swift:550:13:550:41 | call to Self.init(contentsOfFile:) [str] : | test.swift:535:9:535:9 | self [str] : | +| test.swift:550:13:550:41 | call to Self.init(contentsOfFile:) [str] : | test.swift:550:13:550:43 | .str | nodes | file://:0:0:0:0 | .a [x] : | semmle.label | .a [x] : | | file://:0:0:0:0 | .str : | semmle.label | .str : | | file://:0:0:0:0 | .x : | semmle.label | .x : | -| file://:0:0:0:0 | .x : | semmle.label | .x : | -| file://:0:0:0:0 | [post] self [x] : | semmle.label | [post] self [x] : | +| file://:0:0:0:0 | .x [some:0] : | semmle.label | .x [some:0] : | +| file://:0:0:0:0 | [post] self [x, some:0] : | semmle.label | [post] self [x, some:0] : | | file://:0:0:0:0 | [post] self [x] : | semmle.label | [post] self [x] : | | file://:0:0:0:0 | [summary param] this in signum() : | semmle.label | [summary param] this in signum() : | +| file://:0:0:0:0 | [summary param] this in signum() [some:0] : | semmle.label | [summary param] this in signum() [some:0] : | | file://:0:0:0:0 | [summary] to write: return (return) in signum() : | semmle.label | [summary] to write: return (return) in signum() : | +| file://:0:0:0:0 | [summary] to write: return (return) in signum() [some:0] : | semmle.label | [summary] to write: return (return) in signum() [some:0] : | | file://:0:0:0:0 | self [a, x] : | semmle.label | self [a, x] : | | file://:0:0:0:0 | self [str] : | semmle.label | self [str] : | -| file://:0:0:0:0 | self [x] : | semmle.label | self [x] : | +| file://:0:0:0:0 | self [x, some:0] : | semmle.label | self [x, some:0] : | | file://:0:0:0:0 | self [x] : | semmle.label | self [x] : | | file://:0:0:0:0 | value : | semmle.label | value : | -| file://:0:0:0:0 | value : | semmle.label | value : | +| file://:0:0:0:0 | value [some:0] : | semmle.label | value [some:0] : | | test.swift:6:19:6:26 | call to source() : | semmle.label | call to source() : | | test.swift:7:15:7:15 | t1 | semmle.label | t1 | | test.swift:9:15:9:15 | t1 | semmle.label | t1 | @@ -291,7 +368,9 @@ nodes | test.swift:235:13:235:15 | .source_value | semmle.label | .source_value | | test.swift:238:13:238:15 | .source_value | semmle.label | .source_value | | test.swift:259:12:259:19 | call to source() : | semmle.label | call to source() : | +| test.swift:259:12:259:19 | call to source() [some:0] : | semmle.label | call to source() [some:0] : | | test.swift:263:13:263:28 | call to optionalSource() : | semmle.label | call to optionalSource() : | +| test.swift:263:13:263:28 | call to optionalSource() [some:0] : | semmle.label | call to optionalSource() [some:0] : | | test.swift:265:15:265:15 | x | semmle.label | x | | test.swift:267:15:267:16 | ...! | semmle.label | ...! | | test.swift:270:15:270:22 | call to source() : | semmle.label | call to source() : | @@ -306,14 +385,27 @@ nodes | test.swift:280:31:280:38 | call to source() : | semmle.label | call to source() : | | test.swift:282:15:282:38 | ... ? ... : ... | semmle.label | ... ? ... : ... | | test.swift:282:31:282:38 | call to source() : | semmle.label | call to source() : | +| test.swift:284:8:284:12 | let ...? [some:0] : | semmle.label | let ...? [some:0] : | +| test.swift:284:12:284:12 | z : | semmle.label | z : | | test.swift:285:19:285:19 | z | semmle.label | z | +| test.swift:291:8:291:12 | let ...? [some:0] : | semmle.label | let ...? [some:0] : | +| test.swift:291:12:291:12 | z : | semmle.label | z : | | test.swift:291:16:291:17 | ...? : | semmle.label | ...? : | +| test.swift:291:16:291:17 | ...? [some:0] : | semmle.label | ...? [some:0] : | | test.swift:291:16:291:26 | call to signum() : | semmle.label | call to signum() : | +| test.swift:291:16:291:26 | call to signum() [some:0] : | semmle.label | call to signum() [some:0] : | | test.swift:292:19:292:19 | z | semmle.label | z | +| test.swift:298:11:298:15 | let ...? [some:0] : | semmle.label | let ...? [some:0] : | +| test.swift:298:15:298:15 | z1 : | semmle.label | z1 : | | test.swift:300:15:300:15 | z1 | semmle.label | z1 | | test.swift:303:15:303:16 | ...! : | semmle.label | ...! : | | test.swift:303:15:303:25 | call to signum() | semmle.label | call to signum() | +| test.swift:306:13:306:24 | .some(...) [some:0] : | semmle.label | .some(...) [some:0] : | +| test.swift:306:23:306:23 | z : | semmle.label | z : | | test.swift:307:19:307:19 | z | semmle.label | z | +| test.swift:314:10:314:21 | .some(...) [some:0] : | semmle.label | .some(...) [some:0] : | +| test.swift:314:20:314:20 | z : | semmle.label | z : | +| test.swift:315:19:315:19 | z | semmle.label | z | | test.swift:331:14:331:26 | (...) [Tuple element at index 1] : | semmle.label | (...) [Tuple element at index 1] : | | test.swift:331:18:331:25 | call to source() : | semmle.label | call to source() : | | test.swift:335:15:335:15 | t1 [Tuple element at index 1] : | semmle.label | t1 [Tuple element at index 1] : | @@ -326,6 +418,10 @@ nodes | test.swift:351:14:351:45 | (...) [Tuple element at index 1] : | semmle.label | (...) [Tuple element at index 1] : | | test.swift:351:18:351:25 | call to source() : | semmle.label | call to source() : | | test.swift:351:31:351:38 | call to source() : | semmle.label | call to source() : | +| test.swift:353:9:353:17 | (...) [Tuple element at index 0] : | semmle.label | (...) [Tuple element at index 0] : | +| test.swift:353:9:353:17 | (...) [Tuple element at index 1] : | semmle.label | (...) [Tuple element at index 1] : | +| test.swift:353:10:353:10 | a : | semmle.label | a : | +| test.swift:353:13:353:13 | b : | semmle.label | b : | | test.swift:356:15:356:15 | t1 [Tuple element at index 0] : | semmle.label | t1 [Tuple element at index 0] : | | test.swift:356:15:356:18 | .0 | semmle.label | .0 | | test.swift:357:15:357:15 | t1 [Tuple element at index 1] : | semmle.label | t1 [Tuple element at index 1] : | @@ -334,34 +430,90 @@ nodes | test.swift:360:15:360:18 | .0 | semmle.label | .0 | | test.swift:361:15:361:15 | t2 [Tuple element at index 1] : | semmle.label | t2 [Tuple element at index 1] : | | test.swift:361:15:361:18 | .1 | semmle.label | .1 | -| test.swift:439:13:439:28 | call to optionalSource() : | semmle.label | call to optionalSource() : | -| test.swift:442:19:442:19 | a | semmle.label | a | -| test.swift:462:9:462:9 | self [x] : | semmle.label | self [x] : | -| test.swift:462:9:462:9 | value : | semmle.label | value : | -| test.swift:466:13:466:28 | call to optionalSource() : | semmle.label | call to optionalSource() : | -| test.swift:468:5:468:5 | [post] cx [x] : | semmle.label | [post] cx [x] : | -| test.swift:468:12:468:12 | x : | semmle.label | x : | -| test.swift:472:20:472:20 | cx [x] : | semmle.label | cx [x] : | -| test.swift:472:20:472:23 | .x : | semmle.label | .x : | -| test.swift:473:15:473:15 | z1 | semmle.label | z1 | -| test.swift:479:13:479:21 | call to +(_:) | semmle.label | call to +(_:) | -| test.swift:479:14:479:21 | call to source() : | semmle.label | call to source() : | -| test.swift:480:14:480:21 | call to source() | semmle.label | call to source() | -| test.swift:488:9:488:9 | self [str] : | semmle.label | self [str] : | -| test.swift:489:5:491:5 | self[return] [str] : | semmle.label | self[return] [str] : | -| test.swift:489:10:489:13 | s : | semmle.label | s : | -| test.swift:490:7:490:7 | [post] self [str] : | semmle.label | [post] self [str] : | -| test.swift:490:13:490:13 | s : | semmle.label | s : | -| test.swift:495:17:498:5 | self[return] [str] : | semmle.label | self[return] [str] : | -| test.swift:496:7:496:7 | [post] self [str] : | semmle.label | [post] self [str] : | -| test.swift:496:20:496:28 | call to source3() : | semmle.label | call to source3() : | -| test.swift:497:17:497:17 | .str | semmle.label | .str | -| test.swift:497:17:497:17 | self [str] : | semmle.label | self [str] : | -| test.swift:502:13:502:33 | call to MyClass.init(s:) [str] : | semmle.label | call to MyClass.init(s:) [str] : | -| test.swift:502:13:502:35 | .str | semmle.label | .str | -| test.swift:502:24:502:32 | call to source3() : | semmle.label | call to source3() : | -| test.swift:503:13:503:41 | call to Self.init(contentsOfFile:) [str] : | semmle.label | call to Self.init(contentsOfFile:) [str] : | -| test.swift:503:13:503:43 | .str | semmle.label | .str | +| test.swift:363:15:363:15 | a | semmle.label | a | +| test.swift:364:15:364:15 | b | semmle.label | b | +| test.swift:398:9:398:27 | call to ... [mySingle:0] : | semmle.label | call to ... [mySingle:0] : | +| test.swift:398:19:398:26 | call to source() : | semmle.label | call to source() : | +| test.swift:403:10:403:25 | .mySingle(...) [mySingle:0] : | semmle.label | .mySingle(...) [mySingle:0] : | +| test.swift:403:24:403:24 | a : | semmle.label | a : | +| test.swift:404:19:404:19 | a | semmle.label | a | +| test.swift:412:13:412:28 | .mySingle(...) [mySingle:0] : | semmle.label | .mySingle(...) [mySingle:0] : | +| test.swift:412:27:412:27 | x : | semmle.label | x : | +| test.swift:413:19:413:19 | x | semmle.label | x | +| test.swift:420:9:420:34 | call to ... [myPair:1] : | semmle.label | call to ... [myPair:1] : | +| test.swift:420:26:420:33 | call to source() : | semmle.label | call to source() : | +| test.swift:427:10:427:30 | .myPair(...) [myPair:1] : | semmle.label | .myPair(...) [myPair:1] : | +| test.swift:427:29:427:29 | b : | semmle.label | b : | +| test.swift:429:19:429:19 | b | semmle.label | b | +| test.swift:437:13:437:33 | .myPair(...) [myPair:1] : | semmle.label | .myPair(...) [myPair:1] : | +| test.swift:437:32:437:32 | y : | semmle.label | y : | +| test.swift:439:19:439:19 | y | semmle.label | y | +| test.swift:442:21:442:34 | call to ... [myCons:1, myPair:1] : | semmle.label | call to ... [myCons:1, myPair:1] : | +| test.swift:442:33:442:33 | a [myPair:1] : | semmle.label | a [myPair:1] : | +| test.swift:452:14:452:38 | .myCons(...) [myCons:1, myPair:1] : | semmle.label | .myCons(...) [myCons:1, myPair:1] : | +| test.swift:452:25:452:37 | .myPair(...) [myPair:1] : | semmle.label | .myPair(...) [myPair:1] : | +| test.swift:452:36:452:36 | c : | semmle.label | c : | +| test.swift:455:19:455:19 | c | semmle.label | c | +| test.swift:463:13:463:39 | .myPair(...) [myPair:0] : | semmle.label | .myPair(...) [myPair:0] : | +| test.swift:463:31:463:31 | x : | semmle.label | x : | +| test.swift:463:43:463:62 | call to ... [myPair:0] : | semmle.label | call to ... [myPair:0] : | +| test.swift:463:51:463:58 | call to source() : | semmle.label | call to source() : | +| test.swift:464:19:464:19 | x | semmle.label | x | +| test.swift:467:17:467:41 | .myCons(...) [myCons:1, myPair:1] : | semmle.label | .myCons(...) [myCons:1, myPair:1] : | +| test.swift:467:28:467:40 | .myPair(...) [myPair:1] : | semmle.label | .myPair(...) [myPair:1] : | +| test.swift:467:39:467:39 | c : | semmle.label | c : | +| test.swift:468:19:468:19 | c | semmle.label | c | +| test.swift:471:12:471:17 | (...) [Tuple element at index 0, myPair:1] : | semmle.label | (...) [Tuple element at index 0, myPair:1] : | +| test.swift:471:12:471:17 | (...) [Tuple element at index 1, myCons:1, myPair:1] : | semmle.label | (...) [Tuple element at index 1, myCons:1, myPair:1] : | +| test.swift:471:13:471:13 | a [myPair:1] : | semmle.label | a [myPair:1] : | +| test.swift:471:16:471:16 | b [myCons:1, myPair:1] : | semmle.label | b [myCons:1, myPair:1] : | +| test.swift:472:14:472:55 | (...) [Tuple element at index 0, myPair:1] : | semmle.label | (...) [Tuple element at index 0, myPair:1] : | +| test.swift:472:14:472:55 | (...) [Tuple element at index 1, myCons:1, myPair:1] : | semmle.label | (...) [Tuple element at index 1, myCons:1, myPair:1] : | +| test.swift:472:15:472:27 | .myPair(...) [myPair:1] : | semmle.label | .myPair(...) [myPair:1] : | +| test.swift:472:26:472:26 | b : | semmle.label | b : | +| test.swift:472:30:472:54 | .myCons(...) [myCons:1, myPair:1] : | semmle.label | .myCons(...) [myCons:1, myPair:1] : | +| test.swift:472:41:472:53 | .myPair(...) [myPair:1] : | semmle.label | .myPair(...) [myPair:1] : | +| test.swift:472:52:472:52 | e : | semmle.label | e : | +| test.swift:474:19:474:19 | b | semmle.label | b | +| test.swift:477:19:477:19 | e | semmle.label | e | +| test.swift:486:13:486:28 | call to optionalSource() [some:0] : | semmle.label | call to optionalSource() [some:0] : | +| test.swift:488:8:488:12 | let ...? [some:0] : | semmle.label | let ...? [some:0] : | +| test.swift:488:12:488:12 | a : | semmle.label | a : | +| test.swift:489:19:489:19 | a | semmle.label | a | +| test.swift:493:18:493:23 | (...) [Tuple element at index 0, some:0] : | semmle.label | (...) [Tuple element at index 0, some:0] : | +| test.swift:493:19:493:19 | x [some:0] : | semmle.label | x [some:0] : | +| test.swift:495:10:495:37 | (...) [Tuple element at index 0, some:0] : | semmle.label | (...) [Tuple element at index 0, some:0] : | +| test.swift:495:11:495:22 | .some(...) [some:0] : | semmle.label | .some(...) [some:0] : | +| test.swift:495:21:495:21 | a : | semmle.label | a : | +| test.swift:496:19:496:19 | a | semmle.label | a | +| test.swift:509:9:509:9 | self [x, some:0] : | semmle.label | self [x, some:0] : | +| test.swift:509:9:509:9 | value [some:0] : | semmle.label | value [some:0] : | +| test.swift:513:13:513:28 | call to optionalSource() [some:0] : | semmle.label | call to optionalSource() [some:0] : | +| test.swift:515:5:515:5 | [post] cx [x, some:0] : | semmle.label | [post] cx [x, some:0] : | +| test.swift:515:12:515:12 | x [some:0] : | semmle.label | x [some:0] : | +| test.swift:519:11:519:15 | let ...? [some:0] : | semmle.label | let ...? [some:0] : | +| test.swift:519:15:519:15 | z1 : | semmle.label | z1 : | +| test.swift:519:20:519:20 | cx [x, some:0] : | semmle.label | cx [x, some:0] : | +| test.swift:519:20:519:23 | .x [some:0] : | semmle.label | .x [some:0] : | +| test.swift:520:15:520:15 | z1 | semmle.label | z1 | +| test.swift:526:13:526:21 | call to +(_:) | semmle.label | call to +(_:) | +| test.swift:526:14:526:21 | call to source() : | semmle.label | call to source() : | +| test.swift:527:14:527:21 | call to source() | semmle.label | call to source() | +| test.swift:535:9:535:9 | self [str] : | semmle.label | self [str] : | +| test.swift:536:5:538:5 | self[return] [str] : | semmle.label | self[return] [str] : | +| test.swift:536:10:536:13 | s : | semmle.label | s : | +| test.swift:537:7:537:7 | [post] self [str] : | semmle.label | [post] self [str] : | +| test.swift:537:13:537:13 | s : | semmle.label | s : | +| test.swift:542:17:545:5 | self[return] [str] : | semmle.label | self[return] [str] : | +| test.swift:543:7:543:7 | [post] self [str] : | semmle.label | [post] self [str] : | +| test.swift:543:20:543:28 | call to source3() : | semmle.label | call to source3() : | +| test.swift:544:17:544:17 | .str | semmle.label | .str | +| test.swift:544:17:544:17 | self [str] : | semmle.label | self [str] : | +| test.swift:549:13:549:33 | call to MyClass.init(s:) [str] : | semmle.label | call to MyClass.init(s:) [str] : | +| test.swift:549:13:549:35 | .str | semmle.label | .str | +| test.swift:549:24:549:32 | call to source3() : | semmle.label | call to source3() : | +| test.swift:550:13:550:41 | call to Self.init(contentsOfFile:) [str] : | semmle.label | call to Self.init(contentsOfFile:) [str] : | +| test.swift:550:13:550:43 | .str | semmle.label | .str | subpaths | test.swift:75:21:75:22 | &... : | test.swift:65:16:65:28 | arg1 : | test.swift:65:1:70:1 | arg2[return] : | test.swift:75:31:75:32 | [post] &... : | | test.swift:114:19:114:19 | arg : | test.swift:109:9:109:14 | arg : | test.swift:110:12:110:12 | arg : | test.swift:114:12:114:22 | call to ... : | @@ -391,13 +543,14 @@ subpaths | test.swift:270:15:270:22 | call to source() : | file://:0:0:0:0 | [summary param] this in signum() : | file://:0:0:0:0 | [summary] to write: return (return) in signum() : | test.swift:270:15:270:31 | call to signum() | | test.swift:271:15:271:16 | ...? : | file://:0:0:0:0 | [summary param] this in signum() : | file://:0:0:0:0 | [summary] to write: return (return) in signum() : | test.swift:271:15:271:25 | call to signum() : | | test.swift:291:16:291:17 | ...? : | file://:0:0:0:0 | [summary param] this in signum() : | file://:0:0:0:0 | [summary] to write: return (return) in signum() : | test.swift:291:16:291:26 | call to signum() : | +| test.swift:291:16:291:17 | ...? [some:0] : | file://:0:0:0:0 | [summary param] this in signum() [some:0] : | file://:0:0:0:0 | [summary] to write: return (return) in signum() [some:0] : | test.swift:291:16:291:26 | call to signum() [some:0] : | | test.swift:303:15:303:16 | ...! : | file://:0:0:0:0 | [summary param] this in signum() : | file://:0:0:0:0 | [summary] to write: return (return) in signum() : | test.swift:303:15:303:25 | call to signum() | -| test.swift:468:12:468:12 | x : | test.swift:462:9:462:9 | value : | file://:0:0:0:0 | [post] self [x] : | test.swift:468:5:468:5 | [post] cx [x] : | -| test.swift:472:20:472:20 | cx [x] : | test.swift:462:9:462:9 | self [x] : | file://:0:0:0:0 | .x : | test.swift:472:20:472:23 | .x : | -| test.swift:496:20:496:28 | call to source3() : | test.swift:489:10:489:13 | s : | test.swift:490:7:490:7 | [post] self [str] : | test.swift:496:7:496:7 | [post] self [str] : | -| test.swift:502:13:502:33 | call to MyClass.init(s:) [str] : | test.swift:488:9:488:9 | self [str] : | file://:0:0:0:0 | .str : | test.swift:502:13:502:35 | .str | -| test.swift:502:24:502:32 | call to source3() : | test.swift:489:10:489:13 | s : | test.swift:489:5:491:5 | self[return] [str] : | test.swift:502:13:502:33 | call to MyClass.init(s:) [str] : | -| test.swift:503:13:503:41 | call to Self.init(contentsOfFile:) [str] : | test.swift:488:9:488:9 | self [str] : | file://:0:0:0:0 | .str : | test.swift:503:13:503:43 | .str | +| test.swift:515:12:515:12 | x [some:0] : | test.swift:509:9:509:9 | value [some:0] : | file://:0:0:0:0 | [post] self [x, some:0] : | test.swift:515:5:515:5 | [post] cx [x, some:0] : | +| test.swift:519:20:519:20 | cx [x, some:0] : | test.swift:509:9:509:9 | self [x, some:0] : | file://:0:0:0:0 | .x [some:0] : | test.swift:519:20:519:23 | .x [some:0] : | +| test.swift:543:20:543:28 | call to source3() : | test.swift:536:10:536:13 | s : | test.swift:537:7:537:7 | [post] self [str] : | test.swift:543:7:543:7 | [post] self [str] : | +| test.swift:549:13:549:33 | call to MyClass.init(s:) [str] : | test.swift:535:9:535:9 | self [str] : | file://:0:0:0:0 | .str : | test.swift:549:13:549:35 | .str | +| test.swift:549:24:549:32 | call to source3() : | test.swift:536:10:536:13 | s : | test.swift:536:5:538:5 | self[return] [str] : | test.swift:549:13:549:33 | call to MyClass.init(s:) [str] : | +| test.swift:550:13:550:41 | call to Self.init(contentsOfFile:) [str] : | test.swift:535:9:535:9 | self [str] : | file://:0:0:0:0 | .str : | test.swift:550:13:550:43 | .str | #select | test.swift:7:15:7:15 | t1 | test.swift:6:19:6:26 | call to source() : | test.swift:7:15:7:15 | t1 | result | | test.swift:9:15:9:15 | t1 | test.swift:6:19:6:26 | call to source() : | test.swift:9:15:9:15 | t1 | result | @@ -442,16 +595,29 @@ subpaths | test.swift:300:15:300:15 | z1 | test.swift:259:12:259:19 | call to source() : | test.swift:300:15:300:15 | z1 | result | | test.swift:303:15:303:25 | call to signum() | test.swift:259:12:259:19 | call to source() : | test.swift:303:15:303:25 | call to signum() | result | | test.swift:307:19:307:19 | z | test.swift:259:12:259:19 | call to source() : | test.swift:307:19:307:19 | z | result | +| test.swift:315:19:315:19 | z | test.swift:259:12:259:19 | call to source() : | test.swift:315:19:315:19 | z | result | | test.swift:335:15:335:18 | .1 | test.swift:331:18:331:25 | call to source() : | test.swift:335:15:335:18 | .1 | result | | test.swift:346:15:346:18 | .0 | test.swift:343:12:343:19 | call to source() : | test.swift:346:15:346:18 | .0 | result | | test.swift:356:15:356:18 | .0 | test.swift:351:18:351:25 | call to source() : | test.swift:356:15:356:18 | .0 | result | | test.swift:357:15:357:18 | .1 | test.swift:351:31:351:38 | call to source() : | test.swift:357:15:357:18 | .1 | result | | test.swift:360:15:360:18 | .0 | test.swift:351:18:351:25 | call to source() : | test.swift:360:15:360:18 | .0 | result | | test.swift:361:15:361:18 | .1 | test.swift:351:31:351:38 | call to source() : | test.swift:361:15:361:18 | .1 | result | -| test.swift:442:19:442:19 | a | test.swift:259:12:259:19 | call to source() : | test.swift:442:19:442:19 | a | result | -| test.swift:473:15:473:15 | z1 | test.swift:259:12:259:19 | call to source() : | test.swift:473:15:473:15 | z1 | result | -| test.swift:479:13:479:21 | call to +(_:) | test.swift:479:14:479:21 | call to source() : | test.swift:479:13:479:21 | call to +(_:) | result | -| test.swift:480:14:480:21 | call to source() | test.swift:480:14:480:21 | call to source() | test.swift:480:14:480:21 | call to source() | result | -| test.swift:497:17:497:17 | .str | test.swift:496:20:496:28 | call to source3() : | test.swift:497:17:497:17 | .str | result | -| test.swift:502:13:502:35 | .str | test.swift:502:24:502:32 | call to source3() : | test.swift:502:13:502:35 | .str | result | -| test.swift:503:13:503:43 | .str | test.swift:496:20:496:28 | call to source3() : | test.swift:503:13:503:43 | .str | result | +| test.swift:363:15:363:15 | a | test.swift:351:18:351:25 | call to source() : | test.swift:363:15:363:15 | a | result | +| test.swift:364:15:364:15 | b | test.swift:351:31:351:38 | call to source() : | test.swift:364:15:364:15 | b | result | +| test.swift:404:19:404:19 | a | test.swift:398:19:398:26 | call to source() : | test.swift:404:19:404:19 | a | result | +| test.swift:413:19:413:19 | x | test.swift:398:19:398:26 | call to source() : | test.swift:413:19:413:19 | x | result | +| test.swift:429:19:429:19 | b | test.swift:420:26:420:33 | call to source() : | test.swift:429:19:429:19 | b | result | +| test.swift:439:19:439:19 | y | test.swift:420:26:420:33 | call to source() : | test.swift:439:19:439:19 | y | result | +| test.swift:455:19:455:19 | c | test.swift:420:26:420:33 | call to source() : | test.swift:455:19:455:19 | c | result | +| test.swift:464:19:464:19 | x | test.swift:463:51:463:58 | call to source() : | test.swift:464:19:464:19 | x | result | +| test.swift:468:19:468:19 | c | test.swift:420:26:420:33 | call to source() : | test.swift:468:19:468:19 | c | result | +| test.swift:474:19:474:19 | b | test.swift:420:26:420:33 | call to source() : | test.swift:474:19:474:19 | b | result | +| test.swift:477:19:477:19 | e | test.swift:420:26:420:33 | call to source() : | test.swift:477:19:477:19 | e | result | +| test.swift:489:19:489:19 | a | test.swift:259:12:259:19 | call to source() : | test.swift:489:19:489:19 | a | result | +| test.swift:496:19:496:19 | a | test.swift:259:12:259:19 | call to source() : | test.swift:496:19:496:19 | a | result | +| test.swift:520:15:520:15 | z1 | test.swift:259:12:259:19 | call to source() : | test.swift:520:15:520:15 | z1 | result | +| test.swift:526:13:526:21 | call to +(_:) | test.swift:526:14:526:21 | call to source() : | test.swift:526:13:526:21 | call to +(_:) | result | +| test.swift:527:14:527:21 | call to source() | test.swift:527:14:527:21 | call to source() | test.swift:527:14:527:21 | call to source() | result | +| test.swift:544:17:544:17 | .str | test.swift:543:20:543:28 | call to source3() : | test.swift:544:17:544:17 | .str | result | +| test.swift:549:13:549:35 | .str | test.swift:549:24:549:32 | call to source3() : | test.swift:549:13:549:35 | .str | result | +| test.swift:550:13:550:43 | .str | test.swift:543:20:543:28 | call to source3() : | test.swift:550:13:550:43 | .str | result | diff --git a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected index 647bb37f2e5..516612aa964 100644 --- a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected +++ b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected @@ -1,5 +1,8 @@ -| test.swift:6:9:6:13 | SSA def(t1) | test.swift:7:15:7:15 | t1 | -| test.swift:6:19:6:26 | call to source() | test.swift:6:9:6:13 | SSA def(t1) | +| test.swift:5:9:5:13 | ... as ... | test.swift:5:9:5:9 | t2 | +| test.swift:6:9:6:9 | SSA def(t1) | test.swift:7:15:7:15 | t1 | +| test.swift:6:9:6:9 | t1 | test.swift:6:9:6:9 | SSA def(t1) | +| test.swift:6:9:6:13 | ... as ... | test.swift:6:9:6:9 | t1 | +| test.swift:6:19:6:26 | call to source() | test.swift:6:9:6:13 | ... as ... | | test.swift:7:15:7:15 | [post] t1 | test.swift:8:10:8:10 | t1 | | test.swift:7:15:7:15 | t1 | test.swift:8:10:8:10 | t1 | | test.swift:8:5:8:10 | SSA def(t2) | test.swift:10:15:10:15 | t2 | @@ -18,8 +21,12 @@ | test.swift:29:26:29:29 | y | test.swift:29:26:29:29 | SSA def(y) | | test.swift:42:16:42:19 | SSA def(b) | test.swift:45:8:45:8 | b | | test.swift:42:16:42:19 | b | test.swift:42:16:42:19 | SSA def(b) | -| test.swift:43:9:43:13 | SSA def(t1) | test.swift:46:13:46:13 | t1 | -| test.swift:43:19:43:26 | call to source() | test.swift:43:9:43:13 | SSA def(t1) | +| test.swift:43:9:43:9 | SSA def(t1) | test.swift:46:13:46:13 | t1 | +| test.swift:43:9:43:9 | t1 | test.swift:43:9:43:9 | SSA def(t1) | +| test.swift:43:9:43:13 | ... as ... | test.swift:43:9:43:9 | t1 | +| test.swift:43:19:43:26 | call to source() | test.swift:43:9:43:13 | ... as ... | +| test.swift:44:9:44:12 | ... as ... | test.swift:44:9:44:9 | t | +| test.swift:44:18:44:18 | 0 | test.swift:44:9:44:12 | ... as ... | | test.swift:46:9:46:13 | SSA def(t) | test.swift:50:5:50:5 | SSA phi(t) | | test.swift:46:13:46:13 | t1 | test.swift:46:9:46:13 | SSA def(t) | | test.swift:48:9:48:13 | SSA def(t) | test.swift:50:5:50:5 | SSA phi(t) | @@ -27,8 +34,10 @@ | test.swift:50:5:50:5 | SSA phi(t) | test.swift:50:15:50:15 | t | | test.swift:54:5:54:18 | SSA def(arg) | test.swift:53:1:56:1 | arg[return] | | test.swift:54:11:54:18 | call to source() | test.swift:54:5:54:18 | SSA def(arg) | -| test.swift:59:9:59:12 | SSA def(x) | test.swift:60:15:60:15 | x | -| test.swift:59:18:59:18 | 0 | test.swift:59:9:59:12 | SSA def(x) | +| test.swift:59:9:59:9 | SSA def(x) | test.swift:60:15:60:15 | x | +| test.swift:59:9:59:9 | x | test.swift:59:9:59:9 | SSA def(x) | +| test.swift:59:9:59:12 | ... as ... | test.swift:59:9:59:9 | x | +| test.swift:59:18:59:18 | 0 | test.swift:59:9:59:12 | ... as ... | | test.swift:60:15:60:15 | [post] x | test.swift:61:23:61:23 | x | | test.swift:60:15:60:15 | x | test.swift:61:23:61:23 | x | | test.swift:61:22:61:23 | &... | test.swift:62:15:62:15 | x | @@ -38,16 +47,22 @@ | test.swift:65:16:65:28 | arg1 | test.swift:65:16:65:28 | SSA def(arg1) | | test.swift:65:33:65:45 | SSA def(arg2) | test.swift:67:12:67:12 | arg2 | | test.swift:65:33:65:45 | arg2 | test.swift:65:33:65:45 | SSA def(arg2) | -| test.swift:66:9:66:15 | SSA def(temp) | test.swift:68:12:68:12 | temp | -| test.swift:66:21:66:21 | arg1 | test.swift:66:9:66:15 | SSA def(temp) | +| test.swift:66:9:66:9 | SSA def(temp) | test.swift:68:12:68:12 | temp | +| test.swift:66:9:66:9 | temp | test.swift:66:9:66:9 | SSA def(temp) | +| test.swift:66:9:66:15 | ... as ... | test.swift:66:9:66:9 | temp | +| test.swift:66:21:66:21 | arg1 | test.swift:66:9:66:15 | ... as ... | | test.swift:67:5:67:12 | SSA def(arg1) | test.swift:65:1:70:1 | arg1[return] | | test.swift:67:12:67:12 | arg2 | test.swift:67:5:67:12 | SSA def(arg1) | | test.swift:68:5:68:12 | SSA def(arg2) | test.swift:65:1:70:1 | arg2[return] | | test.swift:68:12:68:12 | temp | test.swift:68:5:68:12 | SSA def(arg2) | -| test.swift:73:9:73:12 | SSA def(x) | test.swift:75:22:75:22 | x | -| test.swift:73:18:73:25 | call to source() | test.swift:73:9:73:12 | SSA def(x) | -| test.swift:74:9:74:12 | SSA def(y) | test.swift:75:32:75:32 | y | -| test.swift:74:18:74:18 | 0 | test.swift:74:9:74:12 | SSA def(y) | +| test.swift:73:9:73:9 | SSA def(x) | test.swift:75:22:75:22 | x | +| test.swift:73:9:73:9 | x | test.swift:73:9:73:9 | SSA def(x) | +| test.swift:73:9:73:12 | ... as ... | test.swift:73:9:73:9 | x | +| test.swift:73:18:73:25 | call to source() | test.swift:73:9:73:12 | ... as ... | +| test.swift:74:9:74:9 | SSA def(y) | test.swift:75:32:75:32 | y | +| test.swift:74:9:74:9 | y | test.swift:74:9:74:9 | SSA def(y) | +| test.swift:74:9:74:12 | ... as ... | test.swift:74:9:74:9 | y | +| test.swift:74:18:74:18 | 0 | test.swift:74:9:74:12 | ... as ... | | test.swift:75:21:75:22 | &... | test.swift:76:15:76:15 | x | | test.swift:75:21:75:22 | [post] &... | test.swift:76:15:76:15 | x | | test.swift:75:22:75:22 | x | test.swift:75:21:75:22 | &... | @@ -65,15 +80,19 @@ | test.swift:89:15:89:22 | call to source() | test.swift:89:9:89:22 | SSA def(arg) | | test.swift:93:17:93:23 | SSA def(bool) | test.swift:104:50:104:50 | bool | | test.swift:93:17:93:23 | bool | test.swift:93:17:93:23 | SSA def(bool) | -| test.swift:95:13:95:16 | SSA def(x) | test.swift:96:19:96:19 | x | -| test.swift:95:22:95:22 | 0 | test.swift:95:13:95:16 | SSA def(x) | +| test.swift:95:13:95:13 | SSA def(x) | test.swift:96:19:96:19 | x | +| test.swift:95:13:95:13 | x | test.swift:95:13:95:13 | SSA def(x) | +| test.swift:95:13:95:16 | ... as ... | test.swift:95:13:95:13 | x | +| test.swift:95:22:95:22 | 0 | test.swift:95:13:95:16 | ... as ... | | test.swift:96:19:96:19 | [post] x | test.swift:97:40:97:40 | x | | test.swift:96:19:96:19 | x | test.swift:97:40:97:40 | x | | test.swift:97:39:97:40 | &... | test.swift:98:19:98:19 | x | | test.swift:97:39:97:40 | [post] &... | test.swift:98:19:98:19 | x | | test.swift:97:40:97:40 | x | test.swift:97:39:97:40 | &... | -| test.swift:102:13:102:16 | SSA def(x) | test.swift:103:19:103:19 | x | -| test.swift:102:22:102:22 | 0 | test.swift:102:13:102:16 | SSA def(x) | +| test.swift:102:13:102:13 | SSA def(x) | test.swift:103:19:103:19 | x | +| test.swift:102:13:102:13 | x | test.swift:102:13:102:13 | SSA def(x) | +| test.swift:102:13:102:16 | ... as ... | test.swift:102:13:102:13 | x | +| test.swift:102:22:102:22 | 0 | test.swift:102:13:102:16 | ... as ... | | test.swift:103:19:103:19 | [post] x | test.swift:104:41:104:41 | x | | test.swift:103:19:103:19 | x | test.swift:104:41:104:41 | x | | test.swift:104:40:104:41 | &... | test.swift:105:19:105:19 | x | @@ -85,25 +104,37 @@ | test.swift:113:14:113:19 | arg | test.swift:113:14:113:19 | SSA def(arg) | | test.swift:113:24:113:41 | SSA def(lambda) | test.swift:114:12:114:12 | lambda | | test.swift:113:24:113:41 | lambda | test.swift:113:24:113:41 | SSA def(lambda) | -| test.swift:118:9:118:12 | SSA def(x) | test.swift:119:31:119:31 | x | -| test.swift:118:18:118:25 | call to source() | test.swift:118:9:118:12 | SSA def(x) | -| test.swift:119:9:119:12 | SSA def(y) | test.swift:120:15:120:15 | y | -| test.swift:119:18:119:44 | call to forward(arg:lambda:) | test.swift:119:9:119:12 | SSA def(y) | -| test.swift:122:9:122:12 | SSA def(z) | test.swift:126:15:126:15 | z | -| test.swift:122:18:125:6 | call to forward(arg:lambda:) | test.swift:122:9:122:12 | SSA def(z) | +| test.swift:118:9:118:9 | SSA def(x) | test.swift:119:31:119:31 | x | +| test.swift:118:9:118:9 | x | test.swift:118:9:118:9 | SSA def(x) | +| test.swift:118:9:118:12 | ... as ... | test.swift:118:9:118:9 | x | +| test.swift:118:18:118:25 | call to source() | test.swift:118:9:118:12 | ... as ... | +| test.swift:119:9:119:9 | SSA def(y) | test.swift:120:15:120:15 | y | +| test.swift:119:9:119:9 | y | test.swift:119:9:119:9 | SSA def(y) | +| test.swift:119:9:119:12 | ... as ... | test.swift:119:9:119:9 | y | +| test.swift:119:18:119:44 | call to forward(arg:lambda:) | test.swift:119:9:119:12 | ... as ... | +| test.swift:122:9:122:9 | SSA def(z) | test.swift:126:15:126:15 | z | +| test.swift:122:9:122:9 | z | test.swift:122:9:122:9 | SSA def(z) | +| test.swift:122:9:122:12 | ... as ... | test.swift:122:9:122:9 | z | +| test.swift:122:18:125:6 | call to forward(arg:lambda:) | test.swift:122:9:122:12 | ... as ... | | test.swift:123:10:123:13 | SSA def(i) | test.swift:124:16:124:16 | i | | test.swift:123:10:123:13 | i | test.swift:123:10:123:13 | SSA def(i) | -| test.swift:128:9:128:16 | SSA def(clean) | test.swift:132:15:132:15 | clean | -| test.swift:128:22:131:6 | call to forward(arg:lambda:) | test.swift:128:9:128:16 | SSA def(clean) | +| test.swift:128:9:128:9 | SSA def(clean) | test.swift:132:15:132:15 | clean | +| test.swift:128:9:128:9 | clean | test.swift:128:9:128:9 | SSA def(clean) | +| test.swift:128:9:128:16 | ... as ... | test.swift:128:9:128:9 | clean | +| test.swift:128:22:131:6 | call to forward(arg:lambda:) | test.swift:128:9:128:16 | ... as ... | +| test.swift:136:19:139:5 | { ... } | test.swift:136:9:136:9 | lambda1 | | test.swift:141:9:141:9 | SSA def(lambda2) | test.swift:145:15:145:15 | lambda2 | -| test.swift:141:19:144:5 | { ... } | test.swift:141:9:141:9 | SSA def(lambda2) | +| test.swift:141:9:141:9 | lambda2 | test.swift:141:9:141:9 | SSA def(lambda2) | +| test.swift:141:19:144:5 | { ... } | test.swift:141:9:141:9 | lambda2 | | test.swift:142:10:142:13 | SSA def(i) | test.swift:143:16:143:16 | i | | test.swift:142:10:142:13 | i | test.swift:142:10:142:13 | SSA def(i) | | test.swift:147:9:147:9 | SSA def(lambdaSource) | test.swift:151:15:151:15 | lambdaSource | -| test.swift:147:24:150:5 | { ... } | test.swift:147:9:147:9 | SSA def(lambdaSource) | +| test.swift:147:9:147:9 | lambdaSource | test.swift:147:9:147:9 | SSA def(lambdaSource) | +| test.swift:147:24:150:5 | { ... } | test.swift:147:9:147:9 | lambdaSource | | test.swift:151:15:151:15 | lambdaSource | test.swift:159:16:159:16 | lambdaSource | | test.swift:153:9:153:9 | SSA def(lambdaSink) | test.swift:157:5:157:5 | lambdaSink | -| test.swift:153:22:156:5 | { ... } | test.swift:153:9:153:9 | SSA def(lambdaSink) | +| test.swift:153:9:153:9 | lambdaSink | test.swift:153:9:153:9 | SSA def(lambdaSink) | +| test.swift:153:22:156:5 | { ... } | test.swift:153:9:153:9 | lambdaSink | | test.swift:154:10:154:13 | SSA def(i) | test.swift:155:19:155:19 | i | | test.swift:154:10:154:13 | i | test.swift:154:10:154:13 | SSA def(i) | | test.swift:157:5:157:5 | lambdaSink | test.swift:159:5:159:5 | lambdaSink | @@ -128,7 +159,8 @@ | test.swift:174:12:174:12 | [post] self | test.swift:173:3:175:3 | self[return] | | test.swift:174:12:174:12 | self | test.swift:173:3:175:3 | self[return] | | test.swift:179:7:179:7 | SSA def(a) | test.swift:180:3:180:3 | a | -| test.swift:179:11:179:13 | call to A.init() | test.swift:179:7:179:7 | SSA def(a) | +| test.swift:179:7:179:7 | a | test.swift:179:7:179:7 | SSA def(a) | +| test.swift:179:11:179:13 | call to A.init() | test.swift:179:7:179:7 | a | | test.swift:180:3:180:3 | [post] a | test.swift:181:13:181:13 | a | | test.swift:180:3:180:3 | a | test.swift:181:13:181:13 | a | | test.swift:184:7:184:7 | SSA def(self) | test.swift:184:7:184:7 | self[return] | @@ -142,23 +174,28 @@ | test.swift:188:5:188:5 | [post] self | test.swift:187:3:189:3 | self[return] | | test.swift:188:5:188:5 | self | test.swift:187:3:189:3 | self[return] | | test.swift:193:7:193:7 | SSA def(b) | test.swift:194:3:194:3 | b | -| test.swift:193:11:193:13 | call to B.init() | test.swift:193:7:193:7 | SSA def(b) | +| test.swift:193:7:193:7 | b | test.swift:193:7:193:7 | SSA def(b) | +| test.swift:193:11:193:13 | call to B.init() | test.swift:193:7:193:7 | b | | test.swift:194:3:194:3 | [post] b | test.swift:195:13:195:13 | b | | test.swift:194:3:194:3 | b | test.swift:195:13:195:13 | b | | test.swift:199:7:199:7 | SSA def(a) | test.swift:200:3:200:3 | a | -| test.swift:199:11:199:13 | call to A.init() | test.swift:199:7:199:7 | SSA def(a) | +| test.swift:199:7:199:7 | a | test.swift:199:7:199:7 | SSA def(a) | +| test.swift:199:11:199:13 | call to A.init() | test.swift:199:7:199:7 | a | | test.swift:200:3:200:3 | [post] a | test.swift:201:13:201:13 | a | | test.swift:200:3:200:3 | a | test.swift:201:13:201:13 | a | | test.swift:205:7:205:7 | SSA def(a) | test.swift:206:3:206:3 | a | -| test.swift:205:11:205:13 | call to A.init() | test.swift:205:7:205:7 | SSA def(a) | +| test.swift:205:7:205:7 | a | test.swift:205:7:205:7 | SSA def(a) | +| test.swift:205:11:205:13 | call to A.init() | test.swift:205:7:205:7 | a | | test.swift:206:3:206:3 | [post] a | test.swift:207:13:207:13 | a | | test.swift:206:3:206:3 | a | test.swift:207:13:207:13 | a | | test.swift:211:7:211:7 | SSA def(a) | test.swift:212:3:212:3 | a | -| test.swift:211:11:211:13 | call to A.init() | test.swift:211:7:211:7 | SSA def(a) | +| test.swift:211:7:211:7 | a | test.swift:211:7:211:7 | SSA def(a) | +| test.swift:211:11:211:13 | call to A.init() | test.swift:211:7:211:7 | a | | test.swift:212:3:212:3 | [post] a | test.swift:213:13:213:13 | a | | test.swift:212:3:212:3 | a | test.swift:213:13:213:13 | a | | test.swift:217:7:217:7 | SSA def(b) | test.swift:218:3:218:3 | b | -| test.swift:217:11:217:13 | call to B.init() | test.swift:217:7:217:7 | SSA def(b) | +| test.swift:217:7:217:7 | b | test.swift:217:7:217:7 | SSA def(b) | +| test.swift:217:11:217:13 | call to B.init() | test.swift:217:7:217:7 | b | | test.swift:218:3:218:3 | [post] b | test.swift:219:13:219:13 | b | | test.swift:218:3:218:3 | b | test.swift:219:13:219:13 | b | | test.swift:222:7:222:7 | SSA def(self) | test.swift:222:7:222:7 | self[return] | @@ -171,7 +208,8 @@ | test.swift:227:5:227:5 | SSA def(self) | test.swift:227:5:229:5 | self[return] | | test.swift:227:5:227:5 | self | test.swift:227:5:227:5 | SSA def(self) | | test.swift:234:7:234:7 | SSA def(a) | test.swift:235:13:235:13 | a | -| test.swift:234:11:234:31 | call to HasComputedProperty.init() | test.swift:234:7:234:7 | SSA def(a) | +| test.swift:234:7:234:7 | a | test.swift:234:7:234:7 | SSA def(a) | +| test.swift:234:11:234:31 | call to HasComputedProperty.init() | test.swift:234:7:234:7 | a | | test.swift:235:13:235:13 | [post] a | test.swift:237:3:237:3 | a | | test.swift:235:13:235:13 | a | test.swift:237:3:237:3 | a | | test.swift:237:3:237:3 | [post] a | test.swift:238:13:238:13 | a | @@ -188,11 +226,13 @@ | test.swift:246:5:246:5 | self | test.swift:246:5:246:5 | SSA def(self) | | test.swift:247:9:247:9 | [post] self | test.swift:246:5:248:5 | self[return] | | test.swift:247:9:247:9 | self | test.swift:246:5:248:5 | self[return] | +| test.swift:252:6:252:27 | call to DidSetSource.init(wrappedValue:) | test.swift:252:23:252:23 | x | | test.swift:252:23:252:23 | value | test.swift:252:23:252:23 | SSA def(value) | | test.swift:262:21:262:27 | SSA def(y) | test.swift:266:15:266:15 | y | | test.swift:262:21:262:27 | y | test.swift:262:21:262:27 | SSA def(y) | | test.swift:263:9:263:9 | SSA def(x) | test.swift:265:15:265:15 | x | -| test.swift:263:13:263:28 | call to optionalSource() | test.swift:263:9:263:9 | SSA def(x) | +| test.swift:263:9:263:9 | x | test.swift:263:9:263:9 | SSA def(x) | +| test.swift:263:13:263:28 | call to optionalSource() | test.swift:263:9:263:9 | x | | test.swift:265:15:265:15 | x | test.swift:267:15:267:15 | x | | test.swift:266:15:266:15 | y | test.swift:268:15:268:15 | y | | test.swift:267:15:267:15 | x | test.swift:267:15:267:16 | ...! | @@ -241,42 +281,57 @@ | test.swift:282:26:282:26 | y | test.swift:287:16:287:16 | y | | test.swift:282:26:282:27 | ...! | test.swift:282:15:282:38 | ... ? ... : ... | | test.swift:282:31:282:38 | call to source() | test.swift:282:15:282:38 | ... ? ... : ... | -| test.swift:284:8:284:12 | SSA def(z) | test.swift:285:19:285:19 | z | -| test.swift:284:16:284:16 | x | test.swift:284:8:284:12 | SSA def(z) | +| test.swift:284:12:284:12 | SSA def(z) | test.swift:285:19:285:19 | z | +| test.swift:284:12:284:12 | z | test.swift:284:12:284:12 | SSA def(z) | +| test.swift:284:16:284:16 | x | test.swift:284:8:284:12 | let ...? | | test.swift:284:16:284:16 | x | test.swift:291:16:291:16 | x | -| test.swift:287:8:287:12 | SSA def(z) | test.swift:288:19:288:19 | z | -| test.swift:287:16:287:16 | y | test.swift:287:8:287:12 | SSA def(z) | +| test.swift:287:12:287:12 | SSA def(z) | test.swift:288:19:288:19 | z | +| test.swift:287:12:287:12 | z | test.swift:287:12:287:12 | SSA def(z) | +| test.swift:287:16:287:16 | y | test.swift:287:8:287:12 | let ...? | | test.swift:287:16:287:16 | y | test.swift:294:16:294:16 | y | -| test.swift:291:8:291:12 | SSA def(z) | test.swift:292:19:292:19 | z | +| test.swift:291:12:291:12 | SSA def(z) | test.swift:292:19:292:19 | z | +| test.swift:291:12:291:12 | z | test.swift:291:12:291:12 | SSA def(z) | | test.swift:291:16:291:16 | x | test.swift:291:16:291:17 | ...? | | test.swift:291:16:291:16 | x | test.swift:298:20:298:20 | x | -| test.swift:291:16:291:26 | OptionalEvaluationExpr | test.swift:291:8:291:12 | SSA def(z) | +| test.swift:291:16:291:26 | OptionalEvaluationExpr | test.swift:291:8:291:12 | let ...? | | test.swift:291:16:291:26 | call to signum() | test.swift:291:16:291:26 | OptionalEvaluationExpr | -| test.swift:294:8:294:12 | SSA def(z) | test.swift:295:19:295:19 | z | +| test.swift:294:12:294:12 | SSA def(z) | test.swift:295:19:295:19 | z | +| test.swift:294:12:294:12 | z | test.swift:294:12:294:12 | SSA def(z) | | test.swift:294:16:294:16 | y | test.swift:294:16:294:17 | ...? | | test.swift:294:16:294:16 | y | test.swift:299:20:299:20 | y | -| test.swift:294:16:294:26 | OptionalEvaluationExpr | test.swift:294:8:294:12 | SSA def(z) | +| test.swift:294:16:294:26 | OptionalEvaluationExpr | test.swift:294:8:294:12 | let ...? | | test.swift:294:16:294:26 | call to signum() | test.swift:294:16:294:26 | OptionalEvaluationExpr | -| test.swift:298:11:298:15 | SSA def(z1) | test.swift:300:15:300:15 | z1 | -| test.swift:298:20:298:20 | x | test.swift:298:11:298:15 | SSA def(z1) | +| test.swift:298:15:298:15 | SSA def(z1) | test.swift:300:15:300:15 | z1 | +| test.swift:298:15:298:15 | z1 | test.swift:298:15:298:15 | SSA def(z1) | +| test.swift:298:20:298:20 | x | test.swift:298:11:298:15 | let ...? | | test.swift:298:20:298:20 | x | test.swift:303:15:303:15 | x | -| test.swift:299:11:299:15 | SSA def(z2) | test.swift:301:15:301:15 | z2 | -| test.swift:299:20:299:20 | y | test.swift:299:11:299:15 | SSA def(z2) | +| test.swift:299:15:299:15 | SSA def(z2) | test.swift:301:15:301:15 | z2 | +| test.swift:299:15:299:15 | z2 | test.swift:299:15:299:15 | SSA def(z2) | +| test.swift:299:20:299:20 | y | test.swift:299:11:299:15 | let ...? | | test.swift:299:20:299:20 | y | test.swift:304:15:304:15 | y | | test.swift:303:15:303:15 | x | test.swift:303:15:303:16 | ...! | | test.swift:303:15:303:15 | x | test.swift:306:28:306:28 | x | | test.swift:304:15:304:15 | y | test.swift:304:15:304:16 | ...! | | test.swift:304:15:304:15 | y | test.swift:309:28:309:28 | y | -| test.swift:306:13:306:24 | SSA def(z) | test.swift:307:19:307:19 | z | -| test.swift:306:28:306:28 | x | test.swift:306:13:306:24 | SSA def(z) | +| test.swift:306:23:306:23 | SSA def(z) | test.swift:307:19:307:19 | z | +| test.swift:306:23:306:23 | z | test.swift:306:23:306:23 | SSA def(z) | +| test.swift:306:28:306:28 | x | test.swift:306:13:306:24 | .some(...) | | test.swift:306:28:306:28 | x | test.swift:313:12:313:12 | x | -| test.swift:309:13:309:24 | SSA def(z) | test.swift:310:19:310:19 | z | -| test.swift:309:28:309:28 | y | test.swift:309:13:309:24 | SSA def(z) | +| test.swift:309:23:309:23 | SSA def(z) | test.swift:310:19:310:19 | z | +| test.swift:309:23:309:23 | z | test.swift:309:23:309:23 | SSA def(z) | +| test.swift:309:28:309:28 | y | test.swift:309:13:309:24 | .some(...) | | test.swift:309:28:309:28 | y | test.swift:319:12:319:12 | y | -| test.swift:314:10:314:21 | SSA def(z) | test.swift:315:19:315:19 | z | -| test.swift:320:10:320:21 | SSA def(z) | test.swift:321:19:321:19 | z | +| test.swift:313:12:313:12 | x | test.swift:314:10:314:21 | .some(...) | +| test.swift:313:12:313:12 | x | test.swift:316:10:316:11 | .none | +| test.swift:314:20:314:20 | SSA def(z) | test.swift:315:19:315:19 | z | +| test.swift:314:20:314:20 | z | test.swift:314:20:314:20 | SSA def(z) | +| test.swift:319:12:319:12 | y | test.swift:320:10:320:21 | .some(...) | +| test.swift:319:12:319:12 | y | test.swift:322:10:322:11 | .none | +| test.swift:320:20:320:20 | SSA def(z) | test.swift:321:19:321:19 | z | +| test.swift:320:20:320:20 | z | test.swift:320:20:320:20 | SSA def(z) | | test.swift:331:9:331:9 | SSA def(t1) | test.swift:333:15:333:15 | t1 | -| test.swift:331:14:331:26 | (...) | test.swift:331:9:331:9 | SSA def(t1) | +| test.swift:331:9:331:9 | t1 | test.swift:331:9:331:9 | SSA def(t1) | +| test.swift:331:14:331:26 | (...) | test.swift:331:9:331:9 | t1 | | test.swift:333:15:333:15 | t1 | test.swift:334:15:334:15 | t1 | | test.swift:334:15:334:15 | [post] t1 | test.swift:335:15:335:15 | t1 | | test.swift:334:15:334:15 | t1 | test.swift:335:15:335:15 | t1 | @@ -295,16 +350,19 @@ | test.swift:346:15:346:15 | [post] t1 | test.swift:347:15:347:15 | t1 | | test.swift:346:15:346:15 | t1 | test.swift:347:15:347:15 | t1 | | test.swift:351:9:351:9 | SSA def(t1) | test.swift:352:14:352:14 | t1 | -| test.swift:351:14:351:45 | (...) | test.swift:351:9:351:9 | SSA def(t1) | +| test.swift:351:9:351:9 | t1 | test.swift:351:9:351:9 | SSA def(t1) | +| test.swift:351:14:351:45 | (...) | test.swift:351:9:351:9 | t1 | | test.swift:352:9:352:9 | SSA def(t2) | test.swift:359:15:359:15 | t2 | -| test.swift:352:14:352:14 | t1 | test.swift:352:9:352:9 | SSA def(t2) | +| test.swift:352:9:352:9 | t2 | test.swift:352:9:352:9 | SSA def(t2) | +| test.swift:352:14:352:14 | t1 | test.swift:352:9:352:9 | t2 | | test.swift:352:14:352:14 | t1 | test.swift:353:21:353:21 | t1 | -| test.swift:353:9:353:17 | SSA def(a) | test.swift:363:15:363:15 | a | -| test.swift:353:9:353:17 | SSA def(b) | test.swift:364:15:364:15 | b | -| test.swift:353:9:353:17 | SSA def(c) | test.swift:365:15:365:15 | c | -| test.swift:353:21:353:21 | t1 | test.swift:353:9:353:17 | SSA def(a) | -| test.swift:353:21:353:21 | t1 | test.swift:353:9:353:17 | SSA def(b) | -| test.swift:353:21:353:21 | t1 | test.swift:353:9:353:17 | SSA def(c) | +| test.swift:353:10:353:10 | SSA def(a) | test.swift:363:15:363:15 | a | +| test.swift:353:10:353:10 | a | test.swift:353:10:353:10 | SSA def(a) | +| test.swift:353:13:353:13 | SSA def(b) | test.swift:364:15:364:15 | b | +| test.swift:353:13:353:13 | b | test.swift:353:13:353:13 | SSA def(b) | +| test.swift:353:16:353:16 | SSA def(c) | test.swift:365:15:365:15 | c | +| test.swift:353:16:353:16 | c | test.swift:353:16:353:16 | SSA def(c) | +| test.swift:353:21:353:21 | t1 | test.swift:353:9:353:17 | (...) | | test.swift:353:21:353:21 | t1 | test.swift:355:15:355:15 | t1 | | test.swift:355:15:355:15 | t1 | test.swift:356:15:356:15 | t1 | | test.swift:356:15:356:15 | [post] t1 | test.swift:357:15:357:15 | t1 | @@ -316,107 +374,230 @@ | test.swift:360:15:360:15 | t2 | test.swift:361:15:361:15 | t2 | | test.swift:361:15:361:15 | [post] t2 | test.swift:362:15:362:15 | t2 | | test.swift:361:15:361:15 | t2 | test.swift:362:15:362:15 | t2 | -| test.swift:375:9:375:13 | SSA def(a) | test.swift:377:12:377:12 | a | -| test.swift:375:22:375:23 | .myNone | test.swift:375:9:375:13 | SSA def(a) | -| test.swift:377:12:377:12 | a | test.swift:387:32:387:32 | a | -| test.swift:380:10:380:25 | SSA def(a) | test.swift:381:19:381:19 | a | -| test.swift:382:10:382:30 | SSA def(a) | test.swift:383:19:383:19 | a | -| test.swift:382:10:382:30 | SSA def(b) | test.swift:384:19:384:19 | b | -| test.swift:387:13:387:28 | SSA def(x) | test.swift:388:19:388:19 | x | -| test.swift:387:32:387:32 | a | test.swift:387:13:387:28 | SSA def(x) | -| test.swift:387:32:387:32 | a | test.swift:390:37:390:37 | a | -| test.swift:390:13:390:33 | SSA def(x) | test.swift:391:19:391:19 | x | -| test.swift:390:13:390:33 | SSA def(y) | test.swift:392:19:392:19 | y | -| test.swift:390:37:390:37 | a | test.swift:407:32:407:32 | a | -| test.swift:395:9:395:13 | SSA def(b) | test.swift:397:12:397:12 | b | -| test.swift:395:22:395:40 | call to ... | test.swift:395:9:395:13 | SSA def(b) | -| test.swift:400:10:400:25 | SSA def(a) | test.swift:401:19:401:19 | a | -| test.swift:402:10:402:30 | SSA def(a) | test.swift:403:19:403:19 | a | -| test.swift:402:10:402:30 | SSA def(b) | test.swift:404:19:404:19 | b | -| test.swift:407:13:407:28 | SSA def(x) | test.swift:408:19:408:19 | x | -| test.swift:407:32:407:32 | a | test.swift:407:13:407:28 | SSA def(x) | -| test.swift:407:32:407:32 | a | test.swift:410:37:410:37 | a | -| test.swift:410:13:410:33 | SSA def(x) | test.swift:411:19:411:19 | x | -| test.swift:410:13:410:33 | SSA def(y) | test.swift:412:19:412:19 | y | -| test.swift:410:37:410:37 | a | test.swift:427:32:427:32 | a | -| test.swift:415:9:415:9 | SSA def(c) | test.swift:417:12:417:12 | c | -| test.swift:415:13:415:38 | call to ... | test.swift:415:9:415:9 | SSA def(c) | -| test.swift:420:10:420:25 | SSA def(a) | test.swift:421:19:421:19 | a | -| test.swift:422:10:422:30 | SSA def(a) | test.swift:423:19:423:19 | a | -| test.swift:422:10:422:30 | SSA def(b) | test.swift:424:19:424:19 | b | -| test.swift:427:13:427:28 | SSA def(x) | test.swift:428:19:428:19 | x | -| test.swift:427:32:427:32 | a | test.swift:427:13:427:28 | SSA def(x) | -| test.swift:427:32:427:32 | a | test.swift:430:37:430:37 | a | -| test.swift:430:13:430:33 | SSA def(x) | test.swift:431:19:431:19 | x | -| test.swift:430:13:430:33 | SSA def(y) | test.swift:432:19:432:19 | y | -| test.swift:438:21:438:27 | SSA def(y) | test.swift:441:27:441:27 | y | -| test.swift:438:21:438:27 | SSA def(y) | test.swift:446:22:446:22 | y | -| test.swift:438:21:438:27 | y | test.swift:438:21:438:27 | SSA def(y) | -| test.swift:439:9:439:9 | SSA def(x) | test.swift:441:16:441:16 | x | -| test.swift:439:13:439:28 | call to optionalSource() | test.swift:439:9:439:9 | SSA def(x) | -| test.swift:441:8:441:12 | SSA def(a) | test.swift:442:19:442:19 | a | -| test.swift:441:16:441:16 | x | test.swift:441:8:441:12 | SSA def(a) | -| test.swift:441:16:441:16 | x | test.swift:446:19:446:19 | x | -| test.swift:441:19:441:23 | SSA def(b) | test.swift:443:19:443:19 | b | -| test.swift:441:27:441:27 | y | test.swift:441:19:441:23 | SSA def(b) | -| test.swift:441:27:441:27 | y | test.swift:446:22:446:22 | y | -| test.swift:446:9:446:9 | SSA def(tuple1) | test.swift:447:12:447:12 | tuple1 | -| test.swift:446:18:446:23 | (...) | test.swift:446:9:446:9 | SSA def(tuple1) | -| test.swift:448:10:448:37 | SSA def(a) | test.swift:449:19:449:19 | a | -| test.swift:448:10:448:37 | SSA def(b) | test.swift:450:19:450:19 | b | -| test.swift:455:8:455:17 | SSA def(x) | test.swift:456:19:456:19 | x | -| test.swift:455:8:455:17 | SSA def(y) | test.swift:457:19:457:19 | y | -| test.swift:461:7:461:7 | SSA def(self) | test.swift:461:7:461:7 | self[return] | -| test.swift:461:7:461:7 | SSA def(self) | test.swift:461:7:461:7 | self[return] | -| test.swift:461:7:461:7 | self | test.swift:461:7:461:7 | SSA def(self) | -| test.swift:461:7:461:7 | self | test.swift:461:7:461:7 | SSA def(self) | -| test.swift:462:9:462:9 | self | test.swift:462:9:462:9 | SSA def(self) | -| test.swift:462:9:462:9 | self | test.swift:462:9:462:9 | SSA def(self) | -| test.swift:462:9:462:9 | self | test.swift:462:9:462:9 | SSA def(self) | -| test.swift:462:9:462:9 | value | test.swift:462:9:462:9 | SSA def(value) | -| test.swift:465:33:465:39 | SSA def(y) | test.swift:470:12:470:12 | y | -| test.swift:465:33:465:39 | y | test.swift:465:33:465:39 | SSA def(y) | -| test.swift:466:9:466:9 | SSA def(x) | test.swift:468:12:468:12 | x | -| test.swift:466:13:466:28 | call to optionalSource() | test.swift:466:9:466:9 | SSA def(x) | -| test.swift:467:9:467:9 | SSA def(cx) | test.swift:468:5:468:5 | cx | -| test.swift:467:14:467:16 | call to C.init() | test.swift:467:9:467:9 | SSA def(cx) | -| test.swift:468:5:468:5 | [post] cx | test.swift:472:20:472:20 | cx | -| test.swift:468:5:468:5 | cx | test.swift:472:20:472:20 | cx | -| test.swift:469:9:469:9 | SSA def(cy) | test.swift:470:5:470:5 | cy | -| test.swift:469:14:469:16 | call to C.init() | test.swift:469:9:469:9 | SSA def(cy) | -| test.swift:470:5:470:5 | [post] cy | test.swift:474:20:474:20 | cy | -| test.swift:470:5:470:5 | cy | test.swift:474:20:474:20 | cy | -| test.swift:472:11:472:15 | SSA def(z1) | test.swift:473:15:473:15 | z1 | -| test.swift:472:20:472:23 | .x | test.swift:472:11:472:15 | SSA def(z1) | -| test.swift:474:11:474:15 | SSA def(z2) | test.swift:475:15:475:15 | z2 | -| test.swift:474:20:474:23 | .x | test.swift:474:11:474:15 | SSA def(z2) | -| test.swift:479:14:479:21 | call to source() | test.swift:479:13:479:21 | call to +(_:) | -| test.swift:487:7:487:7 | SSA def(self) | test.swift:487:7:487:7 | self[return] | -| test.swift:487:7:487:7 | self | test.swift:487:7:487:7 | SSA def(self) | -| test.swift:488:9:488:9 | self | test.swift:488:9:488:9 | SSA def(self) | -| test.swift:488:9:488:9 | self | test.swift:488:9:488:9 | SSA def(self) | -| test.swift:488:9:488:9 | self | test.swift:488:9:488:9 | SSA def(self) | -| test.swift:488:9:488:9 | value | test.swift:488:9:488:9 | SSA def(value) | -| test.swift:489:5:489:5 | SSA def(self) | test.swift:490:7:490:7 | self | -| test.swift:489:5:489:5 | self | test.swift:489:5:489:5 | SSA def(self) | -| test.swift:489:10:489:13 | SSA def(s) | test.swift:490:13:490:13 | s | -| test.swift:489:10:489:13 | s | test.swift:489:10:489:13 | SSA def(s) | -| test.swift:490:7:490:7 | [post] self | test.swift:489:5:491:5 | self[return] | -| test.swift:490:7:490:7 | self | test.swift:489:5:491:5 | self[return] | -| test.swift:495:17:495:17 | SSA def(self) | test.swift:496:7:496:7 | self | -| test.swift:495:17:495:17 | self | test.swift:495:17:495:17 | SSA def(self) | -| test.swift:496:7:496:7 | [post] self | test.swift:497:17:497:17 | self | -| test.swift:496:7:496:7 | self | test.swift:497:17:497:17 | self | -| test.swift:497:17:497:17 | [post] self | test.swift:495:17:498:5 | self[return] | -| test.swift:497:17:497:17 | self | test.swift:495:17:498:5 | self[return] | -| test.swift:501:21:501:27 | SSA def(path) | test.swift:503:37:503:37 | path | -| test.swift:501:21:501:27 | path | test.swift:501:21:501:27 | SSA def(path) | -| test.swift:506:7:506:7 | SSA def(self) | test.swift:506:7:506:7 | self[return] | -| test.swift:506:7:506:7 | self | test.swift:506:7:506:7 | SSA def(self) | -| test.swift:507:3:507:3 | SSA def(self) | test.swift:507:3:507:40 | self[return] | -| test.swift:507:3:507:3 | self | test.swift:507:3:507:3 | SSA def(self) | -| test.swift:507:27:507:38 | SSA def(n) | test.swift:507:3:507:40 | n[return] | -| test.swift:507:31:507:38 | call to source() | test.swift:507:27:507:38 | SSA def(n) | -| test.swift:513:7:513:7 | SSA def(n) | test.swift:514:36:514:36 | n | -| test.swift:513:11:513:11 | 0 | test.swift:513:7:513:7 | SSA def(n) | -| test.swift:514:36:514:36 | n | test.swift:514:35:514:36 | &... | +| test.swift:376:9:376:9 | SSA def(a) | test.swift:378:12:378:12 | a | +| test.swift:376:9:376:9 | a | test.swift:376:9:376:9 | SSA def(a) | +| test.swift:376:9:376:13 | ... as ... | test.swift:376:9:376:9 | a | +| test.swift:376:22:376:23 | .myNone | test.swift:376:9:376:13 | ... as ... | +| test.swift:378:12:378:12 | a | test.swift:379:10:379:11 | .myNone | +| test.swift:378:12:378:12 | a | test.swift:381:10:381:25 | .mySingle(...) | +| test.swift:378:12:378:12 | a | test.swift:383:10:383:30 | .myPair(...) | +| test.swift:378:12:378:12 | a | test.swift:386:14:386:26 | .myCons(...) | +| test.swift:378:12:378:12 | a | test.swift:390:32:390:32 | a | +| test.swift:381:24:381:24 | SSA def(a) | test.swift:382:19:382:19 | a | +| test.swift:381:24:381:24 | a | test.swift:381:24:381:24 | SSA def(a) | +| test.swift:383:22:383:22 | SSA def(a) | test.swift:384:19:384:19 | a | +| test.swift:383:22:383:22 | a | test.swift:383:22:383:22 | SSA def(a) | +| test.swift:383:29:383:29 | SSA def(b) | test.swift:385:19:385:19 | b | +| test.swift:383:29:383:29 | b | test.swift:383:29:383:29 | SSA def(b) | +| test.swift:386:10:386:26 | SSA phi(a) | test.swift:387:19:387:19 | a | +| test.swift:386:22:386:22 | SSA def(a) | test.swift:386:10:386:26 | SSA phi(a) | +| test.swift:386:22:386:22 | a | test.swift:386:22:386:22 | SSA def(a) | +| test.swift:390:27:390:27 | SSA def(x) | test.swift:391:19:391:19 | x | +| test.swift:390:27:390:27 | x | test.swift:390:27:390:27 | SSA def(x) | +| test.swift:390:32:390:32 | a | test.swift:390:13:390:28 | .mySingle(...) | +| test.swift:390:32:390:32 | a | test.swift:393:37:393:37 | a | +| test.swift:393:25:393:25 | SSA def(x) | test.swift:394:19:394:19 | x | +| test.swift:393:25:393:25 | x | test.swift:393:25:393:25 | SSA def(x) | +| test.swift:393:32:393:32 | SSA def(y) | test.swift:395:19:395:19 | y | +| test.swift:393:32:393:32 | y | test.swift:393:32:393:32 | SSA def(y) | +| test.swift:393:37:393:37 | a | test.swift:393:13:393:33 | .myPair(...) | +| test.swift:398:5:398:27 | SSA def(a) | test.swift:400:12:400:12 | a | +| test.swift:398:9:398:27 | call to ... | test.swift:398:5:398:27 | SSA def(a) | +| test.swift:400:12:400:12 | a | test.swift:401:10:401:11 | .myNone | +| test.swift:400:12:400:12 | a | test.swift:403:10:403:25 | .mySingle(...) | +| test.swift:400:12:400:12 | a | test.swift:405:10:405:30 | .myPair(...) | +| test.swift:400:12:400:12 | a | test.swift:408:14:408:26 | .myCons(...) | +| test.swift:400:12:400:12 | a | test.swift:412:32:412:32 | a | +| test.swift:403:24:403:24 | SSA def(a) | test.swift:404:19:404:19 | a | +| test.swift:403:24:403:24 | a | test.swift:403:24:403:24 | SSA def(a) | +| test.swift:405:22:405:22 | SSA def(a) | test.swift:406:19:406:19 | a | +| test.swift:405:22:405:22 | a | test.swift:405:22:405:22 | SSA def(a) | +| test.swift:405:29:405:29 | SSA def(b) | test.swift:407:19:407:19 | b | +| test.swift:405:29:405:29 | b | test.swift:405:29:405:29 | SSA def(b) | +| test.swift:408:10:408:26 | SSA phi(a) | test.swift:409:19:409:19 | a | +| test.swift:408:22:408:22 | SSA def(a) | test.swift:408:10:408:26 | SSA phi(a) | +| test.swift:408:22:408:22 | a | test.swift:408:22:408:22 | SSA def(a) | +| test.swift:412:27:412:27 | SSA def(x) | test.swift:413:19:413:19 | x | +| test.swift:412:27:412:27 | x | test.swift:412:27:412:27 | SSA def(x) | +| test.swift:412:32:412:32 | a | test.swift:412:13:412:28 | .mySingle(...) | +| test.swift:412:32:412:32 | a | test.swift:415:37:415:37 | a | +| test.swift:415:25:415:25 | SSA def(x) | test.swift:416:19:416:19 | x | +| test.swift:415:25:415:25 | x | test.swift:415:25:415:25 | SSA def(x) | +| test.swift:415:32:415:32 | SSA def(y) | test.swift:417:19:417:19 | y | +| test.swift:415:32:415:32 | y | test.swift:415:32:415:32 | SSA def(y) | +| test.swift:415:37:415:37 | a | test.swift:415:13:415:33 | .myPair(...) | +| test.swift:420:5:420:34 | SSA def(a) | test.swift:422:12:422:12 | a | +| test.swift:420:9:420:34 | call to ... | test.swift:420:5:420:34 | SSA def(a) | +| test.swift:422:12:422:12 | a | test.swift:423:10:423:11 | .myNone | +| test.swift:422:12:422:12 | a | test.swift:425:10:425:25 | .mySingle(...) | +| test.swift:422:12:422:12 | a | test.swift:427:10:427:30 | .myPair(...) | +| test.swift:422:12:422:12 | a | test.swift:430:14:430:26 | .myCons(...) | +| test.swift:422:12:422:12 | a | test.swift:434:32:434:32 | a | +| test.swift:425:24:425:24 | SSA def(a) | test.swift:426:19:426:19 | a | +| test.swift:425:24:425:24 | a | test.swift:425:24:425:24 | SSA def(a) | +| test.swift:427:22:427:22 | SSA def(a) | test.swift:428:19:428:19 | a | +| test.swift:427:22:427:22 | a | test.swift:427:22:427:22 | SSA def(a) | +| test.swift:427:29:427:29 | SSA def(b) | test.swift:429:19:429:19 | b | +| test.swift:427:29:427:29 | b | test.swift:427:29:427:29 | SSA def(b) | +| test.swift:430:10:430:26 | SSA phi(a) | test.swift:431:19:431:19 | a | +| test.swift:430:22:430:22 | SSA def(a) | test.swift:430:10:430:26 | SSA phi(a) | +| test.swift:430:22:430:22 | a | test.swift:430:22:430:22 | SSA def(a) | +| test.swift:434:27:434:27 | SSA def(x) | test.swift:435:19:435:19 | x | +| test.swift:434:27:434:27 | x | test.swift:434:27:434:27 | SSA def(x) | +| test.swift:434:32:434:32 | a | test.swift:434:13:434:28 | .mySingle(...) | +| test.swift:434:32:434:32 | a | test.swift:437:37:437:37 | a | +| test.swift:437:25:437:25 | SSA def(x) | test.swift:438:19:438:19 | x | +| test.swift:437:25:437:25 | x | test.swift:437:25:437:25 | SSA def(x) | +| test.swift:437:32:437:32 | SSA def(y) | test.swift:439:19:439:19 | y | +| test.swift:437:32:437:32 | y | test.swift:437:32:437:32 | SSA def(y) | +| test.swift:437:37:437:37 | a | test.swift:437:13:437:33 | .myPair(...) | +| test.swift:437:37:437:37 | a | test.swift:442:33:442:33 | a | +| test.swift:442:9:442:9 | SSA def(b) | test.swift:444:12:444:12 | b | +| test.swift:442:9:442:9 | b | test.swift:442:9:442:9 | SSA def(b) | +| test.swift:442:9:442:12 | ... as ... | test.swift:442:9:442:9 | b | +| test.swift:442:21:442:34 | call to ... | test.swift:442:9:442:12 | ... as ... | +| test.swift:442:33:442:33 | [post] a | test.swift:471:13:471:13 | a | +| test.swift:442:33:442:33 | a | test.swift:471:13:471:13 | a | +| test.swift:444:12:444:12 | b | test.swift:445:10:445:11 | .myNone | +| test.swift:444:12:444:12 | b | test.swift:447:10:447:25 | .mySingle(...) | +| test.swift:444:12:444:12 | b | test.swift:449:10:449:30 | .myPair(...) | +| test.swift:444:12:444:12 | b | test.swift:452:14:452:38 | .myCons(...) | +| test.swift:444:12:444:12 | b | test.swift:456:14:456:26 | .myCons(...) | +| test.swift:444:12:444:12 | b | test.swift:467:45:467:45 | b | +| test.swift:447:24:447:24 | SSA def(a) | test.swift:448:19:448:19 | a | +| test.swift:447:24:447:24 | a | test.swift:447:24:447:24 | SSA def(a) | +| test.swift:449:22:449:22 | SSA def(a) | test.swift:450:19:450:19 | a | +| test.swift:449:22:449:22 | a | test.swift:449:22:449:22 | SSA def(a) | +| test.swift:449:29:449:29 | SSA def(b) | test.swift:451:19:451:19 | b | +| test.swift:449:29:449:29 | b | test.swift:449:29:449:29 | SSA def(b) | +| test.swift:452:10:452:38 | SSA phi(a) | test.swift:453:19:453:19 | a | +| test.swift:452:10:452:38 | SSA phi(b) | test.swift:454:19:454:19 | b | +| test.swift:452:10:452:38 | SSA phi(c) | test.swift:455:19:455:19 | c | +| test.swift:452:22:452:22 | SSA def(a) | test.swift:452:10:452:38 | SSA phi(a) | +| test.swift:452:22:452:22 | a | test.swift:452:22:452:22 | SSA def(a) | +| test.swift:452:33:452:33 | SSA def(b) | test.swift:452:10:452:38 | SSA phi(b) | +| test.swift:452:33:452:33 | b | test.swift:452:33:452:33 | SSA def(b) | +| test.swift:452:36:452:36 | SSA def(c) | test.swift:452:10:452:38 | SSA phi(c) | +| test.swift:452:36:452:36 | c | test.swift:452:36:452:36 | SSA def(c) | +| test.swift:456:10:456:26 | SSA phi(a) | test.swift:457:19:457:19 | a | +| test.swift:456:22:456:22 | SSA def(a) | test.swift:456:10:456:26 | SSA phi(a) | +| test.swift:456:22:456:22 | a | test.swift:456:22:456:22 | SSA def(a) | +| test.swift:460:27:460:27 | SSA def(x) | test.swift:461:19:461:19 | x | +| test.swift:460:27:460:27 | x | test.swift:460:27:460:27 | SSA def(x) | +| test.swift:460:32:460:57 | call to ... | test.swift:460:13:460:28 | .mySingle(...) | +| test.swift:463:31:463:31 | SSA def(x) | test.swift:464:19:464:19 | x | +| test.swift:463:31:463:31 | x | test.swift:463:31:463:31 | SSA def(x) | +| test.swift:463:38:463:38 | SSA def(y) | test.swift:465:19:465:19 | y | +| test.swift:463:38:463:38 | y | test.swift:463:38:463:38 | SSA def(y) | +| test.swift:463:43:463:62 | call to ... | test.swift:463:13:463:39 | .myPair(...) | +| test.swift:467:13:467:41 | SSA phi(c) | test.swift:468:19:468:19 | c | +| test.swift:467:39:467:39 | SSA def(c) | test.swift:467:13:467:41 | SSA phi(c) | +| test.swift:467:39:467:39 | c | test.swift:467:39:467:39 | SSA def(c) | +| test.swift:467:45:467:45 | b | test.swift:467:17:467:41 | .myCons(...) | +| test.swift:467:45:467:45 | b | test.swift:471:16:471:16 | b | +| test.swift:471:12:471:17 | (...) | test.swift:472:14:472:55 | (...) | +| test.swift:471:12:471:17 | (...) | test.swift:478:5:478:5 | _ | +| test.swift:472:10:472:55 | SSA phi(a) | test.swift:473:19:473:19 | a | +| test.swift:472:10:472:55 | SSA phi(b) | test.swift:474:19:474:19 | b | +| test.swift:472:10:472:55 | SSA phi(c) | test.swift:475:19:475:19 | c | +| test.swift:472:10:472:55 | SSA phi(d) | test.swift:476:19:476:19 | d | +| test.swift:472:10:472:55 | SSA phi(e) | test.swift:477:19:477:19 | e | +| test.swift:472:23:472:23 | SSA def(a) | test.swift:472:10:472:55 | SSA phi(a) | +| test.swift:472:23:472:23 | a | test.swift:472:23:472:23 | SSA def(a) | +| test.swift:472:26:472:26 | SSA def(b) | test.swift:472:10:472:55 | SSA phi(b) | +| test.swift:472:26:472:26 | b | test.swift:472:26:472:26 | SSA def(b) | +| test.swift:472:38:472:38 | SSA def(c) | test.swift:472:10:472:55 | SSA phi(c) | +| test.swift:472:38:472:38 | c | test.swift:472:38:472:38 | SSA def(c) | +| test.swift:472:49:472:49 | SSA def(d) | test.swift:472:10:472:55 | SSA phi(d) | +| test.swift:472:49:472:49 | d | test.swift:472:49:472:49 | SSA def(d) | +| test.swift:472:52:472:52 | SSA def(e) | test.swift:472:10:472:55 | SSA phi(e) | +| test.swift:472:52:472:52 | e | test.swift:472:52:472:52 | SSA def(e) | +| test.swift:485:21:485:27 | SSA def(y) | test.swift:488:27:488:27 | y | +| test.swift:485:21:485:27 | SSA def(y) | test.swift:493:22:493:22 | y | +| test.swift:485:21:485:27 | y | test.swift:485:21:485:27 | SSA def(y) | +| test.swift:486:9:486:9 | SSA def(x) | test.swift:488:16:488:16 | x | +| test.swift:486:9:486:9 | x | test.swift:486:9:486:9 | SSA def(x) | +| test.swift:486:13:486:28 | call to optionalSource() | test.swift:486:9:486:9 | x | +| test.swift:488:12:488:12 | SSA def(a) | test.swift:488:27:488:27 | SSA phi(a) | +| test.swift:488:12:488:12 | a | test.swift:488:12:488:12 | SSA def(a) | +| test.swift:488:16:488:16 | x | test.swift:488:8:488:12 | let ...? | +| test.swift:488:16:488:16 | x | test.swift:493:19:493:19 | x | +| test.swift:488:23:488:23 | SSA def(b) | test.swift:490:19:490:19 | b | +| test.swift:488:23:488:23 | b | test.swift:488:23:488:23 | SSA def(b) | +| test.swift:488:27:488:27 | SSA phi(a) | test.swift:489:19:489:19 | a | +| test.swift:488:27:488:27 | y | test.swift:488:19:488:23 | let ...? | +| test.swift:488:27:488:27 | y | test.swift:493:22:493:22 | y | +| test.swift:493:9:493:9 | SSA def(tuple1) | test.swift:494:12:494:12 | tuple1 | +| test.swift:493:9:493:9 | tuple1 | test.swift:493:9:493:9 | SSA def(tuple1) | +| test.swift:493:18:493:23 | (...) | test.swift:493:9:493:9 | tuple1 | +| test.swift:494:12:494:12 | tuple1 | test.swift:495:10:495:37 | (...) | +| test.swift:494:12:494:12 | tuple1 | test.swift:498:5:498:5 | _ | +| test.swift:495:21:495:21 | SSA def(a) | test.swift:496:19:496:19 | a | +| test.swift:495:21:495:21 | a | test.swift:495:21:495:21 | SSA def(a) | +| test.swift:495:35:495:35 | SSA def(b) | test.swift:497:19:497:19 | b | +| test.swift:495:35:495:35 | b | test.swift:495:35:495:35 | SSA def(b) | +| test.swift:502:13:502:13 | SSA def(x) | test.swift:503:19:503:19 | x | +| test.swift:502:13:502:13 | x | test.swift:502:13:502:13 | SSA def(x) | +| test.swift:502:16:502:16 | SSA def(y) | test.swift:504:19:504:19 | y | +| test.swift:502:16:502:16 | y | test.swift:502:16:502:16 | SSA def(y) | +| test.swift:502:21:502:29 | call to source2() | test.swift:502:8:502:17 | let ...? | +| test.swift:508:7:508:7 | SSA def(self) | test.swift:508:7:508:7 | self[return] | +| test.swift:508:7:508:7 | SSA def(self) | test.swift:508:7:508:7 | self[return] | +| test.swift:508:7:508:7 | self | test.swift:508:7:508:7 | SSA def(self) | +| test.swift:508:7:508:7 | self | test.swift:508:7:508:7 | SSA def(self) | +| test.swift:509:9:509:9 | self | test.swift:509:9:509:9 | SSA def(self) | +| test.swift:509:9:509:9 | self | test.swift:509:9:509:9 | SSA def(self) | +| test.swift:509:9:509:9 | self | test.swift:509:9:509:9 | SSA def(self) | +| test.swift:509:9:509:9 | value | test.swift:509:9:509:9 | SSA def(value) | +| test.swift:512:33:512:39 | SSA def(y) | test.swift:517:12:517:12 | y | +| test.swift:512:33:512:39 | y | test.swift:512:33:512:39 | SSA def(y) | +| test.swift:513:9:513:9 | SSA def(x) | test.swift:515:12:515:12 | x | +| test.swift:513:9:513:9 | x | test.swift:513:9:513:9 | SSA def(x) | +| test.swift:513:13:513:28 | call to optionalSource() | test.swift:513:9:513:9 | x | +| test.swift:514:9:514:9 | SSA def(cx) | test.swift:515:5:515:5 | cx | +| test.swift:514:9:514:9 | cx | test.swift:514:9:514:9 | SSA def(cx) | +| test.swift:514:14:514:16 | call to C.init() | test.swift:514:9:514:9 | cx | +| test.swift:515:5:515:5 | [post] cx | test.swift:519:20:519:20 | cx | +| test.swift:515:5:515:5 | cx | test.swift:519:20:519:20 | cx | +| test.swift:516:9:516:9 | SSA def(cy) | test.swift:517:5:517:5 | cy | +| test.swift:516:9:516:9 | cy | test.swift:516:9:516:9 | SSA def(cy) | +| test.swift:516:14:516:16 | call to C.init() | test.swift:516:9:516:9 | cy | +| test.swift:517:5:517:5 | [post] cy | test.swift:521:20:521:20 | cy | +| test.swift:517:5:517:5 | cy | test.swift:521:20:521:20 | cy | +| test.swift:519:15:519:15 | SSA def(z1) | test.swift:520:15:520:15 | z1 | +| test.swift:519:15:519:15 | z1 | test.swift:519:15:519:15 | SSA def(z1) | +| test.swift:519:20:519:23 | .x | test.swift:519:11:519:15 | let ...? | +| test.swift:521:15:521:15 | SSA def(z2) | test.swift:522:15:522:15 | z2 | +| test.swift:521:15:521:15 | z2 | test.swift:521:15:521:15 | SSA def(z2) | +| test.swift:521:20:521:23 | .x | test.swift:521:11:521:15 | let ...? | +| test.swift:526:14:526:21 | call to source() | test.swift:526:13:526:21 | call to +(_:) | +| test.swift:534:7:534:7 | SSA def(self) | test.swift:534:7:534:7 | self[return] | +| test.swift:534:7:534:7 | self | test.swift:534:7:534:7 | SSA def(self) | +| test.swift:535:9:535:9 | self | test.swift:535:9:535:9 | SSA def(self) | +| test.swift:535:9:535:9 | self | test.swift:535:9:535:9 | SSA def(self) | +| test.swift:535:9:535:9 | self | test.swift:535:9:535:9 | SSA def(self) | +| test.swift:535:9:535:9 | value | test.swift:535:9:535:9 | SSA def(value) | +| test.swift:536:5:536:5 | SSA def(self) | test.swift:537:7:537:7 | self | +| test.swift:536:5:536:5 | self | test.swift:536:5:536:5 | SSA def(self) | +| test.swift:536:10:536:13 | SSA def(s) | test.swift:537:13:537:13 | s | +| test.swift:536:10:536:13 | s | test.swift:536:10:536:13 | SSA def(s) | +| test.swift:537:7:537:7 | [post] self | test.swift:536:5:538:5 | self[return] | +| test.swift:537:7:537:7 | self | test.swift:536:5:538:5 | self[return] | +| test.swift:542:17:542:17 | SSA def(self) | test.swift:543:7:543:7 | self | +| test.swift:542:17:542:17 | self | test.swift:542:17:542:17 | SSA def(self) | +| test.swift:543:7:543:7 | [post] self | test.swift:544:17:544:17 | self | +| test.swift:543:7:543:7 | self | test.swift:544:17:544:17 | self | +| test.swift:544:17:544:17 | [post] self | test.swift:542:17:545:5 | self[return] | +| test.swift:544:17:544:17 | self | test.swift:542:17:545:5 | self[return] | +| test.swift:548:21:548:27 | SSA def(path) | test.swift:550:37:550:37 | path | +| test.swift:548:21:548:27 | path | test.swift:548:21:548:27 | SSA def(path) | +| test.swift:553:7:553:7 | SSA def(self) | test.swift:553:7:553:7 | self[return] | +| test.swift:553:7:553:7 | self | test.swift:553:7:553:7 | SSA def(self) | +| test.swift:554:3:554:3 | SSA def(self) | test.swift:554:3:554:40 | self[return] | +| test.swift:554:3:554:3 | self | test.swift:554:3:554:3 | SSA def(self) | +| test.swift:554:27:554:38 | SSA def(n) | test.swift:554:3:554:40 | n[return] | +| test.swift:554:31:554:38 | call to source() | test.swift:554:27:554:38 | SSA def(n) | +| test.swift:560:7:560:7 | SSA def(n) | test.swift:561:36:561:36 | n | +| test.swift:560:7:560:7 | n | test.swift:560:7:560:7 | SSA def(n) | +| test.swift:560:11:560:11 | 0 | test.swift:560:7:560:7 | n | +| test.swift:561:36:561:36 | n | test.swift:561:35:561:36 | &... | diff --git a/swift/ql/test/library-tests/dataflow/dataflow/test.swift b/swift/ql/test/library-tests/dataflow/dataflow/test.swift index c64b29b8f2f..8fa01273d20 100644 --- a/swift/ql/test/library-tests/dataflow/dataflow/test.swift +++ b/swift/ql/test/library-tests/dataflow/dataflow/test.swift @@ -312,7 +312,7 @@ func test_optionals(y: Int?) { switch x { case .some(let z): - sink(arg: z) // $ MISSING: flow=259 + sink(arg: z) // $ flow=259 case .none: () } @@ -360,19 +360,20 @@ func testTuples2() { sink(arg: t2.x) // $ flow=351 sink(arg: t2.y) // $ flow=351 sink(arg: t2.z) - sink(arg: a) // $ MISSING: flow=351 - sink(arg: b) // $ MISSING: flow=351 + sink(arg: a) // $ flow=351 + sink(arg: b) // $ flow=351 sink(arg: c) } -enum MyEnum { +indirect enum MyEnum { case myNone case mySingle(Int) case myPair(Int, Int) + case myCons(Int, MyEnum) } func testEnums() { - let a : MyEnum = .myNone + var a : MyEnum = .myNone switch a { case .myNone: @@ -382,6 +383,8 @@ func testEnums() { case .myPair(let a, let b): sink(arg: a) sink(arg: b) + case let .myCons(a, _): + sink(arg: a) } if case .mySingle(let x) = a { @@ -392,44 +395,88 @@ func testEnums() { sink(arg: y) } - let b : MyEnum = .mySingle(source()) + a = .mySingle(source()) + + switch a { + case .myNone: + () + case .mySingle(let a): + sink(arg: a) // $ flow=398 + case .myPair(let a, let b): + sink(arg: a) + sink(arg: b) + case let .myCons(a, _): + sink(arg: a) + } + + if case .mySingle(let x) = a { + sink(arg: x) // $ flow=398 + } + if case .myPair(let x, let y) = a { + sink(arg: x) + sink(arg: y) + } + + a = MyEnum.myPair(0, source()) + + switch a { + case .myNone: + () + case .mySingle(let a): + sink(arg: a) + case .myPair(let a, let b): + sink(arg: a) + sink(arg: b) // $ flow=420 + case let .myCons(a, _): + sink(arg: a) + } + + if case .mySingle(let x) = a { + sink(arg: x) + } + if case .myPair(let x, let y) = a { + sink(arg: x) + sink(arg: y) // $ flow=420 + } + + let b: MyEnum = .myCons(42, a) switch b { case .myNone: () case .mySingle(let a): - sink(arg: a) // $ MISSING: flow=395 + sink(arg: a) case .myPair(let a, let b): sink(arg: a) sink(arg: b) + case let .myCons(a, .myPair(b, c)): + sink(arg: a) + sink(arg: b) + sink(arg: c) // $ flow=420 + case let .myCons(a, _): + sink(arg: a) } - if case .mySingle(let x) = a { - sink(arg: x) // $ MISSING: flow=395 - } - if case .myPair(let x, let y) = a { + if case .mySingle(let x) = MyEnum.myPair(source(), 0) { sink(arg: x) + } + if case MyEnum.myPair(let x, let y) = .myPair(source(), 0) { + sink(arg: x) // $ flow=463 sink(arg: y) } + if case let .myCons(_, .myPair(_, c)) = b { + sink(arg: c) // $ flow=420 + } - let c = MyEnum.myPair(0, source()) - - switch c { - case .myNone: + switch (a, b) { + case let (.myPair(a, b), .myCons(c, .myPair(d, e))): + sink(arg: a) + sink(arg: b) // $ flow=420 + sink(arg: c) + sink(arg: d) + sink(arg: e) // $ flow=420 + default: () - case .mySingle(let a): - sink(arg: a) - case .myPair(let a, let b): - sink(arg: a) - sink(arg: b) // $ MISSING: flow=415 - } - - if case .mySingle(let x) = a { - sink(arg: x) - } - if case .myPair(let x, let y) = a { - sink(arg: x) - sink(arg: y) // $ MISSING: flow=415 } } @@ -446,7 +493,7 @@ func testOptionals2(y: Int?) { let tuple1 = (x, y) switch tuple1 { case (.some(let a), .some(let b)): - sink(arg: a) // $ MISSING: flow=259 + sink(arg: a) // $ flow=259 sink(arg: b) default: () @@ -476,8 +523,8 @@ func testOptionalPropertyAccess(y: Int?) { } func testIdentityArithmetic() { - sink(arg: +source()) // $ flow=479 - sink(arg: (source())) // $ flow=480 + sink(arg: +source()) // $ flow=526 + sink(arg: (source())) // $ flow=527 } func sink(str: String) {} @@ -493,14 +540,14 @@ class MyClass { extension MyClass { convenience init(contentsOfFile: String) { - self.init(s: source3()) - sink(str: str) // $ flow=496 + self.init(s: source3()) + sink(str: str) // $ flow=543 } } func extensionInits(path: String) { - sink(str: MyClass(s: source3()).str) // $ flow=502 - sink(str: MyClass(contentsOfFile: path).str) // $ flow=496 + sink(str: MyClass(s: source3()).str) // $ flow=549 + sink(str: MyClass(contentsOfFile: path).str) // $ flow=543 } class InoutConstructorClass { @@ -512,4 +559,4 @@ func sink(arg: InoutConstructorClass) {} func inoutConstructor() { var n = 0 sink(arg: InoutConstructorClass(&n)) -} \ No newline at end of file +} diff --git a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected index 6f593ea2cb5..3d58e8a40ad 100644 --- a/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/core/LocalTaint.expected @@ -32,7 +32,8 @@ | simple.swift:32:13:32:20 | call to source() | simple.swift:32:13:32:25 | ... .&*(_:_:) ... | | simple.swift:32:25:32:25 | 2 | simple.swift:32:13:32:25 | ... .&*(_:_:) ... | | simple.swift:36:7:36:7 | SSA def(a) | simple.swift:37:13:37:13 | a | -| simple.swift:36:11:36:11 | 0 | simple.swift:36:7:36:7 | SSA def(a) | +| simple.swift:36:7:36:7 | a | simple.swift:36:7:36:7 | SSA def(a) | +| simple.swift:36:11:36:11 | 0 | simple.swift:36:7:36:7 | a | | simple.swift:37:13:37:13 | [post] a | simple.swift:38:3:38:3 | a | | simple.swift:37:13:37:13 | a | simple.swift:38:3:38:3 | a | | simple.swift:38:3:38:3 | &... | simple.swift:39:13:39:13 | a | @@ -54,7 +55,8 @@ | simple.swift:44:3:44:7 | SSA def(a) | simple.swift:45:13:45:13 | a | | simple.swift:44:7:44:7 | 0 | simple.swift:44:3:44:7 | SSA def(a) | | simple.swift:47:7:47:7 | SSA def(b) | simple.swift:48:3:48:3 | b | -| simple.swift:47:11:47:11 | 128 | simple.swift:47:7:47:7 | SSA def(b) | +| simple.swift:47:7:47:7 | b | simple.swift:47:7:47:7 | SSA def(b) | +| simple.swift:47:11:47:11 | 128 | simple.swift:47:7:47:7 | b | | simple.swift:48:3:48:3 | &... | simple.swift:49:13:49:13 | b | | simple.swift:48:3:48:3 | [post] &... | simple.swift:49:13:49:13 | b | | simple.swift:48:3:48:3 | b | simple.swift:48:3:48:3 | &... | @@ -66,7 +68,8 @@ | simple.swift:50:3:50:3 | b | simple.swift:50:3:50:3 | &... | | simple.swift:50:8:50:8 | 1 | simple.swift:50:3:50:3 | &... | | simple.swift:53:7:53:7 | SSA def(c) | simple.swift:54:3:54:3 | c | -| simple.swift:53:11:53:11 | 10 | simple.swift:53:7:53:7 | SSA def(c) | +| simple.swift:53:7:53:7 | c | simple.swift:53:7:53:7 | SSA def(c) | +| simple.swift:53:11:53:11 | 10 | simple.swift:53:7:53:7 | c | | simple.swift:54:3:54:3 | &... | simple.swift:55:13:55:13 | c | | simple.swift:54:3:54:3 | [post] &... | simple.swift:55:13:55:13 | c | | simple.swift:54:3:54:3 | c | simple.swift:54:3:54:3 | &... | @@ -78,7 +81,8 @@ | simple.swift:56:3:56:3 | c | simple.swift:56:3:56:3 | &... | | simple.swift:56:8:56:8 | 2 | simple.swift:56:3:56:3 | &... | | simple.swift:59:7:59:7 | SSA def(d) | simple.swift:60:3:60:3 | d | -| simple.swift:59:11:59:11 | 100 | simple.swift:59:7:59:7 | SSA def(d) | +| simple.swift:59:7:59:7 | d | simple.swift:59:7:59:7 | SSA def(d) | +| simple.swift:59:11:59:11 | 100 | simple.swift:59:7:59:7 | d | | simple.swift:60:3:60:3 | &... | simple.swift:61:13:61:13 | d | | simple.swift:60:3:60:3 | [post] &... | simple.swift:61:13:61:13 | d | | simple.swift:60:3:60:3 | d | simple.swift:60:3:60:3 | &... | @@ -90,7 +94,8 @@ | simple.swift:62:3:62:3 | d | simple.swift:62:3:62:3 | &... | | simple.swift:62:8:62:8 | 2 | simple.swift:62:3:62:3 | &... | | simple.swift:65:7:65:7 | SSA def(e) | simple.swift:66:3:66:3 | e | -| simple.swift:65:11:65:11 | 1000 | simple.swift:65:7:65:7 | SSA def(e) | +| simple.swift:65:7:65:7 | e | simple.swift:65:7:65:7 | SSA def(e) | +| simple.swift:65:11:65:11 | 1000 | simple.swift:65:7:65:7 | e | | simple.swift:66:3:66:3 | &... | simple.swift:67:13:67:13 | e | | simple.swift:66:3:66:3 | [post] &... | simple.swift:67:13:67:13 | e | | simple.swift:66:3:66:3 | e | simple.swift:66:3:66:3 | &... | @@ -168,7 +173,8 @@ | stringinterpolation.swift:13:47:13:47 | &... | stringinterpolation.swift:13:47:13:47 | [post] &... | | stringinterpolation.swift:13:47:13:47 | [post] &... | stringinterpolation.swift:13:23:13:23 | TapExpr | | stringinterpolation.swift:18:6:18:6 | SSA def(p1) | stringinterpolation.swift:19:2:19:2 | p1 | -| stringinterpolation.swift:18:11:18:24 | call to MyStringPair.init() | stringinterpolation.swift:18:6:18:6 | SSA def(p1) | +| stringinterpolation.swift:18:6:18:6 | p1 | stringinterpolation.swift:18:6:18:6 | SSA def(p1) | +| stringinterpolation.swift:18:11:18:24 | call to MyStringPair.init() | stringinterpolation.swift:18:6:18:6 | p1 | | stringinterpolation.swift:19:2:19:2 | [post] p1 | stringinterpolation.swift:20:2:20:2 | p1 | | stringinterpolation.swift:19:2:19:2 | p1 | stringinterpolation.swift:20:2:20:2 | p1 | | stringinterpolation.swift:20:2:20:2 | [post] p1 | stringinterpolation.swift:22:21:22:21 | p1 | @@ -246,7 +252,8 @@ | stringinterpolation.swift:24:24:24:24 | &... | stringinterpolation.swift:24:24:24:24 | [post] &... | | stringinterpolation.swift:24:24:24:24 | [post] &... | stringinterpolation.swift:24:12:24:12 | TapExpr | | stringinterpolation.swift:26:6:26:6 | SSA def(p2) | stringinterpolation.swift:27:2:27:2 | p2 | -| stringinterpolation.swift:26:11:26:24 | call to MyStringPair.init() | stringinterpolation.swift:26:6:26:6 | SSA def(p2) | +| stringinterpolation.swift:26:6:26:6 | p2 | stringinterpolation.swift:26:6:26:6 | SSA def(p2) | +| stringinterpolation.swift:26:11:26:24 | call to MyStringPair.init() | stringinterpolation.swift:26:6:26:6 | p2 | | stringinterpolation.swift:27:2:27:2 | [post] p2 | stringinterpolation.swift:28:2:28:2 | p2 | | stringinterpolation.swift:27:2:27:2 | p2 | stringinterpolation.swift:28:2:28:2 | p2 | | stringinterpolation.swift:28:2:28:2 | [post] p2 | stringinterpolation.swift:30:21:30:21 | p2 | diff --git a/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.expected b/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.expected index 649de8dd622..49d4c192730 100644 --- a/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.expected +++ b/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.expected @@ -1,8 +1,9 @@ | abstractfunctiondecl.swift:2:1:2:15 | func1() | getName:func1(), hasName:func1() | -| abstractfunctiondecl.swift:5:2:5:16 | func2() | MethodDecl, getName:func2(), hasName:func2(), hasQualifiedName(2):Class1.func2(), hasQualifiedName(3):abstractfunctiondecl.Class1.func2() | -| abstractfunctiondecl.swift:8:3:8:17 | func3() | MethodDecl, getName:func3(), hasName:func3(), hasQualifiedName(2):Class1.Class2.func3(), hasQualifiedName(3):abstractfunctiondecl.Class1.Class2.func3() | -| abstractfunctiondecl.swift:13:2:13:13 | func4() | MethodDecl, getName:func4(), hasName:func4(), hasQualifiedName(2):Protocol1.func4(), hasQualifiedName(3):abstractfunctiondecl.Protocol1.func4() | -| abstractfunctiondecl.swift:17:2:17:16 | func4() | MethodDecl, getName:func4(), hasName:func4(), hasQualifiedName(2):Class3.func4(), hasQualifiedName(3):abstractfunctiondecl.Class3.func4() | -| abstractfunctiondecl.swift:21:2:21:16 | func5() | MethodDecl, getName:func5(), hasName:func5(), hasQualifiedName(2):Class3.func5(), hasQualifiedName(3):abstractfunctiondecl.Class3.func5() | -| abstractfunctiondecl.swift:25:2:25:16 | func6() | MethodDecl, getName:func6(), hasName:func6(), hasQualifiedName(2):Struct1.func6(), hasQualifiedName(3):abstractfunctiondecl.Struct1.func6() | -| abstractfunctiondecl.swift:31:2:31:16 | func7() | MethodDecl, getName:func7(), hasName:func7(), hasQualifiedName(2):Enum1.func7(), hasQualifiedName(3):abstractfunctiondecl.Enum1.func7() | +| abstractfunctiondecl.swift:5:2:5:16 | func2() | MethodDecl, getName:func2(), hasName:func2(), hasQualifiedName(2):Class1.func2(), hasQualifiedName(3):abstractfunctiondecl.Class1.func2(), memberOf:Class1 | +| abstractfunctiondecl.swift:8:3:8:17 | func3() | MethodDecl, getName:func3(), hasName:func3(), hasQualifiedName(2):Class1.Class2.func3(), hasQualifiedName(3):abstractfunctiondecl.Class1.Class2.func3(), memberOf:Class1.Class2 | +| abstractfunctiondecl.swift:13:2:13:13 | func4() | MethodDecl, getName:func4(), hasName:func4(), hasQualifiedName(2):Protocol1.func4(), hasQualifiedName(3):abstractfunctiondecl.Protocol1.func4(), memberOf:Protocol1 | +| abstractfunctiondecl.swift:17:2:17:16 | func4() | MethodDecl, getName:func4(), hasName:func4(), hasQualifiedName(2):Class3.func4(), hasQualifiedName(3):abstractfunctiondecl.Class3.func4(), memberOf:Class3 | +| abstractfunctiondecl.swift:21:2:21:16 | func5() | MethodDecl, getName:func5(), hasName:func5(), hasQualifiedName(2):Class3.func5(), hasQualifiedName(3):abstractfunctiondecl.Class3.func5(), memberOf:Class3 | +| abstractfunctiondecl.swift:25:2:25:16 | func6() | MethodDecl, getName:func6(), hasName:func6(), hasQualifiedName(2):Struct1.func6(), hasQualifiedName(3):abstractfunctiondecl.Struct1.func6(), memberOf:Struct1 | +| abstractfunctiondecl.swift:31:2:31:16 | func7() | MethodDecl, getName:func7(), hasName:func7(), hasQualifiedName(2):Enum1.func7(), hasQualifiedName(3):abstractfunctiondecl.Enum1.func7(), memberOf:Enum1 | +| abstractfunctiondecl.swift:37:3:37:17 | func8() | MethodDecl, getName:func8(), hasName:func8(), hasQualifiedName(2):Class1.Class4.func8(), hasQualifiedName(3):abstractfunctiondecl.Class1.Class4.func8(), memberOf:Class1.Class4 | diff --git a/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.ql b/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.ql index e3b3290890d..acd05cc4438 100644 --- a/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.ql +++ b/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.ql @@ -19,6 +19,10 @@ string describe(AbstractFunctionDecl f) { f.(MethodDecl).hasQualifiedName(a, b, c) and result = "hasQualifiedName(3):" + a + "." + b + "." + c ) + or + exists(Decl td | td.getAMember() = f | + result = "memberOf:" + td.asNominalTypeDecl().getFullName() + ) } from AbstractFunctionDecl f diff --git a/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.swift b/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.swift index 881fb93b5c2..3e0cb330708 100644 --- a/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.swift +++ b/swift/ql/test/library-tests/elements/decl/abstractfunctiondecl/abstractfunctiondecl.swift @@ -30,3 +30,10 @@ enum Enum1 { case case2 func func7() {} } + +extension Class1 +{ + class Class4 { + func func8() {} + } +} diff --git a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.expected b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.expected index 3786b7c2620..0eb3c363ee8 100644 --- a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.expected +++ b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.expected @@ -1,13 +1,13 @@ | nominaltype.swift:35:6:35:6 | a | A | A | | -| nominaltype.swift:36:6:36:6 | a_alias | A_alias | A_alias | | -| nominaltype.swift:37:6:37:6 | a_optional_alias | A_optional_alias | A_optional_alias | | +| nominaltype.swift:36:6:36:6 | a_alias | A_alias | A | getAliasedType:A | +| nominaltype.swift:37:6:37:6 | a_optional_alias | A_optional_alias | A? | getAliasedType:A? | | nominaltype.swift:38:6:38:6 | b1 | B1 | B1 | getABaseType:A | | nominaltype.swift:39:6:39:6 | b2 | B2 | B2 | getABaseType:A_alias | -| nominaltype.swift:40:6:40:6 | b1_alias | B1_alias | B1_alias | | -| nominaltype.swift:41:6:41:6 | b2_alias | B2_alias | B2_alias | | +| nominaltype.swift:40:6:40:6 | b1_alias | B1_alias | B1 | getAliasedType:B1 | +| nominaltype.swift:41:6:41:6 | b2_alias | B2_alias | B2 | getAliasedType:B2 | | nominaltype.swift:42:6:42:6 | p | P | P | | | nominaltype.swift:43:6:43:6 | p_alias | P_alias | P_alias | | | nominaltype.swift:44:6:44:6 | c1 | C1 | C1 | getABaseType:P | | nominaltype.swift:45:6:45:6 | c2 | C2 | C2 | getABaseType:P_alias | -| nominaltype.swift:46:6:46:6 | c1_alias | C1_alias | C1_alias | | -| nominaltype.swift:47:6:47:6 | c2_alias | C2_alias | C2_alias | | +| nominaltype.swift:46:6:46:6 | c1_alias | C1_alias | C1 | getAliasedType:C1 | +| nominaltype.swift:47:6:47:6 | c2_alias | C2_alias | C2 | getAliasedType:C2 | diff --git a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltypedecl.expected b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltypedecl.expected index e5381fb2db4..612b031f54e 100644 --- a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltypedecl.expected +++ b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltypedecl.expected @@ -1,11 +1,11 @@ | nominaltype.swift:35:6:35:6 | a | A | | -| nominaltype.swift:36:6:36:6 | a_alias | A_alias | | -| nominaltype.swift:37:6:37:6 | a_optional_alias | A_optional_alias | | +| nominaltype.swift:36:6:36:6 | a_alias | A_alias | getAliasedType:A | +| nominaltype.swift:37:6:37:6 | a_optional_alias | A_optional_alias | getAliasedType:A? | | nominaltype.swift:38:6:38:6 | b1 | B1 | getABaseType:A | | nominaltype.swift:39:6:39:6 | b2 | B2 | getABaseType:A_alias | -| nominaltype.swift:40:6:40:6 | b1_alias | B1_alias | | -| nominaltype.swift:41:6:41:6 | b2_alias | B2_alias | | +| nominaltype.swift:40:6:40:6 | b1_alias | B1_alias | getAliasedType:B1 | +| nominaltype.swift:41:6:41:6 | b2_alias | B2_alias | getAliasedType:B2 | | nominaltype.swift:44:6:44:6 | c1 | C1 | getABaseType:P | | nominaltype.swift:45:6:45:6 | c2 | C2 | getABaseType:P_alias | -| nominaltype.swift:46:6:46:6 | c1_alias | C1_alias | | -| nominaltype.swift:47:6:47:6 | c2_alias | C2_alias | | +| nominaltype.swift:46:6:46:6 | c1_alias | C1_alias | getAliasedType:C1 | +| nominaltype.swift:47:6:47:6 | c2_alias | C2_alias | getAliasedType:C2 | diff --git a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltypedecl.ql b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltypedecl.ql index 53afa43caf5..917b27d6826 100644 --- a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltypedecl.ql +++ b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltypedecl.ql @@ -1,8 +1,8 @@ import swift string describe(TypeDecl td) { - //result = "getAliasedType:" + td.(TypeAliasDecl).getAliasedType() TODO: not yet implemented. - //or + result = "getAliasedType:" + td.(TypeAliasDecl).getAliasedType() + or result = "getABaseType:" + td.(NominalTypeDecl).getABaseType() } diff --git a/swift/ql/test/query-tests/Security/CWE-135/StringLengthConflation.expected b/swift/ql/test/query-tests/Security/CWE-135/StringLengthConflation.expected index b8983944811..17e2c383dd8 100644 --- a/swift/ql/test/query-tests/Security/CWE-135/StringLengthConflation.expected +++ b/swift/ql/test/query-tests/Security/CWE-135/StringLengthConflation.expected @@ -73,6 +73,9 @@ nodes | StringLengthConflation.swift:138:36:138:46 | ... .-(_:_:) ... | semmle.label | ... .-(_:_:) ... | | StringLengthConflation.swift:144:28:144:30 | .count : | semmle.label | .count : | | StringLengthConflation.swift:144:28:144:38 | ... .-(_:_:) ... | semmle.label | ... .-(_:_:) ... | +| StringLengthConflation.swift:151:45:151:53 | .count | semmle.label | .count | +| StringLengthConflation.swift:156:45:156:52 | .count | semmle.label | .count | +| StringLengthConflation.swift:161:45:161:53 | .count | semmle.label | .count | | file://:0:0:0:0 | .length : | semmle.label | .length : | subpaths #select @@ -111,3 +114,6 @@ subpaths | StringLengthConflation.swift:137:34:137:44 | ... .-(_:_:) ... | StringLengthConflation.swift:137:34:137:36 | .count : | StringLengthConflation.swift:137:34:137:44 | ... .-(_:_:) ... | This String length is used in an NSString, but it may not be equivalent. | | StringLengthConflation.swift:138:36:138:46 | ... .-(_:_:) ... | StringLengthConflation.swift:138:36:138:38 | .count : | StringLengthConflation.swift:138:36:138:46 | ... .-(_:_:) ... | This String length is used in an NSString, but it may not be equivalent. | | StringLengthConflation.swift:144:28:144:38 | ... .-(_:_:) ... | StringLengthConflation.swift:144:28:144:30 | .count : | StringLengthConflation.swift:144:28:144:38 | ... .-(_:_:) ... | This String length is used in an NSString, but it may not be equivalent. | +| StringLengthConflation.swift:151:45:151:53 | .count | StringLengthConflation.swift:151:45:151:53 | .count | StringLengthConflation.swift:151:45:151:53 | .count | This String.unicodeScalars length is used in a String, but it may not be equivalent. | +| StringLengthConflation.swift:156:45:156:52 | .count | StringLengthConflation.swift:156:45:156:52 | .count | StringLengthConflation.swift:156:45:156:52 | .count | This String.utf8 length is used in a String, but it may not be equivalent. | +| StringLengthConflation.swift:161:45:161:53 | .count | StringLengthConflation.swift:161:45:161:53 | .count | StringLengthConflation.swift:161:45:161:53 | .count | This String.utf16 length is used in a String, but it may not be equivalent. | diff --git a/swift/ql/test/query-tests/Security/CWE-135/StringLengthConflation.swift b/swift/ql/test/query-tests/Security/CWE-135/StringLengthConflation.swift index 7eac5d6299d..67b8feb657f 100644 --- a/swift/ql/test/query-tests/Security/CWE-135/StringLengthConflation.swift +++ b/swift/ql/test/query-tests/Security/CWE-135/StringLengthConflation.swift @@ -143,6 +143,24 @@ func test(s: String) { let nmstr8 = NSMutableString(string: s) nmstr8.insert("*", at: s.count - 1) // BAD: String length used in NSString print("insert '\(nmstr7)' / '\(nmstr8)'") + + // --- inspired by real world cases --- + + let scalars = s.unicodeScalars + let _ = s.index(s.startIndex, offsetBy: s.count) // GOOD + let _ = s.index(s.startIndex, offsetBy: scalars.count) // BAD + let _ = scalars.index(scalars.startIndex, offsetBy: scalars.count) // GOOD + let _ = scalars.index(scalars.startIndex, offsetBy: s.count) // BAD [NOT DETECTED] + + let s_utf8 = s.utf8 + let _ = s.index(s.startIndex, offsetBy: s_utf8.count) // BAD + let _ = s_utf8.index(s_utf8.startIndex, offsetBy: s_utf8.count) // GOOD + let _ = s_utf8.index(s_utf8.startIndex, offsetBy: s.count) // BAD [NOT DETECTED] + + let s_utf16 = s.utf16 + let _ = s.index(s.startIndex, offsetBy: s_utf16.count) // BAD + let _ = s_utf16.index(s_utf16.startIndex, offsetBy: scalars.count) // GOOD + let _ = s_utf16.index(s_utf16.startIndex, offsetBy: s.count) // BAD [NOT DETECTED] } // `begin :thumbsup: end`, with thumbs up emoji and skin tone modifier diff --git a/swift/ql/test/query-tests/Security/CWE-135/StringLengthConflation2.swift b/swift/ql/test/query-tests/Security/CWE-135/StringLengthConflation2.swift index 1a0fbfdb638..ffd45c28b10 100644 --- a/swift/ql/test/query-tests/Security/CWE-135/StringLengthConflation2.swift +++ b/swift/ql/test/query-tests/Security/CWE-135/StringLengthConflation2.swift @@ -12,12 +12,7 @@ class NSObject { } -class NSStringBase : NSObject -{ - func substring(from: Int) -> String { return "" } -} - -class NSString : NSStringBase +class NSString : NSObject { init(string: String) { length = string.count } @@ -26,6 +21,11 @@ class NSString : NSStringBase private(set) var length: Int } +extension NSString +{ + func substring(from: Int) -> String { return "" } +} + // --- tests --- func test(s: String) { diff --git a/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected b/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected index 2afbfed846b..540cdad43da 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected +++ b/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected @@ -1,6 +1,8 @@ edges +| file://:0:0:0:0 | self [value] : | file://:0:0:0:0 | .value : | | file://:0:0:0:0 | value : | file://:0:0:0:0 | [post] self [data] : | | file://:0:0:0:0 | value : | file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] : | +| file://:0:0:0:0 | value : | file://:0:0:0:0 | [post] self [value] : | | testCoreData2.swift:23:13:23:13 | value : | file://:0:0:0:0 | value : | | testCoreData2.swift:37:2:37:2 | [post] obj [myValue] : | testCoreData2.swift:37:2:37:2 | [post] obj | | testCoreData2.swift:37:16:37:16 | bankAccountNo : | testCoreData2.swift:37:2:37:2 | [post] obj [myValue] : | @@ -28,6 +30,82 @@ edges | testCoreData2.swift:62:30:62:30 | bankAccountNo : | testCoreData2.swift:62:4:62:4 | [post] obj [myBankAccountNumber] : | | testCoreData2.swift:65:3:65:3 | [post] obj [myBankAccountNumber] : | testCoreData2.swift:65:3:65:3 | [post] obj | | testCoreData2.swift:65:29:65:29 | bankAccountNo : | testCoreData2.swift:65:3:65:3 | [post] obj [myBankAccountNumber] : | +| testCoreData2.swift:70:9:70:9 | self : | file://:0:0:0:0 | .value : | +| testCoreData2.swift:70:9:70:9 | self [value] : | file://:0:0:0:0 | self [value] : | +| testCoreData2.swift:70:9:70:9 | value : | file://:0:0:0:0 | value : | +| testCoreData2.swift:71:9:71:9 | self : | file://:0:0:0:0 | .value2 : | +| testCoreData2.swift:79:2:79:2 | [post] dbObj [myValue] : | testCoreData2.swift:79:2:79:2 | [post] dbObj | +| testCoreData2.swift:79:18:79:28 | .bankAccountNo : | testCoreData2.swift:79:2:79:2 | [post] dbObj [myValue] : | +| testCoreData2.swift:80:2:80:2 | [post] dbObj [myValue] : | testCoreData2.swift:80:2:80:2 | [post] dbObj | +| testCoreData2.swift:80:18:80:28 | ...! : | testCoreData2.swift:80:2:80:2 | [post] dbObj [myValue] : | +| testCoreData2.swift:80:18:80:28 | .bankAccountNo2 : | testCoreData2.swift:80:18:80:28 | ...! : | +| testCoreData2.swift:82:2:82:2 | [post] dbObj [myValue] : | testCoreData2.swift:82:2:82:2 | [post] dbObj | +| testCoreData2.swift:82:18:82:18 | bankAccountNo : | testCoreData2.swift:70:9:70:9 | self : | +| testCoreData2.swift:82:18:82:18 | bankAccountNo : | testCoreData2.swift:82:18:82:32 | .value : | +| testCoreData2.swift:82:18:82:32 | .value : | testCoreData2.swift:82:2:82:2 | [post] dbObj [myValue] : | +| testCoreData2.swift:83:2:83:2 | [post] dbObj [myValue] : | testCoreData2.swift:83:2:83:2 | [post] dbObj | +| testCoreData2.swift:83:18:83:18 | bankAccountNo : | testCoreData2.swift:71:9:71:9 | self : | +| testCoreData2.swift:83:18:83:18 | bankAccountNo : | testCoreData2.swift:83:18:83:32 | ...! : | +| testCoreData2.swift:83:18:83:18 | bankAccountNo : | testCoreData2.swift:83:18:83:32 | .value2 : | +| testCoreData2.swift:83:18:83:32 | ...! : | testCoreData2.swift:83:2:83:2 | [post] dbObj [myValue] : | +| testCoreData2.swift:83:18:83:32 | .value2 : | testCoreData2.swift:83:18:83:32 | ...! : | +| testCoreData2.swift:84:2:84:2 | [post] dbObj [myValue] : | testCoreData2.swift:84:2:84:2 | [post] dbObj | +| testCoreData2.swift:84:18:84:18 | ...! : | testCoreData2.swift:70:9:70:9 | self : | +| testCoreData2.swift:84:18:84:18 | ...! : | testCoreData2.swift:84:18:84:33 | .value : | +| testCoreData2.swift:84:18:84:18 | bankAccountNo2 : | testCoreData2.swift:84:18:84:18 | ...! : | +| testCoreData2.swift:84:18:84:18 | bankAccountNo2 : | testCoreData2.swift:84:18:84:33 | .value : | +| testCoreData2.swift:84:18:84:33 | .value : | testCoreData2.swift:84:2:84:2 | [post] dbObj [myValue] : | +| testCoreData2.swift:85:2:85:2 | [post] dbObj [myValue] : | testCoreData2.swift:85:2:85:2 | [post] dbObj | +| testCoreData2.swift:85:18:85:18 | ...! : | testCoreData2.swift:71:9:71:9 | self : | +| testCoreData2.swift:85:18:85:18 | ...! : | testCoreData2.swift:85:18:85:33 | .value2 : | +| testCoreData2.swift:85:18:85:18 | bankAccountNo2 : | testCoreData2.swift:85:18:85:18 | ...! : | +| testCoreData2.swift:85:18:85:18 | bankAccountNo2 : | testCoreData2.swift:85:18:85:33 | ...! : | +| testCoreData2.swift:85:18:85:33 | ...! : | testCoreData2.swift:85:2:85:2 | [post] dbObj [myValue] : | +| testCoreData2.swift:85:18:85:33 | .value2 : | testCoreData2.swift:85:18:85:33 | ...! : | +| testCoreData2.swift:87:2:87:10 | [post] ...? [myValue] : | testCoreData2.swift:87:2:87:10 | [post] ...? | +| testCoreData2.swift:87:22:87:32 | .bankAccountNo : | testCoreData2.swift:87:2:87:10 | [post] ...? [myValue] : | +| testCoreData2.swift:88:2:88:10 | [post] ...? [myValue] : | testCoreData2.swift:88:2:88:10 | [post] ...? | +| testCoreData2.swift:88:22:88:22 | bankAccountNo : | testCoreData2.swift:70:9:70:9 | self : | +| testCoreData2.swift:88:22:88:22 | bankAccountNo : | testCoreData2.swift:88:22:88:36 | .value : | +| testCoreData2.swift:88:22:88:36 | .value : | testCoreData2.swift:88:2:88:10 | [post] ...? [myValue] : | +| testCoreData2.swift:89:2:89:10 | [post] ...? [myValue] : | testCoreData2.swift:89:2:89:10 | [post] ...? | +| testCoreData2.swift:89:22:89:22 | ...! : | testCoreData2.swift:71:9:71:9 | self : | +| testCoreData2.swift:89:22:89:22 | ...! : | testCoreData2.swift:89:22:89:37 | .value2 : | +| testCoreData2.swift:89:22:89:22 | bankAccountNo2 : | testCoreData2.swift:89:22:89:22 | ...! : | +| testCoreData2.swift:89:22:89:22 | bankAccountNo2 : | testCoreData2.swift:89:22:89:37 | ...! : | +| testCoreData2.swift:89:22:89:37 | ...! : | testCoreData2.swift:89:2:89:10 | [post] ...? [myValue] : | +| testCoreData2.swift:89:22:89:37 | .value2 : | testCoreData2.swift:89:22:89:37 | ...! : | +| testCoreData2.swift:91:10:91:10 | bankAccountNo : | testCoreData2.swift:92:10:92:10 | a : | +| testCoreData2.swift:91:10:91:10 | bankAccountNo : | testCoreData2.swift:93:18:93:18 | b : | +| testCoreData2.swift:92:10:92:10 | a : | testCoreData2.swift:70:9:70:9 | self : | +| testCoreData2.swift:92:10:92:10 | a : | testCoreData2.swift:92:10:92:12 | .value : | +| testCoreData2.swift:92:10:92:12 | .value : | testCoreData2.swift:93:18:93:18 | b : | +| testCoreData2.swift:93:2:93:2 | [post] dbObj [myValue] : | testCoreData2.swift:93:2:93:2 | [post] dbObj | +| testCoreData2.swift:93:18:93:18 | b : | testCoreData2.swift:93:2:93:2 | [post] dbObj [myValue] : | +| testCoreData2.swift:95:10:95:10 | bankAccountNo : | testCoreData2.swift:97:12:97:12 | c : | +| testCoreData2.swift:95:10:95:10 | bankAccountNo : | testCoreData2.swift:97:12:97:14 | .value : | +| testCoreData2.swift:97:2:97:2 | [post] d [value] : | testCoreData2.swift:98:18:98:18 | d [value] : | +| testCoreData2.swift:97:12:97:12 | c : | testCoreData2.swift:70:9:70:9 | self : | +| testCoreData2.swift:97:12:97:12 | c : | testCoreData2.swift:97:12:97:14 | .value : | +| testCoreData2.swift:97:12:97:14 | .value : | testCoreData2.swift:70:9:70:9 | value : | +| testCoreData2.swift:97:12:97:14 | .value : | testCoreData2.swift:97:2:97:2 | [post] d [value] : | +| testCoreData2.swift:98:2:98:2 | [post] dbObj [myValue] : | testCoreData2.swift:98:2:98:2 | [post] dbObj | +| testCoreData2.swift:98:18:98:18 | d [value] : | testCoreData2.swift:70:9:70:9 | self [value] : | +| testCoreData2.swift:98:18:98:18 | d [value] : | testCoreData2.swift:98:18:98:20 | .value : | +| testCoreData2.swift:98:18:98:20 | .value : | testCoreData2.swift:98:2:98:2 | [post] dbObj [myValue] : | +| testCoreData2.swift:101:10:101:10 | bankAccountNo : | testCoreData2.swift:104:18:104:18 | e : | +| testCoreData2.swift:101:10:101:10 | bankAccountNo : | testCoreData2.swift:104:18:104:20 | .value : | +| testCoreData2.swift:101:10:101:10 | bankAccountNo : | testCoreData2.swift:105:18:105:18 | e : | +| testCoreData2.swift:101:10:101:10 | bankAccountNo : | testCoreData2.swift:105:18:105:20 | ...! : | +| testCoreData2.swift:104:2:104:2 | [post] dbObj [myValue] : | testCoreData2.swift:104:2:104:2 | [post] dbObj | +| testCoreData2.swift:104:18:104:18 | e : | testCoreData2.swift:70:9:70:9 | self : | +| testCoreData2.swift:104:18:104:18 | e : | testCoreData2.swift:104:18:104:20 | .value : | +| testCoreData2.swift:104:18:104:20 | .value : | testCoreData2.swift:104:2:104:2 | [post] dbObj [myValue] : | +| testCoreData2.swift:105:2:105:2 | [post] dbObj [myValue] : | testCoreData2.swift:105:2:105:2 | [post] dbObj | +| testCoreData2.swift:105:18:105:18 | e : | testCoreData2.swift:71:9:71:9 | self : | +| testCoreData2.swift:105:18:105:18 | e : | testCoreData2.swift:105:18:105:20 | .value2 : | +| testCoreData2.swift:105:18:105:20 | ...! : | testCoreData2.swift:105:2:105:2 | [post] dbObj [myValue] : | +| testCoreData2.swift:105:18:105:20 | .value2 : | testCoreData2.swift:105:18:105:20 | ...! : | | testCoreData.swift:18:19:18:26 | value : | testCoreData.swift:19:12:19:12 | value | | testCoreData.swift:31:3:31:3 | newValue : | testCoreData.swift:32:13:32:13 | newValue | | testCoreData.swift:61:25:61:25 | password : | testCoreData.swift:18:19:18:26 | value : | @@ -104,8 +182,14 @@ edges | testRealm.swift:59:11:59:11 | myPassword : | testRealm.swift:16:6:16:6 | value : | | testRealm.swift:59:11:59:11 | myPassword : | testRealm.swift:59:2:59:2 | [post] g [data] : | nodes +| file://:0:0:0:0 | .value2 : | semmle.label | .value2 : | +| file://:0:0:0:0 | .value : | semmle.label | .value : | +| file://:0:0:0:0 | .value : | semmle.label | .value : | | file://:0:0:0:0 | [post] self [data] : | semmle.label | [post] self [data] : | | file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] : | semmle.label | [post] self [notStoredBankAccountNumber] : | +| file://:0:0:0:0 | [post] self [value] : | semmle.label | [post] self [value] : | +| file://:0:0:0:0 | self [value] : | semmle.label | self [value] : | +| file://:0:0:0:0 | value : | semmle.label | value : | | file://:0:0:0:0 | value : | semmle.label | value : | | file://:0:0:0:0 | value : | semmle.label | value : | | testCoreData2.swift:23:13:23:13 | value : | semmle.label | value : | @@ -145,6 +229,74 @@ nodes | testCoreData2.swift:65:3:65:3 | [post] obj | semmle.label | [post] obj | | testCoreData2.swift:65:3:65:3 | [post] obj [myBankAccountNumber] : | semmle.label | [post] obj [myBankAccountNumber] : | | testCoreData2.swift:65:29:65:29 | bankAccountNo : | semmle.label | bankAccountNo : | +| testCoreData2.swift:70:9:70:9 | self : | semmle.label | self : | +| testCoreData2.swift:70:9:70:9 | self [value] : | semmle.label | self [value] : | +| testCoreData2.swift:70:9:70:9 | value : | semmle.label | value : | +| testCoreData2.swift:71:9:71:9 | self : | semmle.label | self : | +| testCoreData2.swift:79:2:79:2 | [post] dbObj | semmle.label | [post] dbObj | +| testCoreData2.swift:79:2:79:2 | [post] dbObj [myValue] : | semmle.label | [post] dbObj [myValue] : | +| testCoreData2.swift:79:18:79:28 | .bankAccountNo : | semmle.label | .bankAccountNo : | +| testCoreData2.swift:80:2:80:2 | [post] dbObj | semmle.label | [post] dbObj | +| testCoreData2.swift:80:2:80:2 | [post] dbObj [myValue] : | semmle.label | [post] dbObj [myValue] : | +| testCoreData2.swift:80:18:80:28 | ...! : | semmle.label | ...! : | +| testCoreData2.swift:80:18:80:28 | .bankAccountNo2 : | semmle.label | .bankAccountNo2 : | +| testCoreData2.swift:82:2:82:2 | [post] dbObj | semmle.label | [post] dbObj | +| testCoreData2.swift:82:2:82:2 | [post] dbObj [myValue] : | semmle.label | [post] dbObj [myValue] : | +| testCoreData2.swift:82:18:82:18 | bankAccountNo : | semmle.label | bankAccountNo : | +| testCoreData2.swift:82:18:82:32 | .value : | semmle.label | .value : | +| testCoreData2.swift:83:2:83:2 | [post] dbObj | semmle.label | [post] dbObj | +| testCoreData2.swift:83:2:83:2 | [post] dbObj [myValue] : | semmle.label | [post] dbObj [myValue] : | +| testCoreData2.swift:83:18:83:18 | bankAccountNo : | semmle.label | bankAccountNo : | +| testCoreData2.swift:83:18:83:32 | ...! : | semmle.label | ...! : | +| testCoreData2.swift:83:18:83:32 | .value2 : | semmle.label | .value2 : | +| testCoreData2.swift:84:2:84:2 | [post] dbObj | semmle.label | [post] dbObj | +| testCoreData2.swift:84:2:84:2 | [post] dbObj [myValue] : | semmle.label | [post] dbObj [myValue] : | +| testCoreData2.swift:84:18:84:18 | ...! : | semmle.label | ...! : | +| testCoreData2.swift:84:18:84:18 | bankAccountNo2 : | semmle.label | bankAccountNo2 : | +| testCoreData2.swift:84:18:84:33 | .value : | semmle.label | .value : | +| testCoreData2.swift:85:2:85:2 | [post] dbObj | semmle.label | [post] dbObj | +| testCoreData2.swift:85:2:85:2 | [post] dbObj [myValue] : | semmle.label | [post] dbObj [myValue] : | +| testCoreData2.swift:85:18:85:18 | ...! : | semmle.label | ...! : | +| testCoreData2.swift:85:18:85:18 | bankAccountNo2 : | semmle.label | bankAccountNo2 : | +| testCoreData2.swift:85:18:85:33 | ...! : | semmle.label | ...! : | +| testCoreData2.swift:85:18:85:33 | .value2 : | semmle.label | .value2 : | +| testCoreData2.swift:87:2:87:10 | [post] ...? | semmle.label | [post] ...? | +| testCoreData2.swift:87:2:87:10 | [post] ...? [myValue] : | semmle.label | [post] ...? [myValue] : | +| testCoreData2.swift:87:22:87:32 | .bankAccountNo : | semmle.label | .bankAccountNo : | +| testCoreData2.swift:88:2:88:10 | [post] ...? | semmle.label | [post] ...? | +| testCoreData2.swift:88:2:88:10 | [post] ...? [myValue] : | semmle.label | [post] ...? [myValue] : | +| testCoreData2.swift:88:22:88:22 | bankAccountNo : | semmle.label | bankAccountNo : | +| testCoreData2.swift:88:22:88:36 | .value : | semmle.label | .value : | +| testCoreData2.swift:89:2:89:10 | [post] ...? | semmle.label | [post] ...? | +| testCoreData2.swift:89:2:89:10 | [post] ...? [myValue] : | semmle.label | [post] ...? [myValue] : | +| testCoreData2.swift:89:22:89:22 | ...! : | semmle.label | ...! : | +| testCoreData2.swift:89:22:89:22 | bankAccountNo2 : | semmle.label | bankAccountNo2 : | +| testCoreData2.swift:89:22:89:37 | ...! : | semmle.label | ...! : | +| testCoreData2.swift:89:22:89:37 | .value2 : | semmle.label | .value2 : | +| testCoreData2.swift:91:10:91:10 | bankAccountNo : | semmle.label | bankAccountNo : | +| testCoreData2.swift:92:10:92:10 | a : | semmle.label | a : | +| testCoreData2.swift:92:10:92:12 | .value : | semmle.label | .value : | +| testCoreData2.swift:93:2:93:2 | [post] dbObj | semmle.label | [post] dbObj | +| testCoreData2.swift:93:2:93:2 | [post] dbObj [myValue] : | semmle.label | [post] dbObj [myValue] : | +| testCoreData2.swift:93:18:93:18 | b : | semmle.label | b : | +| testCoreData2.swift:95:10:95:10 | bankAccountNo : | semmle.label | bankAccountNo : | +| testCoreData2.swift:97:2:97:2 | [post] d [value] : | semmle.label | [post] d [value] : | +| testCoreData2.swift:97:12:97:12 | c : | semmle.label | c : | +| testCoreData2.swift:97:12:97:14 | .value : | semmle.label | .value : | +| testCoreData2.swift:98:2:98:2 | [post] dbObj | semmle.label | [post] dbObj | +| testCoreData2.swift:98:2:98:2 | [post] dbObj [myValue] : | semmle.label | [post] dbObj [myValue] : | +| testCoreData2.swift:98:18:98:18 | d [value] : | semmle.label | d [value] : | +| testCoreData2.swift:98:18:98:20 | .value : | semmle.label | .value : | +| testCoreData2.swift:101:10:101:10 | bankAccountNo : | semmle.label | bankAccountNo : | +| testCoreData2.swift:104:2:104:2 | [post] dbObj | semmle.label | [post] dbObj | +| testCoreData2.swift:104:2:104:2 | [post] dbObj [myValue] : | semmle.label | [post] dbObj [myValue] : | +| testCoreData2.swift:104:18:104:18 | e : | semmle.label | e : | +| testCoreData2.swift:104:18:104:20 | .value : | semmle.label | .value : | +| testCoreData2.swift:105:2:105:2 | [post] dbObj | semmle.label | [post] dbObj | +| testCoreData2.swift:105:2:105:2 | [post] dbObj [myValue] : | semmle.label | [post] dbObj [myValue] : | +| testCoreData2.swift:105:18:105:18 | e : | semmle.label | e : | +| testCoreData2.swift:105:18:105:20 | ...! : | semmle.label | ...! : | +| testCoreData2.swift:105:18:105:20 | .value2 : | semmle.label | .value2 : | | testCoreData.swift:18:19:18:26 | value : | semmle.label | value : | | testCoreData.swift:19:12:19:12 | value | semmle.label | value | | testCoreData.swift:31:3:31:3 | newValue : | semmle.label | newValue : | @@ -285,29 +437,54 @@ nodes subpaths | testCoreData2.swift:43:35:43:35 | bankAccountNo : | testCoreData2.swift:23:13:23:13 | value : | file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] : | testCoreData2.swift:43:2:43:2 | [post] obj [notStoredBankAccountNumber] : | | testCoreData2.swift:52:41:52:41 | bankAccountNo : | testCoreData2.swift:23:13:23:13 | value : | file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] : | testCoreData2.swift:52:2:52:10 | [post] ...? [notStoredBankAccountNumber] : | +| testCoreData2.swift:82:18:82:18 | bankAccountNo : | testCoreData2.swift:70:9:70:9 | self : | file://:0:0:0:0 | .value : | testCoreData2.swift:82:18:82:32 | .value : | +| testCoreData2.swift:83:18:83:18 | bankAccountNo : | testCoreData2.swift:71:9:71:9 | self : | file://:0:0:0:0 | .value2 : | testCoreData2.swift:83:18:83:32 | .value2 : | +| testCoreData2.swift:84:18:84:18 | ...! : | testCoreData2.swift:70:9:70:9 | self : | file://:0:0:0:0 | .value : | testCoreData2.swift:84:18:84:33 | .value : | +| testCoreData2.swift:85:18:85:18 | ...! : | testCoreData2.swift:71:9:71:9 | self : | file://:0:0:0:0 | .value2 : | testCoreData2.swift:85:18:85:33 | .value2 : | +| testCoreData2.swift:88:22:88:22 | bankAccountNo : | testCoreData2.swift:70:9:70:9 | self : | file://:0:0:0:0 | .value : | testCoreData2.swift:88:22:88:36 | .value : | +| testCoreData2.swift:89:22:89:22 | ...! : | testCoreData2.swift:71:9:71:9 | self : | file://:0:0:0:0 | .value2 : | testCoreData2.swift:89:22:89:37 | .value2 : | +| testCoreData2.swift:92:10:92:10 | a : | testCoreData2.swift:70:9:70:9 | self : | file://:0:0:0:0 | .value : | testCoreData2.swift:92:10:92:12 | .value : | +| testCoreData2.swift:97:12:97:12 | c : | testCoreData2.swift:70:9:70:9 | self : | file://:0:0:0:0 | .value : | testCoreData2.swift:97:12:97:14 | .value : | +| testCoreData2.swift:97:12:97:14 | .value : | testCoreData2.swift:70:9:70:9 | value : | file://:0:0:0:0 | [post] self [value] : | testCoreData2.swift:97:2:97:2 | [post] d [value] : | +| testCoreData2.swift:98:18:98:18 | d [value] : | testCoreData2.swift:70:9:70:9 | self [value] : | file://:0:0:0:0 | .value : | testCoreData2.swift:98:18:98:20 | .value : | +| testCoreData2.swift:104:18:104:18 | e : | testCoreData2.swift:70:9:70:9 | self : | file://:0:0:0:0 | .value : | testCoreData2.swift:104:18:104:20 | .value : | +| testCoreData2.swift:105:18:105:18 | e : | testCoreData2.swift:71:9:71:9 | self : | file://:0:0:0:0 | .value2 : | testCoreData2.swift:105:18:105:20 | .value2 : | | testRealm.swift:34:11:34:11 | myPassword : | testRealm.swift:16:6:16:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:34:2:34:2 | [post] a [data] : | | testRealm.swift:42:11:42:11 | myPassword : | testRealm.swift:16:6:16:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:42:2:42:2 | [post] c [data] : | | testRealm.swift:52:12:52:12 | myPassword : | testRealm.swift:16:6:16:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:52:2:52:3 | [post] ...! [data] : | | testRealm.swift:59:11:59:11 | myPassword : | testRealm.swift:16:6:16:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:59:2:59:2 | [post] g [data] : | #select -| testCoreData2.swift:37:2:37:2 | obj | testCoreData2.swift:37:16:37:16 | bankAccountNo : | testCoreData2.swift:37:2:37:2 | [post] obj | This operation stores '[post] obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:37:16:37:16 | bankAccountNo : | bankAccountNo | -| testCoreData2.swift:39:2:39:2 | obj | testCoreData2.swift:39:28:39:28 | bankAccountNo : | testCoreData2.swift:39:2:39:2 | [post] obj | This operation stores '[post] obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:39:28:39:28 | bankAccountNo : | bankAccountNo | -| testCoreData2.swift:41:2:41:2 | obj | testCoreData2.swift:41:29:41:29 | bankAccountNo : | testCoreData2.swift:41:2:41:2 | [post] obj | This operation stores '[post] obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:41:29:41:29 | bankAccountNo : | bankAccountNo | -| testCoreData2.swift:43:2:43:2 | obj | testCoreData2.swift:43:35:43:35 | bankAccountNo : | testCoreData2.swift:43:2:43:2 | [post] obj | This operation stores '[post] obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:43:35:43:35 | bankAccountNo : | bankAccountNo | -| testCoreData2.swift:46:2:46:10 | ...? | testCoreData2.swift:46:22:46:22 | bankAccountNo : | testCoreData2.swift:46:2:46:10 | [post] ...? | This operation stores '[post] ...?' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:46:22:46:22 | bankAccountNo : | bankAccountNo | -| testCoreData2.swift:48:2:48:10 | ...? | testCoreData2.swift:48:34:48:34 | bankAccountNo : | testCoreData2.swift:48:2:48:10 | [post] ...? | This operation stores '[post] ...?' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:48:34:48:34 | bankAccountNo : | bankAccountNo | -| testCoreData2.swift:50:2:50:10 | ...? | testCoreData2.swift:50:35:50:35 | bankAccountNo : | testCoreData2.swift:50:2:50:10 | [post] ...? | This operation stores '[post] ...?' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:50:35:50:35 | bankAccountNo : | bankAccountNo | -| testCoreData2.swift:52:2:52:10 | ...? | testCoreData2.swift:52:41:52:41 | bankAccountNo : | testCoreData2.swift:52:2:52:10 | [post] ...? | This operation stores '[post] ...?' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:52:41:52:41 | bankAccountNo : | bankAccountNo | -| testCoreData2.swift:57:3:57:3 | obj | testCoreData2.swift:57:29:57:29 | bankAccountNo : | testCoreData2.swift:57:3:57:3 | [post] obj | This operation stores '[post] obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:57:29:57:29 | bankAccountNo : | bankAccountNo | -| testCoreData2.swift:60:4:60:4 | obj | testCoreData2.swift:60:30:60:30 | bankAccountNo : | testCoreData2.swift:60:4:60:4 | [post] obj | This operation stores '[post] obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:60:30:60:30 | bankAccountNo : | bankAccountNo | -| testCoreData2.swift:62:4:62:4 | obj | testCoreData2.swift:62:30:62:30 | bankAccountNo : | testCoreData2.swift:62:4:62:4 | [post] obj | This operation stores '[post] obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:62:30:62:30 | bankAccountNo : | bankAccountNo | -| testCoreData2.swift:65:3:65:3 | obj | testCoreData2.swift:65:29:65:29 | bankAccountNo : | testCoreData2.swift:65:3:65:3 | [post] obj | This operation stores '[post] obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:65:29:65:29 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:37:2:37:2 | obj | testCoreData2.swift:37:16:37:16 | bankAccountNo : | testCoreData2.swift:37:2:37:2 | [post] obj | This operation stores 'obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:37:16:37:16 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:39:2:39:2 | obj | testCoreData2.swift:39:28:39:28 | bankAccountNo : | testCoreData2.swift:39:2:39:2 | [post] obj | This operation stores 'obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:39:28:39:28 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:41:2:41:2 | obj | testCoreData2.swift:41:29:41:29 | bankAccountNo : | testCoreData2.swift:41:2:41:2 | [post] obj | This operation stores 'obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:41:29:41:29 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:43:2:43:2 | obj | testCoreData2.swift:43:35:43:35 | bankAccountNo : | testCoreData2.swift:43:2:43:2 | [post] obj | This operation stores 'obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:43:35:43:35 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:46:2:46:10 | ...? | testCoreData2.swift:46:22:46:22 | bankAccountNo : | testCoreData2.swift:46:2:46:10 | [post] ...? | This operation stores '...?' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:46:22:46:22 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:48:2:48:10 | ...? | testCoreData2.swift:48:34:48:34 | bankAccountNo : | testCoreData2.swift:48:2:48:10 | [post] ...? | This operation stores '...?' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:48:34:48:34 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:50:2:50:10 | ...? | testCoreData2.swift:50:35:50:35 | bankAccountNo : | testCoreData2.swift:50:2:50:10 | [post] ...? | This operation stores '...?' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:50:35:50:35 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:52:2:52:10 | ...? | testCoreData2.swift:52:41:52:41 | bankAccountNo : | testCoreData2.swift:52:2:52:10 | [post] ...? | This operation stores '...?' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:52:41:52:41 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:57:3:57:3 | obj | testCoreData2.swift:57:29:57:29 | bankAccountNo : | testCoreData2.swift:57:3:57:3 | [post] obj | This operation stores 'obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:57:29:57:29 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:60:4:60:4 | obj | testCoreData2.swift:60:30:60:30 | bankAccountNo : | testCoreData2.swift:60:4:60:4 | [post] obj | This operation stores 'obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:60:30:60:30 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:62:4:62:4 | obj | testCoreData2.swift:62:30:62:30 | bankAccountNo : | testCoreData2.swift:62:4:62:4 | [post] obj | This operation stores 'obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:62:30:62:30 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:65:3:65:3 | obj | testCoreData2.swift:65:29:65:29 | bankAccountNo : | testCoreData2.swift:65:3:65:3 | [post] obj | This operation stores 'obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:65:29:65:29 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:79:2:79:2 | dbObj | testCoreData2.swift:79:18:79:28 | .bankAccountNo : | testCoreData2.swift:79:2:79:2 | [post] dbObj | This operation stores 'dbObj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:79:18:79:28 | .bankAccountNo : | .bankAccountNo | +| testCoreData2.swift:80:2:80:2 | dbObj | testCoreData2.swift:80:18:80:28 | .bankAccountNo2 : | testCoreData2.swift:80:2:80:2 | [post] dbObj | This operation stores 'dbObj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:80:18:80:28 | .bankAccountNo2 : | .bankAccountNo2 | +| testCoreData2.swift:82:2:82:2 | dbObj | testCoreData2.swift:82:18:82:18 | bankAccountNo : | testCoreData2.swift:82:2:82:2 | [post] dbObj | This operation stores 'dbObj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:82:18:82:18 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:83:2:83:2 | dbObj | testCoreData2.swift:83:18:83:18 | bankAccountNo : | testCoreData2.swift:83:2:83:2 | [post] dbObj | This operation stores 'dbObj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:83:18:83:18 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:84:2:84:2 | dbObj | testCoreData2.swift:84:18:84:18 | bankAccountNo2 : | testCoreData2.swift:84:2:84:2 | [post] dbObj | This operation stores 'dbObj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:84:18:84:18 | bankAccountNo2 : | bankAccountNo2 | +| testCoreData2.swift:85:2:85:2 | dbObj | testCoreData2.swift:85:18:85:18 | bankAccountNo2 : | testCoreData2.swift:85:2:85:2 | [post] dbObj | This operation stores 'dbObj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:85:18:85:18 | bankAccountNo2 : | bankAccountNo2 | +| testCoreData2.swift:87:2:87:10 | ...? | testCoreData2.swift:87:22:87:32 | .bankAccountNo : | testCoreData2.swift:87:2:87:10 | [post] ...? | This operation stores '...?' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:87:22:87:32 | .bankAccountNo : | .bankAccountNo | +| testCoreData2.swift:88:2:88:10 | ...? | testCoreData2.swift:88:22:88:22 | bankAccountNo : | testCoreData2.swift:88:2:88:10 | [post] ...? | This operation stores '...?' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:88:22:88:22 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:89:2:89:10 | ...? | testCoreData2.swift:89:22:89:22 | bankAccountNo2 : | testCoreData2.swift:89:2:89:10 | [post] ...? | This operation stores '...?' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:89:22:89:22 | bankAccountNo2 : | bankAccountNo2 | +| testCoreData2.swift:93:2:93:2 | dbObj | testCoreData2.swift:91:10:91:10 | bankAccountNo : | testCoreData2.swift:93:2:93:2 | [post] dbObj | This operation stores 'dbObj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:91:10:91:10 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:98:2:98:2 | dbObj | testCoreData2.swift:95:10:95:10 | bankAccountNo : | testCoreData2.swift:98:2:98:2 | [post] dbObj | This operation stores 'dbObj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:95:10:95:10 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:104:2:104:2 | dbObj | testCoreData2.swift:101:10:101:10 | bankAccountNo : | testCoreData2.swift:104:2:104:2 | [post] dbObj | This operation stores 'dbObj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:101:10:101:10 | bankAccountNo : | bankAccountNo | +| testCoreData2.swift:105:2:105:2 | dbObj | testCoreData2.swift:101:10:101:10 | bankAccountNo : | testCoreData2.swift:105:2:105:2 | [post] dbObj | This operation stores 'dbObj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:101:10:101:10 | bankAccountNo : | bankAccountNo | | testCoreData.swift:19:12:19:12 | value | testCoreData.swift:61:25:61:25 | password : | testCoreData.swift:19:12:19:12 | value | This operation stores 'value' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:61:25:61:25 | password : | password | | testCoreData.swift:32:13:32:13 | newValue | testCoreData.swift:64:16:64:16 | password : | testCoreData.swift:32:13:32:13 | newValue | This operation stores 'newValue' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:64:16:64:16 | password : | password | | testCoreData.swift:48:15:48:15 | password | testCoreData.swift:48:15:48:15 | password | testCoreData.swift:48:15:48:15 | password | This operation stores 'password' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:48:15:48:15 | password | password | | testCoreData.swift:51:24:51:24 | password | testCoreData.swift:51:24:51:24 | password | testCoreData.swift:51:24:51:24 | password | This operation stores 'password' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:51:24:51:24 | password | password | | testCoreData.swift:58:15:58:15 | password | testCoreData.swift:58:15:58:15 | password | testCoreData.swift:58:15:58:15 | password | This operation stores 'password' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:58:15:58:15 | password | password | -| testCoreData.swift:64:2:64:2 | obj | testCoreData.swift:64:16:64:16 | password : | testCoreData.swift:64:2:64:2 | [post] obj | This operation stores '[post] obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:64:16:64:16 | password : | password | +| testCoreData.swift:64:2:64:2 | obj | testCoreData.swift:64:16:64:16 | password : | testCoreData.swift:64:2:64:2 | [post] obj | This operation stores 'obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:64:16:64:16 | password : | password | | testCoreData.swift:78:15:78:15 | x | testCoreData.swift:77:24:77:24 | x : | testCoreData.swift:78:15:78:15 | x | This operation stores 'x' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:77:24:77:24 | x : | x | | testCoreData.swift:81:15:81:15 | y | testCoreData.swift:80:10:80:22 | call to getPassword() : | testCoreData.swift:81:15:81:15 | y | This operation stores 'y' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:80:10:80:22 | call to getPassword() : | call to getPassword() | | testCoreData.swift:85:15:85:17 | .password | testCoreData.swift:85:15:85:17 | .password | testCoreData.swift:85:15:85:17 | .password | This operation stores '.password' in a database. It may contain unencrypted sensitive data from $@. | testCoreData.swift:85:15:85:17 | .password | .password | @@ -365,7 +542,7 @@ subpaths | testGRDB.swift:208:80:208:89 | [...] | testGRDB.swift:208:81:208:81 | password : | testGRDB.swift:208:80:208:89 | [...] | This operation stores '[...]' in a database. It may contain unencrypted sensitive data from $@. | testGRDB.swift:208:81:208:81 | password : | password | | testGRDB.swift:210:84:210:93 | [...] | testGRDB.swift:210:85:210:85 | password : | testGRDB.swift:210:84:210:93 | [...] | This operation stores '[...]' in a database. It may contain unencrypted sensitive data from $@. | testGRDB.swift:210:85:210:85 | password : | password | | testGRDB.swift:212:98:212:107 | [...] | testGRDB.swift:212:99:212:99 | password : | testGRDB.swift:212:98:212:107 | [...] | This operation stores '[...]' in a database. It may contain unencrypted sensitive data from $@. | testGRDB.swift:212:99:212:99 | password : | password | -| testRealm.swift:34:2:34:2 | a | testRealm.swift:34:11:34:11 | myPassword : | testRealm.swift:34:2:34:2 | [post] a | This operation stores '[post] a' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:34:11:34:11 | myPassword : | myPassword | -| testRealm.swift:42:2:42:2 | c | testRealm.swift:42:11:42:11 | myPassword : | testRealm.swift:42:2:42:2 | [post] c | This operation stores '[post] c' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:42:11:42:11 | myPassword : | myPassword | -| testRealm.swift:52:2:52:3 | ...! | testRealm.swift:52:12:52:12 | myPassword : | testRealm.swift:52:2:52:3 | [post] ...! | This operation stores '[post] ...!' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:52:12:52:12 | myPassword : | myPassword | -| testRealm.swift:59:2:59:2 | g | testRealm.swift:59:11:59:11 | myPassword : | testRealm.swift:59:2:59:2 | [post] g | This operation stores '[post] g' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:59:11:59:11 | myPassword : | myPassword | +| testRealm.swift:34:2:34:2 | a | testRealm.swift:34:11:34:11 | myPassword : | testRealm.swift:34:2:34:2 | [post] a | This operation stores 'a' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:34:11:34:11 | myPassword : | myPassword | +| testRealm.swift:42:2:42:2 | c | testRealm.swift:42:11:42:11 | myPassword : | testRealm.swift:42:2:42:2 | [post] c | This operation stores 'c' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:42:11:42:11 | myPassword : | myPassword | +| testRealm.swift:52:2:52:3 | ...! | testRealm.swift:52:12:52:12 | myPassword : | testRealm.swift:52:2:52:3 | [post] ...! | This operation stores '...!' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:52:12:52:12 | myPassword : | myPassword | +| testRealm.swift:59:2:59:2 | g | testRealm.swift:59:11:59:11 | myPassword : | testRealm.swift:59:2:59:2 | [post] g | This operation stores 'g' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:59:11:59:11 | myPassword : | myPassword | diff --git a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected index 8243711db6a..4f0e89775e4 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected +++ b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected @@ -36,6 +36,18 @@ | testCoreData2.swift:62:30:62:30 | bankAccountNo | label:bankAccountNo, type:private information | | testCoreData2.swift:65:3:65:7 | .myBankAccountNumber | label:myBankAccountNumber, type:private information | | testCoreData2.swift:65:29:65:29 | bankAccountNo | label:bankAccountNo, type:private information | +| testCoreData2.swift:79:18:79:28 | .bankAccountNo | label:bankAccountNo, type:private information | +| testCoreData2.swift:80:18:80:28 | .bankAccountNo2 | label:bankAccountNo2, type:private information | +| testCoreData2.swift:82:18:82:18 | bankAccountNo | label:bankAccountNo, type:private information | +| testCoreData2.swift:83:18:83:18 | bankAccountNo | label:bankAccountNo, type:private information | +| testCoreData2.swift:84:18:84:18 | bankAccountNo2 | label:bankAccountNo2, type:private information | +| testCoreData2.swift:85:18:85:18 | bankAccountNo2 | label:bankAccountNo2, type:private information | +| testCoreData2.swift:87:22:87:32 | .bankAccountNo | label:bankAccountNo, type:private information | +| testCoreData2.swift:88:22:88:22 | bankAccountNo | label:bankAccountNo, type:private information | +| testCoreData2.swift:89:22:89:22 | bankAccountNo2 | label:bankAccountNo2, type:private information | +| testCoreData2.swift:91:10:91:10 | bankAccountNo | label:bankAccountNo, type:private information | +| testCoreData2.swift:95:10:95:10 | bankAccountNo | label:bankAccountNo, type:private information | +| testCoreData2.swift:101:10:101:10 | bankAccountNo | label:bankAccountNo, type:private information | | testCoreData.swift:48:15:48:15 | password | label:password, type:credential | | testCoreData.swift:51:24:51:24 | password | label:password, type:credential | | testCoreData.swift:58:15:58:15 | password | label:password, type:credential | diff --git a/swift/ql/test/query-tests/Security/CWE-311/testCoreData2.swift b/swift/ql/test/query-tests/Security/CWE-311/testCoreData2.swift index 25121dbdb51..9cb61b3bd77 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/testCoreData2.swift +++ b/swift/ql/test/query-tests/Security/CWE-311/testCoreData2.swift @@ -65,3 +65,42 @@ class testCoreData2_2 { obj.myBankAccountNumber = bankAccountNo // BAD } } + +class MyContainer { + var value: Int = 0 + var value2: Int! = 0 + var bankAccountNo: Int = 0 + var bankAccountNo2: Int! = 0 +} + +func testCoreData2_3(dbObj: MyManagedObject2, maybeObj: MyManagedObject2?, container: MyContainer, bankAccountNo: MyContainer, bankAccountNo2: MyContainer!) { + dbObj.myValue = container.value // GOOD (not sensitive) + dbObj.myValue = container.value2 // GOOD (not sensitive) + dbObj.myValue = container.bankAccountNo // BAD + dbObj.myValue = container.bankAccountNo2 // BAD + + dbObj.myValue = bankAccountNo.value // BAD + dbObj.myValue = bankAccountNo.value2 // BAD + dbObj.myValue = bankAccountNo2.value // BAD + dbObj.myValue = bankAccountNo2.value2 // BAD + + maybeObj?.myValue = container.bankAccountNo // BAD + maybeObj?.myValue = bankAccountNo.value // BAD + maybeObj?.myValue = bankAccountNo2.value2 // BAD + + var a = bankAccountNo // sensitive + var b = a.value + dbObj.myValue = b // BAD + + let c = bankAccountNo // sensitive + var d: MyContainer = MyContainer() + d.value = c.value + dbObj.myValue = d.value // BAD + dbObj.myValue = d.value2 // GOOD + + let e = bankAccountNo // sensitive + var f: MyContainer? + f?.value = e.value + dbObj.myValue = e.value // BAD + dbObj.myValue = e.value2 // GOOD [FALSE POSITIVE] +} diff --git a/swift/ql/test/query-tests/Security/CWE-916/InsufficientHashIterations.expected b/swift/ql/test/query-tests/Security/CWE-916/InsufficientHashIterations.expected index 0e46106d3f2..8f432710dc0 100644 --- a/swift/ql/test/query-tests/Security/CWE-916/InsufficientHashIterations.expected +++ b/swift/ql/test/query-tests/Security/CWE-916/InsufficientHashIterations.expected @@ -14,4 +14,4 @@ subpaths | test.swift:37:84:37:84 | lowIterations | test.swift:20:45:20:45 | 99999 : | test.swift:37:84:37:84 | lowIterations | The value '99999' is an insufficient number of iterations for secure password hashing. | | test.swift:38:84:38:84 | 80000 | test.swift:38:84:38:84 | 80000 | test.swift:38:84:38:84 | 80000 | The value '80000' is an insufficient number of iterations for secure password hashing. | | test.swift:44:84:44:84 | lowIterations | test.swift:20:45:20:45 | 99999 : | test.swift:44:84:44:84 | lowIterations | The value '99999' is an insufficient number of iterations for secure password hashing. | -| test.swift:45:84:45:84 | 80000 | test.swift:45:84:45:84 | 80000 | test.swift:45:84:45:84 | 80000 | The value '80000' is an insufficient number of iterations for secure password hashing. | \ No newline at end of file +| test.swift:45:84:45:84 | 80000 | test.swift:45:84:45:84 | 80000 | test.swift:45:84:45:84 | 80000 | The value '80000' is an insufficient number of iterations for secure password hashing. | diff --git a/swift/schema.py b/swift/schema.py index a9b075cd933..2737ebf8ac4 100644 --- a/swift/schema.py +++ b/swift/schema.py @@ -324,7 +324,18 @@ class OpaqueTypeDecl(GenericTypeDecl): opaque_generic_params: list["GenericTypeParamType"] class TypeAliasDecl(GenericTypeDecl): - pass + """ + A declaration of a type alias to another type. For example: + ``` + typealias MyInt = Int + ``` + """ + aliased_type: Type | doc("aliased type on the right-hand side of this type alias declaration") | desc(""" + For example the aliased type of `MyInt` in the following code is `Int`: + ``` + typealias MyInt = Int + ``` + """) class ClassDecl(NominalTypeDecl): pass