diff --git a/.github/workflows/qhelp-pr-preview.yml b/.github/workflows/qhelp-pr-preview.yml index 5cca4faf540..a44ef5ad48d 100644 --- a/.github/workflows/qhelp-pr-preview.yml +++ b/.github/workflows/qhelp-pr-preview.yml @@ -52,7 +52,7 @@ jobs: id: changes run: | (git diff -z --name-only --diff-filter=ACMRT HEAD~1 HEAD | grep -z '.qhelp$' | grep -z -v '.inc.qhelp'; - git diff -z --name-only --diff-filter=ACMRT HEAD~1 HEAD | grep -z '.inc.qhelp$' | xargs --null -rn1 basename | xargs --null -rn1 git grep -z -l) | + git diff -z --name-only --diff-filter=ACMRT HEAD~1 HEAD | grep -z '.inc.qhelp$' | xargs --null -rn1 basename -z | xargs --null -rn1 git grep -z -l) | grep -z '.qhelp$' | grep -z -v '^-' | sort -z -u > "${RUNNER_TEMP}/paths.txt" - name: QHelp preview diff --git a/cpp/ql/lib/CHANGELOG.md b/cpp/ql/lib/CHANGELOG.md index f1dfa53f9ba..5ccbbd8592c 100644 --- a/cpp/ql/lib/CHANGELOG.md +++ b/cpp/ql/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.1 + +No user-facing changes. + ## 0.4.0 ### Deprecated APIs diff --git a/cpp/ql/lib/change-notes/released/0.4.1.md b/cpp/ql/lib/change-notes/released/0.4.1.md new file mode 100644 index 00000000000..0d865d0571e --- /dev/null +++ b/cpp/ql/lib/change-notes/released/0.4.1.md @@ -0,0 +1,3 @@ +## 0.4.1 + +No user-facing changes. diff --git a/cpp/ql/lib/codeql-pack.release.yml b/cpp/ql/lib/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/cpp/ql/lib/codeql-pack.release.yml +++ b/cpp/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index cb70ba272d3..fade2cc7c96 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-all -version: 0.4.1-dev +version: 0.4.2-dev groups: cpp dbscheme: semmlecode.cpp.dbscheme extractor: cpp 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 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 @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 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 @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 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 @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 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 @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/cpp/ql/src/Best Practices/Hiding/LocalVariableHidesGlobalVariable.ql b/cpp/ql/src/Best Practices/Hiding/LocalVariableHidesGlobalVariable.ql index 53c96c4beb7..ef9135f1c0a 100644 --- a/cpp/ql/src/Best Practices/Hiding/LocalVariableHidesGlobalVariable.ql +++ b/cpp/ql/src/Best Practices/Hiding/LocalVariableHidesGlobalVariable.ql @@ -35,4 +35,4 @@ from LocalVariableOrParameter lv, GlobalVariable gv where lv.getName() = gv.getName() and lv.getFile() = gv.getFile() -select lv, lv.type() + gv.getName() + " hides $@ with the same name.", gv, "a global variable" +select lv, lv.type() + gv.getName() + " hides a $@ with the same name.", gv, "global variable" diff --git a/cpp/ql/src/CHANGELOG.md b/cpp/ql/src/CHANGELOG.md index 54dec3b197f..8da02215877 100644 --- a/cpp/ql/src/CHANGELOG.md +++ b/cpp/ql/src/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.4.1 + +### Minor Analysis Improvements + +* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. + ## 0.4.0 ### New Queries diff --git a/cpp/ql/src/Likely Bugs/ShortLoopVarName.ql b/cpp/ql/src/Likely Bugs/ShortLoopVarName.ql index 87dee3c8e30..298e4c1051a 100644 --- a/cpp/ql/src/Likely Bugs/ShortLoopVarName.ql +++ b/cpp/ql/src/Likely Bugs/ShortLoopVarName.ql @@ -48,5 +48,5 @@ where not coordinatePair(iterationVar, innerVar) select iterationVar, "Iteration variable " + iterationVar.getName() + - " for $@ should have a descriptive name, since there is $@.", outer, "this loop", inner, - "a nested loop" + " for $@ should have a descriptive name, since there is a $@.", outer, "this loop", inner, + "nested loop" diff --git a/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql b/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql index d5892844370..9c456f71bbb 100644 --- a/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql +++ b/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql @@ -56,29 +56,26 @@ class VarargsFunction extends Function { result = strictcount(FunctionCall fc | fc = this.getACallToThisFunction()) } - string normalTerminator(int cnt) { + string normalTerminator(int cnt, int totalCount) { + // the terminator is 0 or -1 result = ["0", "-1"] and + // at least 80% of calls have the terminator cnt = this.trailingArgValueCount(result) and - 2 * cnt > this.totalCount() and - not exists(FunctionCall fc, int index | - // terminator value is used in a non-terminating position - this.nonTrailingVarArgValue(fc, index) = result - ) + totalCount = this.totalCount() and + 100 * cnt / totalCount >= 80 and + // terminator value is not used in a non-terminating position + not exists(FunctionCall fc, int index | this.nonTrailingVarArgValue(fc, index) = result) } - predicate isWhitelisted() { - this.hasGlobalName("open") or - this.hasGlobalName("fcntl") or - this.hasGlobalName("ptrace") - } + predicate isWhitelisted() { this.hasGlobalName(["open", "fcntl", "ptrace", "mremap"]) } } -from VarargsFunction f, FunctionCall fc, string terminator, int cnt +from VarargsFunction f, FunctionCall fc, string terminator, int cnt, int totalCount where - terminator = f.normalTerminator(cnt) and + terminator = f.normalTerminator(cnt, totalCount) and fc = f.getACallToThisFunction() and not normalisedExprValue(f.trailingArgumentIn(fc)) = terminator and not f.isWhitelisted() select fc, - "Calls to $@ should use the value " + terminator + " as a terminator (" + cnt + " calls do).", f, - f.getQualifiedName() + "Calls to $@ should use the value " + terminator + " as a terminator (" + cnt + " of " + + totalCount + " calls do).", f, f.getQualifiedName() diff --git a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql index 76ee3b60e13..964b2ff33d8 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql @@ -135,5 +135,5 @@ where sink.getNode().asExpr() = va and missingGuard(va, effect) select sink.getNode(), source, sink, - "Arithmetic expression depends on an $@, potentially causing an " + effect + ".", + "This arithmetic expression depends on an $@, potentially causing an " + effect + ".", getExpr(source.getNode()), "uncontrolled value" diff --git a/cpp/ql/src/change-notes/2022-10-06-unterminated-variadic-call.md b/cpp/ql/src/change-notes/2022-10-06-unterminated-variadic-call.md new file mode 100644 index 00000000000..d986ba666ff --- /dev/null +++ b/cpp/ql/src/change-notes/2022-10-06-unterminated-variadic-call.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The "Unterminated variadic call" (`cpp/unterminated-variadic-call`) query has been tuned to produce fewer false positive results. diff --git a/csharp/ql/src/change-notes/2022-09-29-alert-messages.md b/cpp/ql/src/change-notes/released/0.4.1.md similarity index 76% rename from csharp/ql/src/change-notes/2022-09-29-alert-messages.md rename to cpp/ql/src/change-notes/released/0.4.1.md index c6ce24514b8..f5e1dbf00ed 100644 --- a/csharp/ql/src/change-notes/2022-09-29-alert-messages.md +++ b/cpp/ql/src/change-notes/released/0.4.1.md @@ -1,4 +1,5 @@ ---- -category: minorAnalysis ---- +## 0.4.1 + +### Minor Analysis Improvements + * The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. diff --git a/cpp/ql/src/codeql-pack.release.yml b/cpp/ql/src/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/cpp/ql/src/codeql-pack.release.yml +++ b/cpp/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml index 12c12ffe83e..169ac0a41ee 100644 --- a/cpp/ql/src/qlpack.yml +++ b/cpp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-queries -version: 0.4.1-dev +version: 0.4.2-dev groups: - cpp - queries diff --git a/cpp/ql/test/examples/BadLocking/LocalVariableHidesGlobalVariable.expected b/cpp/ql/test/examples/BadLocking/LocalVariableHidesGlobalVariable.expected index 4aaecc3b3bd..531452ba1b4 100644 --- a/cpp/ql/test/examples/BadLocking/LocalVariableHidesGlobalVariable.expected +++ b/cpp/ql/test/examples/BadLocking/LocalVariableHidesGlobalVariable.expected @@ -1 +1 @@ -| UnintendedDeclaration.cpp:65:14:65:20 | definition of myMutex | Local variable myMutex hides $@ with the same name. | UnintendedDeclaration.cpp:40:7:40:13 | myMutex | a global variable | +| UnintendedDeclaration.cpp:65:14:65:20 | definition of myMutex | Local variable myMutex hides a $@ with the same name. | UnintendedDeclaration.cpp:40:7:40:13 | myMutex | global variable | diff --git a/cpp/ql/test/query-tests/Best Practices/Hiding/LocalVariableHidesGlobalVariable/LocalVariableHidesGlobalVariable.expected b/cpp/ql/test/query-tests/Best Practices/Hiding/LocalVariableHidesGlobalVariable/LocalVariableHidesGlobalVariable.expected index 1ad05dacf8b..d79adba14e4 100644 --- a/cpp/ql/test/query-tests/Best Practices/Hiding/LocalVariableHidesGlobalVariable/LocalVariableHidesGlobalVariable.expected +++ b/cpp/ql/test/query-tests/Best Practices/Hiding/LocalVariableHidesGlobalVariable/LocalVariableHidesGlobalVariable.expected @@ -1,5 +1,5 @@ -| Hiding.c:22:25:22:26 | definition of gi | Local variable gi hides $@ with the same name. | Hiding.c:2:5:2:6 | gi | a global variable | -| Hiding.c:23:25:23:26 | definition of gj | Local variable gj hides $@ with the same name. | Hiding.c:3:12:3:13 | gj | a global variable | -| Hiding.c:24:25:24:26 | definition of gk | Local variable gk hides $@ with the same name. | Hiding.c:4:12:4:13 | gk | a global variable | -| Hiding.c:37:20:37:21 | definition of g3 | Parameter g3 hides $@ with the same name. | Hiding.c:33:13:33:14 | g3 | a global variable | -| Hiding.c:40:20:40:21 | definition of g5 | Parameter g5 hides $@ with the same name. | Hiding.c:33:21:33:22 | g5 | a global variable | +| Hiding.c:22:25:22:26 | definition of gi | Local variable gi hides a $@ with the same name. | Hiding.c:2:5:2:6 | gi | global variable | +| Hiding.c:23:25:23:26 | definition of gj | Local variable gj hides a $@ with the same name. | Hiding.c:3:12:3:13 | gj | global variable | +| Hiding.c:24:25:24:26 | definition of gk | Local variable gk hides a $@ with the same name. | Hiding.c:4:12:4:13 | gk | global variable | +| Hiding.c:37:20:37:21 | definition of g3 | Parameter g3 hides a $@ with the same name. | Hiding.c:33:13:33:14 | g3 | global variable | +| Hiding.c:40:20:40:21 | definition of g5 | Parameter g5 hides a $@ with the same name. | Hiding.c:33:21:33:22 | g5 | global variable | diff --git a/cpp/ql/test/query-tests/Likely Bugs/ShortLoopVarName/ShortLoopVarName.expected b/cpp/ql/test/query-tests/Likely Bugs/ShortLoopVarName/ShortLoopVarName.expected index 16c5690bf75..22b1f8f4456 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/ShortLoopVarName/ShortLoopVarName.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/ShortLoopVarName/ShortLoopVarName.expected @@ -1,4 +1,4 @@ -| ShortLoopVarName.cpp:6:6:6:6 | i | Iteration variable i for $@ should have a descriptive name, since there is $@. | ShortLoopVarName.cpp:12:2:18:2 | for(...;...;...) ... | this loop | ShortLoopVarName.cpp:14:3:17:3 | for(...;...;...) ... | a nested loop | -| ShortLoopVarName.cpp:30:13:30:13 | a | Iteration variable a for $@ should have a descriptive name, since there is $@. | ShortLoopVarName.cpp:30:2:38:2 | for(...;...;...) ... | this loop | ShortLoopVarName.cpp:34:3:37:3 | for(...;...;...) ... | a nested loop | -| ShortLoopVarName.cpp:73:11:73:11 | y | Iteration variable y for $@ should have a descriptive name, since there is $@. | ShortLoopVarName.cpp:73:2:80:2 | for(...;...;...) ... | this loop | ShortLoopVarName.cpp:75:3:79:3 | for(...;...;...) ... | a nested loop | -| ShortLoopVarName.cpp:96:12:96:12 | i | Iteration variable i for $@ should have a descriptive name, since there is $@. | ShortLoopVarName.cpp:96:3:102:3 | for(...;...;...) ... | this loop | ShortLoopVarName.cpp:98:4:101:4 | for(...;...;...) ... | a nested loop | +| ShortLoopVarName.cpp:6:6:6:6 | i | Iteration variable i for $@ should have a descriptive name, since there is a $@. | ShortLoopVarName.cpp:12:2:18:2 | for(...;...;...) ... | this loop | ShortLoopVarName.cpp:14:3:17:3 | for(...;...;...) ... | nested loop | +| ShortLoopVarName.cpp:30:13:30:13 | a | Iteration variable a for $@ should have a descriptive name, since there is a $@. | ShortLoopVarName.cpp:30:2:38:2 | for(...;...;...) ... | this loop | ShortLoopVarName.cpp:34:3:37:3 | for(...;...;...) ... | nested loop | +| ShortLoopVarName.cpp:73:11:73:11 | y | Iteration variable y for $@ should have a descriptive name, since there is a $@. | ShortLoopVarName.cpp:73:2:80:2 | for(...;...;...) ... | this loop | ShortLoopVarName.cpp:75:3:79:3 | for(...;...;...) ... | nested loop | +| ShortLoopVarName.cpp:96:12:96:12 | i | Iteration variable i for $@ should have a descriptive name, since there is a $@. | ShortLoopVarName.cpp:96:3:102:3 | for(...;...;...) ... | this loop | ShortLoopVarName.cpp:98:4:101:4 | for(...;...;...) ... | nested loop | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-121/semmle/tests/UnterminatedVarargsCall.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-121/semmle/tests/UnterminatedVarargsCall.expected index e1b64faea28..2cf386e2f41 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-121/semmle/tests/UnterminatedVarargsCall.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-121/semmle/tests/UnterminatedVarargsCall.expected @@ -1,9 +1,9 @@ -| more_tests.cpp:23:2:23:12 | call to myFunction2 | Calls to $@ should use the value -1 as a terminator (4 calls do). | more_tests.cpp:5:6:5:16 | myFunction2 | myFunction2 | -| more_tests.cpp:34:2:34:12 | call to myFunction4 | Calls to $@ should use the value 0 as a terminator (3 calls do). | more_tests.cpp:7:6:7:16 | myFunction4 | myFunction4 | -| more_tests.cpp:44:2:44:12 | call to myFunction6 | Calls to $@ should use the value 0 as a terminator (3 calls do). | more_tests.cpp:9:6:9:16 | myFunction6 | myFunction6 | -| more_tests.cpp:55:2:55:12 | call to myFunction7 | Calls to $@ should use the value 0 as a terminator (7 calls do). | more_tests.cpp:10:6:10:16 | myFunction7 | myFunction7 | -| more_tests.cpp:56:2:56:12 | call to myFunction7 | Calls to $@ should use the value 0 as a terminator (7 calls do). | more_tests.cpp:10:6:10:16 | myFunction7 | myFunction7 | -| tests.c:34:2:34:3 | call to f1 | Calls to $@ should use the value 0 as a terminator (4 calls do). | tests.c:4:6:4:7 | f1 | f1 | -| tests.c:67:2:67:3 | call to f6 | Calls to $@ should use the value -1 as a terminator (3 calls do). | tests.c:24:6:24:7 | f6 | f6 | -| tests.c:68:2:68:3 | call to f6 | Calls to $@ should use the value -1 as a terminator (3 calls do). | tests.c:24:6:24:7 | f6 | f6 | -| tests.c:73:2:73:3 | call to f7 | Calls to $@ should use the value 0 as a terminator (3 calls do). | tests.c:28:6:28:7 | f7 | f7 | +| more_tests.cpp:25:2:25:12 | call to myFunction2 | Calls to $@ should use the value -1 as a terminator (5 of 6 calls do). | more_tests.cpp:5:6:5:16 | myFunction2 | myFunction2 | +| more_tests.cpp:39:2:39:12 | call to myFunction4 | Calls to $@ should use the value 0 as a terminator (5 of 6 calls do). | more_tests.cpp:7:6:7:16 | myFunction4 | myFunction4 | +| more_tests.cpp:49:2:49:12 | call to myFunction6 | Calls to $@ should use the value 0 as a terminator (5 of 6 calls do). | more_tests.cpp:9:6:9:16 | myFunction6 | myFunction6 | +| more_tests.cpp:64:2:64:12 | call to myFunction7 | Calls to $@ should use the value 0 as a terminator (9 of 11 calls do). | more_tests.cpp:10:6:10:16 | myFunction7 | myFunction7 | +| more_tests.cpp:65:2:65:12 | call to myFunction7 | Calls to $@ should use the value 0 as a terminator (9 of 11 calls do). | more_tests.cpp:10:6:10:16 | myFunction7 | myFunction7 | +| tests.c:34:2:34:3 | call to f1 | Calls to $@ should use the value 0 as a terminator (4 of 5 calls do). | tests.c:4:6:4:7 | f1 | f1 | +| tests.c:78:2:78:3 | call to f6 | Calls to $@ should use the value -1 as a terminator (10 of 12 calls do). | tests.c:24:6:24:7 | f6 | f6 | +| tests.c:79:2:79:3 | call to f6 | Calls to $@ should use the value -1 as a terminator (10 of 12 calls do). | tests.c:24:6:24:7 | f6 | f6 | +| tests.c:84:2:84:3 | call to f7 | Calls to $@ should use the value 0 as a terminator (12 of 13 calls do). | tests.c:28:6:28:7 | f7 | f7 | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-121/semmle/tests/more_tests.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-121/semmle/tests/more_tests.cpp index a8c34fb490a..d6c9a3915e7 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-121/semmle/tests/more_tests.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-121/semmle/tests/more_tests.cpp @@ -13,27 +13,32 @@ int main() { int x; - myFunction1("%i", 0); // not common enough to be assumed a terminator + myFunction1("%i", 0); // GOOD: not common enough to be assumed a terminator + myFunction1("%i", 0); myFunction1("%i", x); myFunction2(-1); myFunction2(0, -1); myFunction2(0, 1, -1); myFunction2(0, 1, 2, -1); - myFunction2(0, 1, 2, 3); // missing terminator + myFunction2(0, 1, 2, 3, -1); + myFunction2(0, 1, 2, 3, 4); // BAD: missing terminator myFunction3(-1); myFunction3(0, -1); - myFunction3(-1, 1, -1); // -1 isn't a terminator because it's used in a non-terminal position + myFunction3(-1, 1, -1); // GOOD: -1 isn't a terminator because it's used in a non-terminal position myFunction3(0, 1, 2, -1); - myFunction3(0, 1, 2, 3); + myFunction3(0, 1, 2, 3, -1); + myFunction3(0, 1, 2, 3, 4); myFunction4(x, x, 0); myFunction4(0, x, 1, 0); myFunction4(0, 0, 1, 1, 0); - myFunction4(x, 0, 1, 1, 1); // missing terminator + myFunction4(0, x, 1, 1, 1, 0); + myFunction4(0, 0, 1, 1, 1, 1, 0); + myFunction4(x, 0, 1, 1, 1, 1, 1); // BAD: missing terminator - myFunction5('a', 'b', 'c', 0); // ambiguous terminator + myFunction5('a', 'b', 'c', 0); // GOOD: ambiguous terminator myFunction5('a', 'b', 'c', 0); myFunction5('a', 'b', 'c', 0); myFunction5('a', 'b', 'c', -1); @@ -41,19 +46,23 @@ int main() myFunction5('a', 'b', 'c', -1); myFunction6(0.0); - myFunction6(1.0); // missing terminator + myFunction6(1.0); // BAD: missing terminator myFunction6(1.0, 2.0, 0.0); myFunction6(1.0, 2.0, 3.0, 0.0); + myFunction6(1.0, 2.0, 3.0, 4.0, 0.0); + myFunction6(1.0, 2.0, 3.0, 4.0, 5.0, 0.0); myFunction7(NULL); myFunction7("hello", "world", NULL); myFunction7("apple", "banana", "pear", "mango", NULL); myFunction7("dog", "cat", "elephant", "badger", "fish", NULL); myFunction7("one", "two", "three", 0); + myFunction7("four", "five", "six", 0); + myFunction7("seven", "eight", "nine", 0); myFunction7("alpha", "beta", "gamma", 0); myFunction7("", 0); - myFunction7("yes", "no"); // missing terminator - myFunction7(); // missing terminator + myFunction7("yes", "no"); // BAD: missing terminator + myFunction7(); // BAD: missing terminator return 0; } \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-121/semmle/tests/tests.c b/cpp/ql/test/query-tests/Security/CWE/CWE-121/semmle/tests/tests.c index a02a6e02b56..f89d19cf3c7 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-121/semmle/tests/tests.c +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-121/semmle/tests/tests.c @@ -42,6 +42,7 @@ int main(int argc, char *argv[]) // GOOD: 0 is not common enough to be sure it's a terminator f3("", 0); + f3("", 0); f3("", 10); // GOOD: -1 is not common enough to be sure it's a terminator @@ -50,6 +51,9 @@ int main(int argc, char *argv[]) f4("", -1); f4("", -1); f4("", -1); + f4("", -1); + f4("", -1); + f4("", -1); f4("", 1); // GOOD: no obvious required terminator @@ -61,16 +65,32 @@ int main(int argc, char *argv[]) f5("", 0); f5("", 10); - f6("fsdf", 3, 8, -1); - f6("a", 7, 9, 10, -1); - f6("a", 1, 22, 6, 17, 2, -1); - f6("fgasfgas", 5, 6, argc); // BAD: not (necessarily) terminated with -1 - f6("sadfsaf"); // BAD: not terminated with -1 + f6("a", 3, 8, -1); + f6("b", 7, 9, 10, -1); + f6("c", 1, 22, 6, 17, 2, -1); + f6("d", 1, -1); + f6("e", 1, 2, -1); + f6("f", 1, 2, 3, -1); + f6("g", 1, 2, 3, 4, -1); + f6("h", 5, -1); + f6("i", 5, 6, -1); + f6("j", 5, 6, 7, -1); + f6("k", 5, 6, argc); // BAD: not (necessarily) terminated with -1 + f6("l"); // BAD: not terminated with -1 f7("", 0); f7("", 0); f7("", 0); f7(""); // BAD: not terminated with 0 + f7("", 0); + f7("", 0); + f7("", 0); + f7("", 0); + f7("", 0); + f7("", 0); + f7("", 0); + f7("", 0); + f7("", 0); return 0; } \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/SAMATE/ArithmeticUncontrolled.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/SAMATE/ArithmeticUncontrolled.expected index b672d501c5e..3834d769463 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/SAMATE/ArithmeticUncontrolled.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/SAMATE/ArithmeticUncontrolled.expected @@ -52,27 +52,27 @@ nodes | examples.cpp:38:9:38:12 | data | semmle.label | data | subpaths #select -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | Arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/ArithmeticUncontrolled/ArithmeticUncontrolled.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/ArithmeticUncontrolled/ArithmeticUncontrolled.expected index efec436a131..011f8f73819 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/ArithmeticUncontrolled/ArithmeticUncontrolled.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/ArithmeticUncontrolled/ArithmeticUncontrolled.expected @@ -92,31 +92,31 @@ nodes | test.cpp:219:8:219:8 | x | semmle.label | x | subpaths #select -| test.c:21:17:21:17 | r | test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:18:13:18:16 | call to rand | uncontrolled value | -| test.c:35:5:35:5 | r | test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:34:13:34:18 | call to rand | uncontrolled value | -| test.c:45:5:45:5 | r | test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:44:13:44:16 | call to rand | uncontrolled value | -| test.c:77:9:77:9 | r | test.c:75:13:75:19 | call to rand | test.c:77:9:77:9 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:75:13:75:19 | call to rand | uncontrolled value | -| test.c:77:9:77:9 | r | test.c:75:13:75:19 | call to rand | test.c:77:9:77:9 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:75:13:75:19 | call to rand | uncontrolled value | -| test.c:83:9:83:9 | r | test.c:81:14:81:17 | call to rand | test.c:83:9:83:9 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:81:14:81:17 | call to rand | uncontrolled value | -| test.c:83:9:83:9 | r | test.c:81:23:81:26 | call to rand | test.c:83:9:83:9 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:81:23:81:26 | call to rand | uncontrolled value | -| test.c:127:9:127:9 | r | test.c:125:13:125:16 | call to rand | test.c:127:9:127:9 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:125:13:125:16 | call to rand | uncontrolled value | -| test.c:133:5:133:5 | r | test.c:131:13:131:16 | call to rand | test.c:133:5:133:5 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:131:13:131:16 | call to rand | uncontrolled value | -| test.c:139:10:139:10 | r | test.c:137:13:137:16 | call to rand | test.c:139:10:139:10 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.c:137:13:137:16 | call to rand | uncontrolled value | -| test.c:157:9:157:9 | r | test.c:155:22:155:25 | call to rand | test.c:157:9:157:9 | r | Arithmetic expression depends on an $@, potentially causing an underflow. | test.c:155:22:155:25 | call to rand | uncontrolled value | -| test.c:157:9:157:9 | r | test.c:155:22:155:27 | (unsigned int)... | test.c:157:9:157:9 | r | Arithmetic expression depends on an $@, potentially causing an underflow. | test.c:155:22:155:25 | call to rand | uncontrolled value | -| test.cpp:25:7:25:7 | r | test.cpp:8:9:8:12 | call to rand | test.cpp:25:7:25:7 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:8:9:8:12 | call to rand | uncontrolled value | -| test.cpp:31:7:31:7 | r | test.cpp:13:10:13:13 | call to rand | test.cpp:31:7:31:7 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:13:10:13:13 | call to rand | uncontrolled value | -| test.cpp:37:7:37:7 | r | test.cpp:18:9:18:12 | call to rand | test.cpp:37:7:37:7 | r | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:18:9:18:12 | call to rand | uncontrolled value | -| test.cpp:90:10:90:10 | x | test.cpp:86:10:86:13 | call to rand | test.cpp:90:10:90:10 | x | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:86:10:86:13 | call to rand | uncontrolled value | -| test.cpp:102:10:102:10 | x | test.cpp:98:10:98:13 | call to rand | test.cpp:102:10:102:10 | x | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:98:10:98:13 | call to rand | uncontrolled value | -| test.cpp:146:9:146:9 | y | test.cpp:137:10:137:13 | call to rand | test.cpp:146:9:146:9 | y | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:137:10:137:13 | call to rand | uncontrolled value | -| test.cpp:154:10:154:10 | b | test.cpp:151:10:151:13 | call to rand | test.cpp:154:10:154:10 | b | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:151:10:151:13 | call to rand | uncontrolled value | -| test.cpp:171:11:171:16 | (int)... | test.cpp:169:11:169:14 | call to rand | test.cpp:171:11:171:16 | (int)... | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:169:11:169:14 | call to rand | uncontrolled value | -| test.cpp:171:16:171:16 | y | test.cpp:169:11:169:14 | call to rand | test.cpp:171:16:171:16 | y | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:169:11:169:14 | call to rand | uncontrolled value | -| test.cpp:196:7:196:7 | x | test.cpp:189:10:189:13 | call to rand | test.cpp:196:7:196:7 | x | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:189:10:189:13 | call to rand | uncontrolled value | -| test.cpp:198:7:198:7 | x | test.cpp:189:10:189:13 | call to rand | test.cpp:198:7:198:7 | x | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:189:10:189:13 | call to rand | uncontrolled value | -| test.cpp:199:7:199:7 | x | test.cpp:189:10:189:13 | call to rand | test.cpp:199:7:199:7 | x | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:189:10:189:13 | call to rand | uncontrolled value | -| test.cpp:204:7:204:7 | y | test.cpp:190:10:190:13 | call to rand | test.cpp:204:7:204:7 | y | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:190:10:190:13 | call to rand | uncontrolled value | -| test.cpp:205:7:205:7 | y | test.cpp:190:10:190:13 | call to rand | test.cpp:205:7:205:7 | y | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:190:10:190:13 | call to rand | uncontrolled value | -| test.cpp:208:7:208:7 | y | test.cpp:190:10:190:13 | call to rand | test.cpp:208:7:208:7 | y | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:190:10:190:13 | call to rand | uncontrolled value | -| test.cpp:219:8:219:8 | x | test.cpp:215:11:215:14 | call to rand | test.cpp:219:8:219:8 | x | Arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:215:11:215:14 | call to rand | uncontrolled value | +| test.c:21:17:21:17 | r | test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:18:13:18:16 | call to rand | uncontrolled value | +| test.c:35:5:35:5 | r | test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:34:13:34:18 | call to rand | uncontrolled value | +| test.c:45:5:45:5 | r | test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:44:13:44:16 | call to rand | uncontrolled value | +| test.c:77:9:77:9 | r | test.c:75:13:75:19 | call to rand | test.c:77:9:77:9 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:75:13:75:19 | call to rand | uncontrolled value | +| test.c:77:9:77:9 | r | test.c:75:13:75:19 | call to rand | test.c:77:9:77:9 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:75:13:75:19 | call to rand | uncontrolled value | +| test.c:83:9:83:9 | r | test.c:81:14:81:17 | call to rand | test.c:83:9:83:9 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:81:14:81:17 | call to rand | uncontrolled value | +| test.c:83:9:83:9 | r | test.c:81:23:81:26 | call to rand | test.c:83:9:83:9 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:81:23:81:26 | call to rand | uncontrolled value | +| test.c:127:9:127:9 | r | test.c:125:13:125:16 | call to rand | test.c:127:9:127:9 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:125:13:125:16 | call to rand | uncontrolled value | +| test.c:133:5:133:5 | r | test.c:131:13:131:16 | call to rand | test.c:133:5:133:5 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:131:13:131:16 | call to rand | uncontrolled value | +| test.c:139:10:139:10 | r | test.c:137:13:137:16 | call to rand | test.c:139:10:139:10 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:137:13:137:16 | call to rand | uncontrolled value | +| test.c:157:9:157:9 | r | test.c:155:22:155:25 | call to rand | test.c:157:9:157:9 | r | This arithmetic expression depends on an $@, potentially causing an underflow. | test.c:155:22:155:25 | call to rand | uncontrolled value | +| test.c:157:9:157:9 | r | test.c:155:22:155:27 | (unsigned int)... | test.c:157:9:157:9 | r | This arithmetic expression depends on an $@, potentially causing an underflow. | test.c:155:22:155:25 | call to rand | uncontrolled value | +| test.cpp:25:7:25:7 | r | test.cpp:8:9:8:12 | call to rand | test.cpp:25:7:25:7 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:8:9:8:12 | call to rand | uncontrolled value | +| test.cpp:31:7:31:7 | r | test.cpp:13:10:13:13 | call to rand | test.cpp:31:7:31:7 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:13:10:13:13 | call to rand | uncontrolled value | +| test.cpp:37:7:37:7 | r | test.cpp:18:9:18:12 | call to rand | test.cpp:37:7:37:7 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:18:9:18:12 | call to rand | uncontrolled value | +| test.cpp:90:10:90:10 | x | test.cpp:86:10:86:13 | call to rand | test.cpp:90:10:90:10 | x | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:86:10:86:13 | call to rand | uncontrolled value | +| test.cpp:102:10:102:10 | x | test.cpp:98:10:98:13 | call to rand | test.cpp:102:10:102:10 | x | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:98:10:98:13 | call to rand | uncontrolled value | +| test.cpp:146:9:146:9 | y | test.cpp:137:10:137:13 | call to rand | test.cpp:146:9:146:9 | y | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:137:10:137:13 | call to rand | uncontrolled value | +| test.cpp:154:10:154:10 | b | test.cpp:151:10:151:13 | call to rand | test.cpp:154:10:154:10 | b | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:151:10:151:13 | call to rand | uncontrolled value | +| test.cpp:171:11:171:16 | (int)... | test.cpp:169:11:169:14 | call to rand | test.cpp:171:11:171:16 | (int)... | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:169:11:169:14 | call to rand | uncontrolled value | +| test.cpp:171:16:171:16 | y | test.cpp:169:11:169:14 | call to rand | test.cpp:171:16:171:16 | y | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:169:11:169:14 | call to rand | uncontrolled value | +| test.cpp:196:7:196:7 | x | test.cpp:189:10:189:13 | call to rand | test.cpp:196:7:196:7 | x | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:189:10:189:13 | call to rand | uncontrolled value | +| test.cpp:198:7:198:7 | x | test.cpp:189:10:189:13 | call to rand | test.cpp:198:7:198:7 | x | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:189:10:189:13 | call to rand | uncontrolled value | +| test.cpp:199:7:199:7 | x | test.cpp:189:10:189:13 | call to rand | test.cpp:199:7:199:7 | x | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:189:10:189:13 | call to rand | uncontrolled value | +| test.cpp:204:7:204:7 | y | test.cpp:190:10:190:13 | call to rand | test.cpp:204:7:204:7 | y | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:190:10:190:13 | call to rand | uncontrolled value | +| test.cpp:205:7:205:7 | y | test.cpp:190:10:190:13 | call to rand | test.cpp:205:7:205:7 | y | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:190:10:190:13 | call to rand | uncontrolled value | +| test.cpp:208:7:208:7 | y | test.cpp:190:10:190:13 | call to rand | test.cpp:208:7:208:7 | y | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:190:10:190:13 | call to rand | uncontrolled value | +| test.cpp:219:8:219:8 | x | test.cpp:215:11:215:14 | call to rand | test.cpp:219:8:219:8 | x | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:215:11:215:14 | call to rand | uncontrolled value | diff --git a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md index 49d355ec453..afbbf19794a 100644 --- a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md +++ b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.1 + +No user-facing changes. + ## 1.3.0 No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.3.1.md b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.3.1.md new file mode 100644 index 00000000000..8dd9964197c --- /dev/null +++ b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.3.1.md @@ -0,0 +1,3 @@ +## 1.3.1 + +No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml index ec16350ed6f..e71b6d081f1 100644 --- a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml +++ b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.3.0 +lastReleaseVersion: 1.3.1 diff --git a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml index 648df77d7ff..96ed3493829 100644 --- a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-all -version: 1.3.1-dev +version: 1.3.2-dev groups: - csharp - solorigate diff --git a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md index 49d355ec453..afbbf19794a 100644 --- a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md +++ b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.1 + +No user-facing changes. + ## 1.3.0 No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.3.1.md b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.3.1.md new file mode 100644 index 00000000000..8dd9964197c --- /dev/null +++ b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.3.1.md @@ -0,0 +1,3 @@ +## 1.3.1 + +No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml index ec16350ed6f..e71b6d081f1 100644 --- a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml +++ b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.3.0 +lastReleaseVersion: 1.3.1 diff --git a/csharp/ql/campaigns/Solorigate/src/qlpack.yml b/csharp/ql/campaigns/Solorigate/src/qlpack.yml index 940cdf055f8..888b9099b3d 100644 --- a/csharp/ql/campaigns/Solorigate/src/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-queries -version: 1.3.1-dev +version: 1.3.2-dev groups: - csharp - solorigate diff --git a/csharp/ql/lib/CHANGELOG.md b/csharp/ql/lib/CHANGELOG.md index 83b9e7b837c..c303fa86a4a 100644 --- a/csharp/ql/lib/CHANGELOG.md +++ b/csharp/ql/lib/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.4.1 + +### Minor Analysis Improvements + +* `DateTime` expressions are now considered simple type sanitizers. This affects a wide range of security queries. +* ASP.NET Core controller definition has been made more precise. The amount of introduced taint sources or eliminated false positives should be low though, since the most common pattern is to derive all user defined ASP.NET Core controllers from the standard Controller class, which is not affected. + ## 0.4.0 ### Deprecated APIs diff --git a/csharp/ql/lib/change-notes/2022-09-23-simpletypesanitizer.md b/csharp/ql/lib/change-notes/2022-09-23-simpletypesanitizer.md deleted file mode 100644 index a4d7e4cde7a..00000000000 --- a/csharp/ql/lib/change-notes/2022-09-23-simpletypesanitizer.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* `DateTime` expressions are now considered simple type sanitizers. This affects a wide range of security queries. \ No newline at end of file diff --git a/csharp/ql/lib/change-notes/2022-08-24-aps-net-core-controllers.md b/csharp/ql/lib/change-notes/released/0.4.1.md similarity index 65% rename from csharp/ql/lib/change-notes/2022-08-24-aps-net-core-controllers.md rename to csharp/ql/lib/change-notes/released/0.4.1.md index b3b5006bc57..f3bdef7797c 100644 --- a/csharp/ql/lib/change-notes/2022-08-24-aps-net-core-controllers.md +++ b/csharp/ql/lib/change-notes/released/0.4.1.md @@ -1,4 +1,6 @@ ---- -category: minorAnalysis ---- +## 0.4.1 + +### Minor Analysis Improvements + +* `DateTime` expressions are now considered simple type sanitizers. This affects a wide range of security queries. * ASP.NET Core controller definition has been made more precise. The amount of introduced taint sources or eliminated false positives should be low though, since the most common pattern is to derive all user defined ASP.NET Core controllers from the standard Controller class, which is not affected. diff --git a/csharp/ql/lib/codeql-pack.release.yml b/csharp/ql/lib/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/csharp/ql/lib/codeql-pack.release.yml +++ b/csharp/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/csharp/ql/lib/qlpack.yml b/csharp/ql/lib/qlpack.yml index 270ae8a65aa..8b00f8845c2 100644 --- a/csharp/ql/lib/qlpack.yml +++ b/csharp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-all -version: 0.4.1-dev +version: 0.4.2-dev groups: csharp dbscheme: semmlecode.csharp.dbscheme extractor: csharp 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/csharp/ql/src/CHANGELOG.md b/csharp/ql/src/CHANGELOG.md index bf47d9f7f70..8bd7652a52c 100644 --- a/csharp/ql/src/CHANGELOG.md +++ b/csharp/ql/src/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.4.1 + +### Minor Analysis Improvements + +* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. + ## 0.4.0 ### Minor Analysis Improvements diff --git a/java/ql/src/change-notes/2022-09-23-alert-messages.md b/csharp/ql/src/change-notes/released/0.4.1.md similarity index 69% rename from java/ql/src/change-notes/2022-09-23-alert-messages.md rename to csharp/ql/src/change-notes/released/0.4.1.md index de46b7752eb..f5e1dbf00ed 100644 --- a/java/ql/src/change-notes/2022-09-23-alert-messages.md +++ b/csharp/ql/src/change-notes/released/0.4.1.md @@ -1,4 +1,5 @@ ---- -category: minorAnalysis ---- -* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. \ No newline at end of file +## 0.4.1 + +### Minor Analysis Improvements + +* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. diff --git a/csharp/ql/src/codeql-pack.release.yml b/csharp/ql/src/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/csharp/ql/src/codeql-pack.release.yml +++ b/csharp/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/csharp/ql/src/experimental/CWE-099/TaintedWebClient.ql b/csharp/ql/src/experimental/CWE-099/TaintedWebClient.ql index 513c658cf92..8cee95a3d54 100644 --- a/csharp/ql/src/experimental/CWE-099/TaintedWebClient.ql +++ b/csharp/ql/src/experimental/CWE-099/TaintedWebClient.ql @@ -19,5 +19,5 @@ import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph from TaintTrackingConfiguration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "$@ flows to here and is used in a method of WebClient.", - source.getNode(), "User-provided value" +select sink.getNode(), source, sink, "A method of WebClient depepends on a $@.", source.getNode(), + "user-provided value" diff --git a/csharp/ql/src/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.ql b/csharp/ql/src/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.ql index 57561944718..753dfb82999 100644 --- a/csharp/ql/src/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.ql +++ b/csharp/ql/src/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.ql @@ -17,5 +17,6 @@ import JsonWebTokenHandlerLib from TokenValidationParametersProperty p, CallableAlwaysReturnsTrueHigherPrecision e where e = p.getAnAssignedValue() -select e, "JsonWebTokenHandler security-sensitive property $@ is being delegated to $@.", p, - p.getQualifiedName().toString(), e, "a callable that always returns \"true\"" +select e, + "JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns \"true\".", + p, p.getQualifiedName().toString() diff --git a/csharp/ql/src/experimental/Security Features/backdoor/ProcessNameToHashTaintFlow.ql b/csharp/ql/src/experimental/Security Features/backdoor/ProcessNameToHashTaintFlow.ql index 14d0cc02e44..5bb8a1dc6e9 100644 --- a/csharp/ql/src/experimental/Security Features/backdoor/ProcessNameToHashTaintFlow.ql +++ b/csharp/ql/src/experimental/Security Features/backdoor/ProcessNameToHashTaintFlow.ql @@ -50,5 +50,5 @@ predicate isSuspiciousPropertyName(PropertyRead pr) { from DataFlow::PathNode src, DataFlow::PathNode sink, DataFlowFromMethodToHash conf where conf.hasFlow(src.getNode(), sink.getNode()) select src.getNode(), src, sink, - "The hash is calculated on the process name $@, may be related to a backdoor. Please review the code for possible malicious intent.", - sink.getNode(), "here" + "The hash is calculated on $@, may be related to a backdoor. Please review the code for possible malicious intent.", + sink.getNode(), "this process name" diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml index e2721c02552..682028cf7cc 100644 --- a/csharp/ql/src/qlpack.yml +++ b/csharp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-queries -version: 0.4.1-dev +version: 0.4.2-dev groups: - csharp - queries diff --git a/csharp/ql/test/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.expected b/csharp/ql/test/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.expected index dc224c9586e..a76e9660cec 100644 --- a/csharp/ql/test/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.expected +++ b/csharp/ql/test/experimental/Security Features/JsonWebTokenHandler/delegated-security-validations-always-return-true.expected @@ -1,7 +1,7 @@ -| delegation-test.cs:101:63:101:186 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to $@. | stubs.cs:54:34:54:50 | LifetimeValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.LifetimeValidator | delegation-test.cs:101:63:101:186 | (...) => ... | a callable that always returns "true" | -| delegation-test.cs:102:63:102:178 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to $@. | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | delegation-test.cs:102:63:102:178 | (...) => ... | a callable that always returns "true" | -| delegation-test.cs:115:63:115:190 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to $@. | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | delegation-test.cs:115:63:115:190 | (...) => ... | a callable that always returns "true" | -| delegation-test.cs:116:63:116:180 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to $@. | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | delegation-test.cs:116:63:116:180 | (...) => ... | a callable that always returns "true" | -| delegation-test.cs:117:63:117:217 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to $@. | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | delegation-test.cs:117:63:117:217 | (...) => ... | a callable that always returns "true" | -| delegation-test.cs:118:63:118:248 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to $@. | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | delegation-test.cs:118:63:118:248 | (...) => ... | a callable that always returns "true" | -| delegation-test.cs:119:63:119:177 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to $@. | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | delegation-test.cs:119:63:119:177 | (...) => ... | a callable that always returns "true" | +| delegation-test.cs:101:63:101:186 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns "true". | stubs.cs:54:34:54:50 | LifetimeValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.LifetimeValidator | +| delegation-test.cs:102:63:102:178 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns "true". | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | +| delegation-test.cs:115:63:115:190 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns "true". | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | +| delegation-test.cs:116:63:116:180 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns "true". | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | +| delegation-test.cs:117:63:117:217 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns "true". | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | +| delegation-test.cs:118:63:118:248 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns "true". | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | +| delegation-test.cs:119:63:119:177 | (...) => ... | JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns "true". | stubs.cs:55:34:55:50 | AudienceValidator | Microsoft.IdentityModel.Tokens.TokenValidationParameters.AudienceValidator | diff --git a/go/ql/lib/CHANGELOG.md b/go/ql/lib/CHANGELOG.md index 1f851cdf663..c38ebde0723 100644 --- a/go/ql/lib/CHANGELOG.md +++ b/go/ql/lib/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.3.1 + +### Minor Analysis Improvements + +* Added support for `BeegoInput.RequestBody` as a source of untrusted data. + ## 0.3.0 ### Deprecated APIs diff --git a/go/ql/lib/change-notes/2022-10-06-beego-request-body-source.md b/go/ql/lib/change-notes/released/0.3.1.md similarity index 63% rename from go/ql/lib/change-notes/2022-10-06-beego-request-body-source.md rename to go/ql/lib/change-notes/released/0.3.1.md index 9980b0aadd2..be16eed5d3e 100644 --- a/go/ql/lib/change-notes/2022-10-06-beego-request-body-source.md +++ b/go/ql/lib/change-notes/released/0.3.1.md @@ -1,4 +1,5 @@ ---- -category: minorAnalysis ---- +## 0.3.1 + +### Minor Analysis Improvements + * Added support for `BeegoInput.RequestBody` as a source of untrusted data. diff --git a/go/ql/lib/codeql-pack.release.yml b/go/ql/lib/codeql-pack.release.yml index 95f6e3a0ba6..bb106b1cb63 100644 --- a/go/ql/lib/codeql-pack.release.yml +++ b/go/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.0 +lastReleaseVersion: 0.3.1 diff --git a/go/ql/lib/qlpack.yml b/go/ql/lib/qlpack.yml index 8025056129c..3b38291ebb5 100644 --- a/go/ql/lib/qlpack.yml +++ b/go/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-all -version: 0.3.1-dev +version: 0.3.2-dev groups: go dbscheme: go.dbscheme extractor: go diff --git a/go/ql/lib/semmle/go/security/InsecureRandomnessCustomizations.qll b/go/ql/lib/semmle/go/security/InsecureRandomnessCustomizations.qll index 2cbb350461b..3bc6b5f5eec 100644 --- a/go/ql/lib/semmle/go/security/InsecureRandomnessCustomizations.qll +++ b/go/ql/lib/semmle/go/security/InsecureRandomnessCustomizations.qll @@ -64,7 +64,7 @@ module InsecureRandomness { ) } - override string getKind() { result = "this cryptographic algorithm" } + override string getKind() { result = "This cryptographic algorithm" } } /** @@ -75,7 +75,7 @@ module InsecureRandomness { this.getRoot().(FuncDef).getName().regexpMatch("(?i).*(gen(erate)?|salt|make|mk)Password.*") } - override string getKind() { result = "a password-related function" } + override string getKind() { result = "A password-related function" } } /** Gets a package that implements hash algorithms. */ diff --git a/go/ql/src/CHANGELOG.md b/go/ql/src/CHANGELOG.md index 47dabdb2d2e..68880b18281 100644 --- a/go/ql/src/CHANGELOG.md +++ b/go/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.1 + +No user-facing changes. + ## 0.3.0 ### Query Metadata Changes diff --git a/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql b/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql index c846ef16303..93889b0a23e 100644 --- a/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql +++ b/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql @@ -61,4 +61,4 @@ where // } n = DataFlow::BarrierGuard::getABarrierNode() ) -select n, "The first argument to 'errors.Wrap' is always nil" +select n, "The first argument to 'errors.Wrap' is always nil." diff --git a/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql b/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql index 71ae1ac183a..5c1b4528302 100644 --- a/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql +++ b/go/ql/src/Security/CWE-020/SuspiciousCharacterInRegexp.ql @@ -48,5 +48,5 @@ class Config extends DataFlow::Configuration { from Config c, DataFlow::PathNode source, DataFlow::PathNode sink, string report where c.hasFlowPath(source, sink) and c.isSource(source.getNode(), report) -select source, source, sink, "$@ that is $@ contains " + report, source, "A string literal", sink, +select source, source, sink, "This string literal that is $@ contains " + report, sink, "used as a regular expression" diff --git a/go/ql/src/Security/CWE-117/LogInjection.ql b/go/ql/src/Security/CWE-117/LogInjection.ql index 070788af884..dbf0c767bb3 100644 --- a/go/ql/src/Security/CWE-117/LogInjection.ql +++ b/go/ql/src/Security/CWE-117/LogInjection.ql @@ -17,5 +17,5 @@ import DataFlow::PathGraph from LogInjection::Configuration c, DataFlow::PathNode source, DataFlow::PathNode sink where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "Log entry depends on a $@.", source.getNode(), +select sink.getNode(), source, sink, "This log entry depends on a $@.", source.getNode(), "user-provided value" diff --git a/go/ql/src/Security/CWE-338/InsecureRandomness.ql b/go/ql/src/Security/CWE-338/InsecureRandomness.ql index 37ec1c21655..e87bbbae37b 100644 --- a/go/ql/src/Security/CWE-338/InsecureRandomness.ql +++ b/go/ql/src/Security/CWE-338/InsecureRandomness.ql @@ -19,7 +19,7 @@ where cfg.hasFlowPath(source, sink) and cfg.isSink(sink.getNode(), kind) and ( - kind != "a password-related function" + kind != "A password-related function" or sink = min(DataFlow::PathNode sink2, int line | @@ -31,5 +31,5 @@ where ) ) select sink.getNode(), source, sink, - "$@ generated with a cryptographically weak RNG is used in $@.", source.getNode(), - "A random number", sink.getNode(), kind + kind + " depends on a $@ generated with a cryptographically weak RNG.", source.getNode(), + "random number" diff --git a/cpp/ql/src/change-notes/2022-09-23-alert-messages.md b/go/ql/src/change-notes/2022-10-07-alert-messages.md similarity index 100% rename from cpp/ql/src/change-notes/2022-09-23-alert-messages.md rename to go/ql/src/change-notes/2022-10-07-alert-messages.md diff --git a/go/ql/src/change-notes/released/0.3.1.md b/go/ql/src/change-notes/released/0.3.1.md new file mode 100644 index 00000000000..9fd4efd6c80 --- /dev/null +++ b/go/ql/src/change-notes/released/0.3.1.md @@ -0,0 +1,3 @@ +## 0.3.1 + +No user-facing changes. diff --git a/go/ql/src/codeql-pack.release.yml b/go/ql/src/codeql-pack.release.yml index 95f6e3a0ba6..bb106b1cb63 100644 --- a/go/ql/src/codeql-pack.release.yml +++ b/go/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.0 +lastReleaseVersion: 0.3.1 diff --git a/go/ql/src/experimental/CWE-369/DivideByZero.ql b/go/ql/src/experimental/CWE-369/DivideByZero.ql index 8aa12f7f66e..b2e61bef37d 100644 --- a/go/ql/src/experimental/CWE-369/DivideByZero.ql +++ b/go/ql/src/experimental/CWE-369/DivideByZero.ql @@ -54,5 +54,4 @@ class DivideByZeroCheckConfig extends TaintTracking::Configuration { from DataFlow::PathNode source, DataFlow::PathNode sink, DivideByZeroCheckConfig cfg where cfg.hasFlowPath(source, sink) -select sink, source, sink, "Variable $@ might be zero leading to a division-by-zero panic.", sink, - sink.getNode().toString() +select sink, source, sink, "This variable might be zero leading to a division-by-zero panic." diff --git a/go/ql/src/experimental/CWE-400/DatabaseCallInLoop.ql b/go/ql/src/experimental/CWE-400/DatabaseCallInLoop.ql index 253d598835d..66fb90664ea 100644 --- a/go/ql/src/experimental/CWE-400/DatabaseCallInLoop.ql +++ b/go/ql/src/experimental/CWE-400/DatabaseCallInLoop.ql @@ -66,4 +66,4 @@ query predicate edges(CallGraphNode pred, CallGraphNode succ) { from LoopStmt loop, DatabaseAccess dbAccess where edges*(loop, dbAccess.asExpr()) -select dbAccess, loop, dbAccess, "$@ is called in $@", dbAccess, dbAccess.toString(), loop, "a loop" +select dbAccess, loop, dbAccess, "This calls " + dbAccess.toString() + " in a $@.", loop, "loop" diff --git a/go/ql/src/experimental/CWE-918/SSRF.ql b/go/ql/src/experimental/CWE-918/SSRF.ql index 41c41bb18de..4c14969c35f 100644 --- a/go/ql/src/experimental/CWE-918/SSRF.ql +++ b/go/ql/src/experimental/CWE-918/SSRF.ql @@ -19,4 +19,4 @@ from where cfg.hasFlowPath(source, sink) and request = sink.getNode().(ServerSideRequestForgery::Sink).getARequest() -select request, source, sink, "The URL of this request depends on a user-provided value" +select request, source, sink, "The URL of this request depends on a user-provided value." diff --git a/go/ql/src/experimental/IntegerOverflow/IntegerOverflow.ql b/go/ql/src/experimental/IntegerOverflow/IntegerOverflow.ql index 3a3c6b1d745..ca17228816c 100644 --- a/go/ql/src/experimental/IntegerOverflow/IntegerOverflow.ql +++ b/go/ql/src/experimental/IntegerOverflow/IntegerOverflow.ql @@ -11,4 +11,4 @@ import RangeAnalysis from Expr expr where exprMayOverflow(expr) or exprMayUnderflow(expr) -select expr, "this expression may cause an integer overflow" +select expr, "This expression may cause an integer overflow." diff --git a/go/ql/src/qlpack.yml b/go/ql/src/qlpack.yml index f454b5ce9d9..574b63f69c1 100644 --- a/go/ql/src/qlpack.yml +++ b/go/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-queries -version: 0.3.1-dev +version: 0.3.2-dev groups: - go - queries diff --git a/go/ql/test/experimental/CWE-369/DivideByZero.expected b/go/ql/test/experimental/CWE-369/DivideByZero.expected index 35a3e399cb7..e80e3295c22 100644 --- a/go/ql/test/experimental/CWE-369/DivideByZero.expected +++ b/go/ql/test/experimental/CWE-369/DivideByZero.expected @@ -24,9 +24,9 @@ nodes | DivideByZero.go:57:17:57:21 | value | semmle.label | value | subpaths #select -| DivideByZero.go:12:16:12:20 | value | DivideByZero.go:10:12:10:16 | selection of URL : pointer type | DivideByZero.go:12:16:12:20 | value | Variable $@ might be zero leading to a division-by-zero panic. | DivideByZero.go:12:16:12:20 | value | value | -| DivideByZero.go:19:16:19:20 | value | DivideByZero.go:17:12:17:16 | selection of URL : pointer type | DivideByZero.go:19:16:19:20 | value | Variable $@ might be zero leading to a division-by-zero panic. | DivideByZero.go:19:16:19:20 | value | value | -| DivideByZero.go:26:16:26:20 | value | DivideByZero.go:24:12:24:16 | selection of URL : pointer type | DivideByZero.go:26:16:26:20 | value | Variable $@ might be zero leading to a division-by-zero panic. | DivideByZero.go:26:16:26:20 | value | value | -| DivideByZero.go:33:16:33:20 | value | DivideByZero.go:31:12:31:16 | selection of URL : pointer type | DivideByZero.go:33:16:33:20 | value | Variable $@ might be zero leading to a division-by-zero panic. | DivideByZero.go:33:16:33:20 | value | value | -| DivideByZero.go:40:16:40:20 | value | DivideByZero.go:38:12:38:16 | selection of URL : pointer type | DivideByZero.go:40:16:40:20 | value | Variable $@ might be zero leading to a division-by-zero panic. | DivideByZero.go:40:16:40:20 | value | value | -| DivideByZero.go:57:17:57:21 | value | DivideByZero.go:54:12:54:16 | selection of URL : pointer type | DivideByZero.go:57:17:57:21 | value | Variable $@ might be zero leading to a division-by-zero panic. | DivideByZero.go:57:17:57:21 | value | value | +| DivideByZero.go:12:16:12:20 | value | DivideByZero.go:10:12:10:16 | selection of URL : pointer type | DivideByZero.go:12:16:12:20 | value | This variable might be zero leading to a division-by-zero panic. | +| DivideByZero.go:19:16:19:20 | value | DivideByZero.go:17:12:17:16 | selection of URL : pointer type | DivideByZero.go:19:16:19:20 | value | This variable might be zero leading to a division-by-zero panic. | +| DivideByZero.go:26:16:26:20 | value | DivideByZero.go:24:12:24:16 | selection of URL : pointer type | DivideByZero.go:26:16:26:20 | value | This variable might be zero leading to a division-by-zero panic. | +| DivideByZero.go:33:16:33:20 | value | DivideByZero.go:31:12:31:16 | selection of URL : pointer type | DivideByZero.go:33:16:33:20 | value | This variable might be zero leading to a division-by-zero panic. | +| DivideByZero.go:40:16:40:20 | value | DivideByZero.go:38:12:38:16 | selection of URL : pointer type | DivideByZero.go:40:16:40:20 | value | This variable might be zero leading to a division-by-zero panic. | +| DivideByZero.go:57:17:57:21 | value | DivideByZero.go:54:12:54:16 | selection of URL : pointer type | DivideByZero.go:57:17:57:21 | value | This variable might be zero leading to a division-by-zero panic. | diff --git a/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.expected b/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.expected index bb197203f22..074dfaa134f 100644 --- a/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.expected +++ b/go/ql/test/experimental/CWE-400/DatabaseCallInLoop.expected @@ -8,6 +8,6 @@ edges | test.go:24:2:26:2 | for statement | test.go:25:3:25:17 | call to runRunQuery | | test.go:25:3:25:17 | call to runRunQuery | test.go:14:1:16:1 | function declaration | #select -| DatabaseCallInLoop.go:9:3:9:41 | call to First | DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First | $@ is called in $@ | DatabaseCallInLoop.go:9:3:9:41 | call to First | call to First | DatabaseCallInLoop.go:7:2:11:2 | range statement | a loop | -| test.go:11:2:11:13 | call to Take | test.go:20:2:22:2 | for statement | test.go:11:2:11:13 | call to Take | $@ is called in $@ | test.go:11:2:11:13 | call to Take | call to Take | test.go:20:2:22:2 | for statement | a loop | -| test.go:11:2:11:13 | call to Take | test.go:24:2:26:2 | for statement | test.go:11:2:11:13 | call to Take | $@ is called in $@ | test.go:11:2:11:13 | call to Take | call to Take | test.go:24:2:26:2 | for statement | a loop | +| DatabaseCallInLoop.go:9:3:9:41 | call to First | DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First | This calls call to First in a $@. | DatabaseCallInLoop.go:7:2:11:2 | range statement | loop | +| test.go:11:2:11:13 | call to Take | test.go:20:2:22:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:20:2:22:2 | for statement | loop | +| test.go:11:2:11:13 | call to Take | test.go:24:2:26:2 | for statement | test.go:11:2:11:13 | call to Take | This calls call to Take in a $@. | test.go:24:2:26:2 | for statement | loop | diff --git a/go/ql/test/experimental/CWE-918/SSRF.expected b/go/ql/test/experimental/CWE-918/SSRF.expected index a0b9993a4ca..5fdd1775d3d 100644 --- a/go/ql/test/experimental/CWE-918/SSRF.expected +++ b/go/ql/test/experimental/CWE-918/SSRF.expected @@ -55,20 +55,20 @@ nodes | new-tests.go:96:11:96:46 | ...+... | semmle.label | ...+... | subpaths #select -| builtin.go:22:12:22:63 | call to Get | builtin.go:19:12:19:34 | call to FormValue : string | builtin.go:22:21:22:62 | ...+... | The URL of this request depends on a user-provided value | -| builtin.go:88:12:88:53 | call to Dial | builtin.go:83:21:83:31 | call to Referer : string | builtin.go:88:27:88:40 | untrustedInput | The URL of this request depends on a user-provided value | -| builtin.go:102:13:102:40 | call to DialConfig | builtin.go:97:21:97:31 | call to Referer : string | builtin.go:101:36:101:49 | untrustedInput | The URL of this request depends on a user-provided value | -| builtin.go:114:3:114:39 | call to Dial | builtin.go:111:21:111:31 | call to Referer : string | builtin.go:114:15:114:28 | untrustedInput | The URL of this request depends on a user-provided value | -| builtin.go:132:3:132:62 | call to DialContext | builtin.go:129:21:129:31 | call to Referer : string | builtin.go:132:38:132:51 | untrustedInput | The URL of this request depends on a user-provided value | -| new-tests.go:31:2:31:58 | call to Get | new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:31:11:31:57 | call to Sprintf | The URL of this request depends on a user-provided value | -| new-tests.go:32:2:32:58 | call to Get | new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:32:11:32:57 | call to Sprintf | The URL of this request depends on a user-provided value | -| new-tests.go:35:3:35:59 | call to Get | new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:35:12:35:58 | call to Sprintf | The URL of this request depends on a user-provided value | -| new-tests.go:47:2:47:47 | call to Get | new-tests.go:39:18:39:30 | call to Param : string | new-tests.go:47:11:47:46 | ...+... | The URL of this request depends on a user-provided value | -| new-tests.go:50:2:50:47 | call to Get | new-tests.go:49:18:49:30 | call to Query : string | new-tests.go:50:11:50:46 | ...+... | The URL of this request depends on a user-provided value | -| new-tests.go:68:2:68:58 | call to Get | new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:68:11:68:57 | call to Sprintf | The URL of this request depends on a user-provided value | -| new-tests.go:69:2:69:58 | call to Get | new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:69:11:69:57 | call to Sprintf | The URL of this request depends on a user-provided value | -| new-tests.go:74:3:74:59 | call to Get | new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:74:12:74:58 | call to Sprintf | The URL of this request depends on a user-provided value | -| new-tests.go:79:2:79:47 | call to Get | new-tests.go:78:18:78:24 | selection of URL : pointer type | new-tests.go:79:11:79:46 | ...+... | The URL of this request depends on a user-provided value | -| new-tests.go:82:2:82:47 | call to Get | new-tests.go:81:37:81:43 | selection of URL : pointer type | new-tests.go:82:11:82:46 | ...+... | The URL of this request depends on a user-provided value | -| new-tests.go:88:2:88:47 | call to Get | new-tests.go:86:10:86:20 | call to Vars : map type | new-tests.go:88:11:88:46 | ...+... | The URL of this request depends on a user-provided value | -| new-tests.go:96:2:96:47 | call to Get | new-tests.go:95:18:95:45 | call to URLParam : string | new-tests.go:96:11:96:46 | ...+... | The URL of this request depends on a user-provided value | +| builtin.go:22:12:22:63 | call to Get | builtin.go:19:12:19:34 | call to FormValue : string | builtin.go:22:21:22:62 | ...+... | The URL of this request depends on a user-provided value. | +| builtin.go:88:12:88:53 | call to Dial | builtin.go:83:21:83:31 | call to Referer : string | builtin.go:88:27:88:40 | untrustedInput | The URL of this request depends on a user-provided value. | +| builtin.go:102:13:102:40 | call to DialConfig | builtin.go:97:21:97:31 | call to Referer : string | builtin.go:101:36:101:49 | untrustedInput | The URL of this request depends on a user-provided value. | +| builtin.go:114:3:114:39 | call to Dial | builtin.go:111:21:111:31 | call to Referer : string | builtin.go:114:15:114:28 | untrustedInput | The URL of this request depends on a user-provided value. | +| builtin.go:132:3:132:62 | call to DialContext | builtin.go:129:21:129:31 | call to Referer : string | builtin.go:132:38:132:51 | untrustedInput | The URL of this request depends on a user-provided value. | +| new-tests.go:31:2:31:58 | call to Get | new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:31:11:31:57 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:32:2:32:58 | call to Get | new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:32:11:32:57 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:35:3:35:59 | call to Get | new-tests.go:26:26:26:30 | &... : pointer type | new-tests.go:35:12:35:58 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:47:2:47:47 | call to Get | new-tests.go:39:18:39:30 | call to Param : string | new-tests.go:47:11:47:46 | ...+... | The URL of this request depends on a user-provided value. | +| new-tests.go:50:2:50:47 | call to Get | new-tests.go:49:18:49:30 | call to Query : string | new-tests.go:50:11:50:46 | ...+... | The URL of this request depends on a user-provided value. | +| new-tests.go:68:2:68:58 | call to Get | new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:68:11:68:57 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:69:2:69:58 | call to Get | new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:69:11:69:57 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:74:3:74:59 | call to Get | new-tests.go:62:31:62:38 | selection of Body : ReadCloser | new-tests.go:74:12:74:58 | call to Sprintf | The URL of this request depends on a user-provided value. | +| new-tests.go:79:2:79:47 | call to Get | new-tests.go:78:18:78:24 | selection of URL : pointer type | new-tests.go:79:11:79:46 | ...+... | The URL of this request depends on a user-provided value. | +| new-tests.go:82:2:82:47 | call to Get | new-tests.go:81:37:81:43 | selection of URL : pointer type | new-tests.go:82:11:82:46 | ...+... | The URL of this request depends on a user-provided value. | +| new-tests.go:88:2:88:47 | call to Get | new-tests.go:86:10:86:20 | call to Vars : map type | new-tests.go:88:11:88:46 | ...+... | The URL of this request depends on a user-provided value. | +| new-tests.go:96:2:96:47 | call to Get | new-tests.go:95:18:95:45 | call to URLParam : string | new-tests.go:96:11:96:46 | ...+... | The URL of this request depends on a user-provided value. | diff --git a/go/ql/test/query-tests/InconsistentCode/WrappedErrorAlwaysNil/WrappedErrorAlwaysNil.expected b/go/ql/test/query-tests/InconsistentCode/WrappedErrorAlwaysNil/WrappedErrorAlwaysNil.expected index 4ac2411d7ca..43853d29664 100644 --- a/go/ql/test/query-tests/InconsistentCode/WrappedErrorAlwaysNil/WrappedErrorAlwaysNil.expected +++ b/go/ql/test/query-tests/InconsistentCode/WrappedErrorAlwaysNil/WrappedErrorAlwaysNil.expected @@ -1,4 +1,4 @@ -| WrappedErrorAlwaysNil.go:31:22:31:24 | err | The first argument to 'errors.Wrap' is always nil | -| WrappedErrorAlwaysNil.go:41:14:41:16 | nil | The first argument to 'errors.Wrap' is always nil | -| WrappedErrorAlwaysNil.go:45:14:45:16 | err | The first argument to 'errors.Wrap' is always nil | -| WrappedErrorAlwaysNil.go:49:14:49:21 | localErr | The first argument to 'errors.Wrap' is always nil | +| WrappedErrorAlwaysNil.go:31:22:31:24 | err | The first argument to 'errors.Wrap' is always nil. | +| WrappedErrorAlwaysNil.go:41:14:41:16 | nil | The first argument to 'errors.Wrap' is always nil. | +| WrappedErrorAlwaysNil.go:45:14:45:16 | err | The first argument to 'errors.Wrap' is always nil. | +| WrappedErrorAlwaysNil.go:49:14:49:21 | localErr | The first argument to 'errors.Wrap' is always nil. | diff --git a/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.expected b/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.expected index 130894d0639..cea5780a6c5 100644 --- a/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.expected +++ b/go/ql/test/query-tests/Security/CWE-020/SuspiciousCharacterInRegexp/SuspiciousCharacterInRegexp.expected @@ -13,14 +13,14 @@ nodes | test.go:23:21:23:36 | "hello\\\\\\bworld" | semmle.label | "hello\\\\\\bworld" | subpaths #select -| SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | $@ that is $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | A string literal | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | used as a regular expression | -| test.go:7:21:7:24 | "\\a" | test.go:7:21:7:24 | "\\a" | test.go:7:21:7:24 | "\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:7:21:7:24 | "\\a" | A string literal | test.go:7:21:7:24 | "\\a" | used as a regular expression | -| test.go:9:21:9:26 | "\\\\\\a" | test.go:9:21:9:26 | "\\\\\\a" | test.go:9:21:9:26 | "\\\\\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:9:21:9:26 | "\\\\\\a" | A string literal | test.go:9:21:9:26 | "\\\\\\a" | used as a regular expression | -| test.go:10:21:10:27 | "x\\\\\\a" | test.go:10:21:10:27 | "x\\\\\\a" | test.go:10:21:10:27 | "x\\\\\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:10:21:10:27 | "x\\\\\\a" | A string literal | test.go:10:21:10:27 | "x\\\\\\a" | used as a regular expression | -| test.go:12:21:12:28 | "\\\\\\\\\\a" | test.go:12:21:12:28 | "\\\\\\\\\\a" | test.go:12:21:12:28 | "\\\\\\\\\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:12:21:12:28 | "\\\\\\\\\\a" | A string literal | test.go:12:21:12:28 | "\\\\\\\\\\a" | used as a regular expression | -| test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | A string literal | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | used as a regular expression | -| test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | A string literal | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | used as a regular expression | -| test.go:20:21:20:34 | "hello\\aworld" | test.go:20:21:20:34 | "hello\\aworld" | test.go:20:21:20:34 | "hello\\aworld" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:20:21:20:34 | "hello\\aworld" | A string literal | test.go:20:21:20:34 | "hello\\aworld" | used as a regular expression | -| test.go:21:21:21:36 | "hello\\\\\\aworld" | test.go:21:21:21:36 | "hello\\\\\\aworld" | test.go:21:21:21:36 | "hello\\\\\\aworld" | $@ that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:21:21:21:36 | "hello\\\\\\aworld" | A string literal | test.go:21:21:21:36 | "hello\\\\\\aworld" | used as a regular expression | -| test.go:22:21:22:34 | "hello\\bworld" | test.go:22:21:22:34 | "hello\\bworld" | test.go:22:21:22:34 | "hello\\bworld" | $@ that is $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | test.go:22:21:22:34 | "hello\\bworld" | A string literal | test.go:22:21:22:34 | "hello\\bworld" | used as a regular expression | -| test.go:23:21:23:36 | "hello\\\\\\bworld" | test.go:23:21:23:36 | "hello\\\\\\bworld" | test.go:23:21:23:36 | "hello\\\\\\bworld" | $@ that is $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | test.go:23:21:23:36 | "hello\\\\\\bworld" | A string literal | test.go:23:21:23:36 | "hello\\\\\\bworld" | used as a regular expression | +| SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | This string literal that is $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | SuspiciousCharacterInRegexp.go:6:34:6:55 | "\\bforbidden.host.org" | used as a regular expression | +| test.go:7:21:7:24 | "\\a" | test.go:7:21:7:24 | "\\a" | test.go:7:21:7:24 | "\\a" | This string literal that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:7:21:7:24 | "\\a" | used as a regular expression | +| test.go:9:21:9:26 | "\\\\\\a" | test.go:9:21:9:26 | "\\\\\\a" | test.go:9:21:9:26 | "\\\\\\a" | This string literal that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:9:21:9:26 | "\\\\\\a" | used as a regular expression | +| test.go:10:21:10:27 | "x\\\\\\a" | test.go:10:21:10:27 | "x\\\\\\a" | test.go:10:21:10:27 | "x\\\\\\a" | This string literal that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:10:21:10:27 | "x\\\\\\a" | used as a regular expression | +| test.go:12:21:12:28 | "\\\\\\\\\\a" | test.go:12:21:12:28 | "\\\\\\\\\\a" | test.go:12:21:12:28 | "\\\\\\\\\\a" | This string literal that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:12:21:12:28 | "\\\\\\\\\\a" | used as a regular expression | +| test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | This string literal that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:14:21:14:30 | "\\\\\\\\\\\\\\a" | used as a regular expression | +| test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | This string literal that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:16:21:16:32 | "\\\\\\\\\\\\\\\\\\a" | used as a regular expression | +| test.go:20:21:20:34 | "hello\\aworld" | test.go:20:21:20:34 | "hello\\aworld" | test.go:20:21:20:34 | "hello\\aworld" | This string literal that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:20:21:20:34 | "hello\\aworld" | used as a regular expression | +| test.go:21:21:21:36 | "hello\\\\\\aworld" | test.go:21:21:21:36 | "hello\\\\\\aworld" | test.go:21:21:21:36 | "hello\\\\\\aworld" | This string literal that is $@ contains the bell character \\a; did you mean \\\\a, the Vim alphabetic character class (use [[:alpha:]] instead) or \\\\A, the beginning of text? | test.go:21:21:21:36 | "hello\\\\\\aworld" | used as a regular expression | +| test.go:22:21:22:34 | "hello\\bworld" | test.go:22:21:22:34 | "hello\\bworld" | test.go:22:21:22:34 | "hello\\bworld" | This string literal that is $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | test.go:22:21:22:34 | "hello\\bworld" | used as a regular expression | +| test.go:23:21:23:36 | "hello\\\\\\bworld" | test.go:23:21:23:36 | "hello\\\\\\bworld" | test.go:23:21:23:36 | "hello\\\\\\bworld" | This string literal that is $@ contains a literal backspace \\b; did you mean \\\\b, a word boundary? | test.go:23:21:23:36 | "hello\\\\\\bworld" | used as a regular expression | diff --git a/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.expected b/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.expected index be68561ca27..2ba310c6ee1 100644 --- a/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.expected +++ b/go/ql/test/query-tests/Security/CWE-338/InsecureRandomness/InsecureRandomness.expected @@ -20,8 +20,8 @@ nodes | sample.go:47:17:47:39 | call to Intn | semmle.label | call to Intn | subpaths #select -| InsecureRandomness.go:12:18:12:40 | call to Intn | InsecureRandomness.go:12:18:12:40 | call to Intn | InsecureRandomness.go:12:18:12:40 | call to Intn | $@ generated with a cryptographically weak RNG is used in $@. | InsecureRandomness.go:12:18:12:40 | call to Intn | A random number | InsecureRandomness.go:12:18:12:40 | call to Intn | a password-related function | -| sample.go:26:25:26:30 | call to Guid | sample.go:15:49:15:61 | call to Uint32 : uint32 | sample.go:26:25:26:30 | call to Guid | $@ generated with a cryptographically weak RNG is used in $@. | sample.go:15:49:15:61 | call to Uint32 | A random number | sample.go:26:25:26:30 | call to Guid | this cryptographic algorithm | -| sample.go:37:25:37:29 | nonce | sample.go:34:12:34:40 | call to New : pointer type | sample.go:37:25:37:29 | nonce | $@ generated with a cryptographically weak RNG is used in $@. | sample.go:34:12:34:40 | call to New | A random number | sample.go:37:25:37:29 | nonce | this cryptographic algorithm | -| sample.go:37:32:37:36 | nonce | sample.go:34:12:34:40 | call to New : pointer type | sample.go:37:32:37:36 | nonce | $@ generated with a cryptographically weak RNG is used in $@. | sample.go:34:12:34:40 | call to New | A random number | sample.go:37:32:37:36 | nonce | this cryptographic algorithm | -| sample.go:43:17:43:39 | call to Intn | sample.go:43:17:43:39 | call to Intn | sample.go:43:17:43:39 | call to Intn | $@ generated with a cryptographically weak RNG is used in $@. | sample.go:43:17:43:39 | call to Intn | A random number | sample.go:43:17:43:39 | call to Intn | a password-related function | +| InsecureRandomness.go:12:18:12:40 | call to Intn | InsecureRandomness.go:12:18:12:40 | call to Intn | InsecureRandomness.go:12:18:12:40 | call to Intn | A password-related function depends on a $@ generated with a cryptographically weak RNG. | InsecureRandomness.go:12:18:12:40 | call to Intn | random number | +| sample.go:26:25:26:30 | call to Guid | sample.go:15:49:15:61 | call to Uint32 : uint32 | sample.go:26:25:26:30 | call to Guid | This cryptographic algorithm depends on a $@ generated with a cryptographically weak RNG. | sample.go:15:49:15:61 | call to Uint32 | random number | +| sample.go:37:25:37:29 | nonce | sample.go:34:12:34:40 | call to New : pointer type | sample.go:37:25:37:29 | nonce | This cryptographic algorithm depends on a $@ generated with a cryptographically weak RNG. | sample.go:34:12:34:40 | call to New | random number | +| sample.go:37:32:37:36 | nonce | sample.go:34:12:34:40 | call to New : pointer type | sample.go:37:32:37:36 | nonce | This cryptographic algorithm depends on a $@ generated with a cryptographically weak RNG. | sample.go:34:12:34:40 | call to New | random number | +| sample.go:43:17:43:39 | call to Intn | sample.go:43:17:43:39 | call to Intn | sample.go:43:17:43:39 | call to Intn | A password-related function depends on a $@ generated with a cryptographically weak RNG. | sample.go:43:17:43:39 | call to Intn | random number | diff --git a/java/kotlin-extractor/build.py b/java/kotlin-extractor/build.py index a4da1a2ea23..9525522869b 100755 --- a/java/kotlin-extractor/build.py +++ b/java/kotlin-extractor/build.py @@ -25,6 +25,8 @@ def parse_args(): dest='many', help='Build for a single version/kind') parser.add_argument('--single-version', help='Build for a specific version/kind') + parser.add_argument('--single-version-embeddable', action='store_true', + help='When building a single version, build an embeddable extractor (default is standalone)') return parser.parse_args() @@ -235,7 +237,13 @@ def compile_standalone(version): if args.single_version: - compile_standalone(args.single_version) + if args.single_version_embeddable == True: + compile_embeddable(args.single_version) + else: + compile_standalone(args.single_version) +elif args.single_version_embeddable == True: + print("--single-version-embeddable requires --single-version", file=sys.stderr) + sys.exit(1) elif args.many: for version in kotlin_plugin_versions.many_versions: compile_standalone(version) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index b7aff59b599..1c34f1d8471 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* @@ -154,7 +155,7 @@ open class KotlinFileExtractor( is IrEnumEntry -> { val parentId = useDeclarationParent(declaration.parent, false)?.cast() if (parentId != null) { - extractEnumEntry(declaration, parentId, extractFunctionBodies) + extractEnumEntry(declaration, parentId, extractPrivateMembers, extractFunctionBodies) } Unit } @@ -253,9 +254,23 @@ open class KotlinFileExtractor( } } + fun extractClassInstance(classLabel: Label, c: IrClass, argsIncludingOuterClasses: List?, shouldExtractOutline: Boolean, shouldExtractDetails: Boolean) { + DeclarationStackAdjuster(c).use { + if (shouldExtractOutline) { + extractClassWithoutMembers(c, argsIncludingOuterClasses) + } + + if (shouldExtractDetails) { + val supertypeMode = if (argsIncludingOuterClasses == null) ExtractSupertypesMode.Raw else ExtractSupertypesMode.Specialised(argsIncludingOuterClasses) + extractClassSupertypes(c, classLabel, supertypeMode, true) + extractNonPrivateMemberPrototypes(c, argsIncludingOuterClasses, classLabel) + } + } + } + // `argsIncludingOuterClasses` can be null to describe a raw generic type. // For non-generic types it will be zero-length list. - fun extractClassInstance(c: IrClass, argsIncludingOuterClasses: List?): Label { + private fun extractClassWithoutMembers(c: IrClass, argsIncludingOuterClasses: List?): Label { with("class instance", c) { if (argsIncludingOuterClasses?.isEmpty() == true) { logger.error("Instance without type arguments: " + c.name.asString()) @@ -341,7 +356,7 @@ open class KotlinFileExtractor( // `argsIncludingOuterClasses` can be null to describe a raw generic type. // For non-generic types it will be zero-length list. - fun extractNonPrivateMemberPrototypes(c: IrClass, argsIncludingOuterClasses: List?, id: Label) { + private fun extractNonPrivateMemberPrototypes(c: IrClass, argsIncludingOuterClasses: List?, id: Label) { with("member prototypes", c) { val typeParamSubstitution = when (argsIncludingOuterClasses) { @@ -388,9 +403,7 @@ open class KotlinFileExtractor( addModifiers(obinitId, "private") // add body: - val blockId = tw.getFreshIdLabel() - tw.writeStmts_block(blockId, obinitId, 0, obinitId) - tw.writeHasLocation(blockId, locId) + val blockId = extractBlockBody(obinitId, locId) extractDeclInitializers(c.declarations, false) { Pair(blockId, obinitId) } } @@ -688,7 +701,7 @@ open class KotlinFileExtractor( "", listOf(), pluginContext.irBuiltIns.unitType, - extensionReceiverParameter = null, + extensionParamType = null, functionTypeParameters = listOf(), classTypeArgsIncludingOuterClasses = listOf(), overridesCollectionsMethod = false, @@ -706,10 +719,7 @@ open class KotlinFileExtractor( tw.writeHasLocation(clinitId, locId) // add and return body block: - Pair(tw.getFreshIdLabel().also({ - tw.writeStmts_block(it, clinitId, 0, clinitId) - tw.writeHasLocation(it, locId) - }), clinitId) + Pair(extractBlockBody(clinitId, locId), clinitId) } } } @@ -774,32 +784,18 @@ open class KotlinFileExtractor( val expr = initializer.expression val declLocId = tw.getLocation(f) - val stmtId = tw.getFreshIdLabel() - tw.writeStmts_exprstmt(stmtId, blockAndFunctionId.first, idx++, blockAndFunctionId.second) - tw.writeHasLocation(stmtId, declLocId) - val assignmentId = tw.getFreshIdLabel() - val type = useType(if (isAnnotationClassField) kClassToJavaClass(expr.type) else expr.type) - tw.writeExprs_assignexpr(assignmentId, type.javaResult.id, stmtId, 0) - tw.writeExprsKotlinType(assignmentId, type.kotlinResult.id) - tw.writeHasLocation(assignmentId, declLocId) - tw.writeCallableEnclosingExpr(assignmentId, blockAndFunctionId.second) - tw.writeStatementEnclosingExpr(assignmentId, stmtId) - tw.writeKtInitializerAssignment(assignmentId) - - val lhsId = tw.getFreshIdLabel() - tw.writeExprs_varaccess(lhsId, lhsType.javaResult.id, assignmentId, 0) - tw.writeExprsKotlinType(lhsId, lhsType.kotlinResult.id) - tw.writeHasLocation(lhsId, declLocId) - tw.writeCallableEnclosingExpr(lhsId, blockAndFunctionId.second) - tw.writeStatementEnclosingExpr(lhsId, stmtId) - - tw.writeVariableBinding(lhsId, vId) - - if (static) { - extractStaticTypeAccessQualifier(f, lhsId, declLocId, blockAndFunctionId.second, stmtId) + extractExpressionStmt(declLocId, blockAndFunctionId.first, idx++, blockAndFunctionId.second).also { stmtId -> + val type = if (isAnnotationClassField) kClassToJavaClass(expr.type) else expr.type + extractAssignExpr(type, declLocId, stmtId, 0, blockAndFunctionId.second, stmtId).also { assignmentId -> + tw.writeKtInitializerAssignment(assignmentId) + extractVariableAccess(vId, lhsType, declLocId, assignmentId, 0, blockAndFunctionId.second, stmtId).also { lhsId -> + if (static) { + extractStaticTypeAccessQualifier(f, lhsId, declLocId, blockAndFunctionId.second, stmtId) + } + } + extractExpressionExpr(expr, blockAndFunctionId.second, assignmentId, 1, stmtId) + } } - - extractExpressionExpr(expr, blockAndFunctionId.second, assignmentId, 1, stmtId) } for (decl in declarations) { @@ -832,10 +828,123 @@ open class KotlinFileExtractor( null else { forceExtractFunction(f, parentId, extractBody, extractMethodAndParameterTypeAccesses, typeSubstitution, classTypeArgsIncludingOuterClasses).also { + // The defaults-forwarder function is a static utility, not a member, so we only need to extract this for the unspecialised instance of this class. + if (classTypeArgsIncludingOuterClasses.isNullOrEmpty()) + extractDefaultsFunction(f, parentId, extractBody, extractMethodAndParameterTypeAccesses) extractGeneratedOverloads(f, parentId, null, extractBody, extractMethodAndParameterTypeAccesses, typeSubstitution, classTypeArgsIncludingOuterClasses) } } + private fun extractDefaultsFunction(f: IrFunction, parentId: Label, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean) { + if (f.valueParameters.none { it.defaultValue != null }) + return + + val id = getDefaultsMethodLabel(f) + val locId = getLocation(f, null) + val extReceiver = f.extensionReceiverParameter + val dispatchReceiver = if (f.shouldExtractAsStatic) null else f.dispatchReceiverParameter + val parameterTypes = listOfNotNull(extReceiver?.let { erase(it.type) }) + getDefaultsMethodArgTypes(f) + val allParamTypeResults = parameterTypes.mapIndexed { i, paramType -> + val paramId = tw.getLabelFor(getValueParameterLabel(id, i)) + extractValueParameter(paramId, paramType, "p$i", locId, id, i, paramId, isVararg = false, syntheticParameterNames = true, isCrossinline = false, isNoinline = false).also { + if (extractMethodAndParameterTypeAccesses) + extractTypeAccess(useType(paramType), locId, paramId, -1) + } + } + val paramsSignature = allParamTypeResults.joinToString(separator = ",", prefix = "(", postfix = ")") { it.javaResult.signature } + val shortName = getDefaultsMethodName(f) + + if (f.symbol is IrConstructorSymbol) { + val constrId = id.cast() + extractConstructor(constrId, shortName, paramsSignature, parentId, constrId) + } else { + val methodId = id.cast() + extractMethod(methodId, locId, shortName, erase(f.returnType), paramsSignature, parentId, methodId, origin = null, extractTypeAccess = extractMethodAndParameterTypeAccesses) + addModifiers(id, "static") + } + tw.writeHasLocation(id, locId) + if (f.visibility != DescriptorVisibilities.PRIVATE && f.visibility != DescriptorVisibilities.PRIVATE_TO_THIS) { + // Private methods have package-private (default) visibility $default methods; all other visibilities seem to produce a public $default method. + addModifiers(id, "public") + } + tw.writeCompiler_generated(id, CompilerGeneratedKinds.DEFAULT_ARGUMENTS_METHOD.kind) + + if (extractBody) { + val nonSyntheticParams = listOfNotNull(dispatchReceiver) + f.valueParameters + // This stack entry represents as if we're extracting the 'real' function `f`, giving the indices of its non-synthetic parameters + // such that when we extract the default expressions below, any reference to f's nth parameter will resolve to f$default's + // n + o'th parameter, where `o` is the parameter offset caused by adding any dispatch receiver to the parameter list. + // Note we don't need to add the extension receiver here because `useValueParameter` always assumes an extension receiver + // will be prepended if one exists. + // Note we have to get the real function ID here before entering this block, because otherwise we'll misrepresent the signature of a generic + // function without its type variables -- for example, trying to address `f(T, List)` as `f(Object, List)`. + val realFunctionId = useFunction(f) + DeclarationStackAdjuster(f, OverriddenFunctionAttributes(id, id, locId, nonSyntheticParams, typeParameters = listOf(), isStatic = true)).use { + val realParamsVarId = getValueParameterLabel(id, parameterTypes.size - 2) + val intType = pluginContext.irBuiltIns.intType + val paramIdxOffset = listOf(dispatchReceiver, f.extensionReceiverParameter).count { it != null } + extractBlockBody(id, locId).also { blockId -> + var nextStmt = 0 + // For each parameter with a default, sub in the default value if the caller hasn't supplied a value: + f.valueParameters.forEachIndexed { paramIdx, param -> + val defaultVal = param.defaultValue + if (defaultVal != null) { + extractIfStmt(locId, blockId, nextStmt++, id).also { ifId -> + // if (realParams & thisParamBit == 0) ... + extractEqualsExpression(locId, ifId, 0, id, ifId).also { eqId -> + extractAndbitExpression(intType, locId, eqId, 0, id, ifId).also { opId -> + extractConstantInteger(1 shl paramIdx, locId, opId, 0, id, ifId) + extractVariableAccess(tw.getLabelFor(realParamsVarId), intType, locId, opId, 1, id, ifId) + } + extractConstantInteger(0, locId, eqId, 1, id, ifId) + } + // thisParamVar = defaultExpr... + extractExpressionStmt(locId, ifId, 1, id).also { exprStmtId -> + extractAssignExpr(param.type, locId, exprStmtId, 0, id, exprStmtId).also { assignId -> + extractVariableAccess(tw.getLabelFor(getValueParameterLabel(id, paramIdx + paramIdxOffset)), param.type, locId, assignId, 0, id, exprStmtId) + extractExpressionExpr(defaultVal.expression, id, assignId, 1, exprStmtId) + } + } + } + } + } + // Now call the real function: + if (f is IrConstructor) { + tw.getFreshIdLabel().also { thisCallId -> + tw.writeStmts_constructorinvocationstmt(thisCallId, blockId, nextStmt++, id) + tw.writeHasLocation(thisCallId, locId) + f.valueParameters.forEachIndexed { idx, param -> + extractVariableAccess(tw.getLabelFor(getValueParameterLabel(id, idx)), param.type, locId, thisCallId, idx, id, thisCallId) + } + tw.writeCallableBinding(thisCallId, realFunctionId) + } + } else { + tw.getFreshIdLabel().also { returnId -> + tw.writeStmts_returnstmt(returnId, blockId, nextStmt++, id) + tw.writeHasLocation(returnId, locId) + extractMethodAccessWithoutArgs(f.returnType, locId, id, returnId, 0, returnId, realFunctionId).also { thisCallId -> + val realFnIdxOffset = if (f.extensionReceiverParameter != null) 1 else 0 + val paramMappings = f.valueParameters.mapIndexed { idx, param -> Triple(param.type, idx + paramIdxOffset, idx + realFnIdxOffset) } + + listOfNotNull( + dispatchReceiver?.let { Triple(it.type, realFnIdxOffset, -1) }, + extReceiver?.let { Triple(it.type, 0, 0) } + ) + paramMappings.forEach { (type, fromIdx, toIdx) -> + extractVariableAccess(tw.getLabelFor(getValueParameterLabel(id, fromIdx)), type, locId, thisCallId, toIdx, id, returnId) + } + if (f.shouldExtractAsStatic) + extractStaticTypeAccessQualifier(f, thisCallId, locId, id, returnId) + else if (f.isLocalFunction()) { + extractNewExprForLocalFunction(getLocallyVisibleFunctionLabels(f), thisCallId, locId, id, returnId) + } + } + } + } + } + } + } + } + private val jvmOverloadsFqName = FqName("kotlin.jvm.JvmOverloads") private fun extractGeneratedOverloads(f: IrFunction, parentId: Label, maybeSourceParentId: Label?, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List?) { @@ -884,10 +993,7 @@ open class KotlinFileExtractor( // Create a synthetic function body that calls the real function supplying default arguments where required: if (f is IrConstructor) { - val blockId = tw.getFreshIdLabel() - tw.writeStmts_block(blockId, overloadId, 0, overloadId) - tw.writeHasLocation(blockId, realFunctionLocId) - + val blockId = extractBlockBody(overloadId, realFunctionLocId) val constructorCallId = tw.getFreshIdLabel() tw.writeStmts_constructorinvocationstmt(constructorCallId, blockId, 0, overloadId) tw.writeHasLocation(constructorCallId, realFunctionLocId) @@ -932,6 +1038,29 @@ open class KotlinFileExtractor( } } + private fun extractConstructor(id: Label, shortName: String, paramsSignature: String, parentId: Label, sourceDeclaration: Label) { + val unitType = useType(pluginContext.irBuiltIns.unitType, TypeContext.RETURN) + tw.writeConstrs(id, shortName, "$shortName$paramsSignature", unitType.javaResult.id, parentId, sourceDeclaration) + tw.writeConstrsKotlinType(id, unitType.kotlinResult.id) + } + + private fun extractMethod(id: Label, locId: Label, shortName: String, returnType: IrType, paramsSignature: String, parentId: Label, sourceDeclaration: Label, origin: IrDeclarationOrigin?, extractTypeAccess: Boolean) { + val returnTypeResults = useType(returnType, TypeContext.RETURN) + tw.writeMethods(id, shortName, "$shortName$paramsSignature", returnTypeResults.javaResult.id, parentId, sourceDeclaration) + tw.writeMethodsKotlinType(id, returnTypeResults.kotlinResult.id) + when (origin) { + IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER -> + tw.writeCompiler_generated(id, CompilerGeneratedKinds.GENERATED_DATA_CLASS_MEMBER.kind) + IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR -> + tw.writeCompiler_generated(id, CompilerGeneratedKinds.DEFAULT_PROPERTY_ACCESSOR.kind) + IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER -> + tw.writeCompiler_generated(id, CompilerGeneratedKinds.ENUM_CLASS_SPECIAL_MEMBER.kind) + } + if (extractTypeAccess) { + extractTypeAccessRecursive(returnType, locId, id, -1) + } + } + private fun forceExtractFunction(f: IrFunction, parentId: Label, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List?, extractOrigin: Boolean = true, overriddenAttributes: OverriddenFunctionAttributes? = null): Label { with("function", f) { DeclarationStackAdjuster(f, overriddenAttributes).use { @@ -976,42 +1105,23 @@ open class KotlinFileExtractor( val locId = overriddenAttributes?.sourceLoc ?: getLocation(f, classTypeArgsIncludingOuterClasses) if (f.symbol is IrConstructorSymbol) { - val unitType = useType(pluginContext.irBuiltIns.unitType, TypeContext.RETURN) val shortName = when { adjustedReturnType.isAnonymous -> "" typeSubstitution != null -> useType(substReturnType).javaResult.shortName else -> adjustedReturnType.classFqName?.shortName()?.asString() ?: f.name.asString() } - val constrId = id.cast() - tw.writeConstrs(constrId, shortName, "$shortName$paramsSignature", unitType.javaResult.id, parentId, sourceDeclaration.cast()) - tw.writeConstrsKotlinType(constrId, unitType.kotlinResult.id) + extractConstructor(id.cast(), shortName, paramsSignature, parentId, sourceDeclaration.cast()) } else { - val returnType = useType(substReturnType, TypeContext.RETURN) - val shortName = getFunctionShortName(f) + val shortNames = getFunctionShortName(f) val methodId = id.cast() - tw.writeMethods(methodId, shortName.nameInDB, "${shortName.nameInDB}$paramsSignature", returnType.javaResult.id, parentId, sourceDeclaration.cast()) - tw.writeMethodsKotlinType(methodId, returnType.kotlinResult.id) - if (extractOrigin) { - when (f.origin) { - IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER -> - tw.writeCompiler_generated(methodId, CompilerGeneratedKinds.GENERATED_DATA_CLASS_MEMBER.kind) - IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR -> - tw.writeCompiler_generated(methodId, CompilerGeneratedKinds.DEFAULT_PROPERTY_ACCESSOR.kind) - IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER -> - tw.writeCompiler_generated(methodId, CompilerGeneratedKinds.ENUM_CLASS_SPECIAL_MEMBER.kind) - } - } + extractMethod(methodId, locId, shortNames.nameInDB, substReturnType, paramsSignature, parentId, sourceDeclaration.cast(), if (extractOrigin) f.origin else null, extractMethodAndParameterTypeAccesses) - if (extractMethodAndParameterTypeAccesses) { - extractTypeAccessRecursive(substReturnType, locId, id, -1) - } - - if (shortName.nameInDB != shortName.kotlinName) { - tw.writeKtFunctionOriginalNames(methodId, shortName.kotlinName) + if (shortNames.nameInDB != shortNames.kotlinName) { + tw.writeKtFunctionOriginalNames(methodId, shortNames.kotlinName) } if (f.hasInterfaceParent() && f.body != null) { - addModifiers(id, "default") // The actual output class file may or may not have this modifier, depending on the -Xjvm-default setting. + addModifiers(methodId, "default") // The actual output class file may or may not have this modifier, depending on the -Xjvm-default setting. } } @@ -1158,7 +1268,7 @@ open class KotlinFileExtractor( } } - private fun extractEnumEntry(ee: IrEnumEntry, parentId: Label, extractTypeAccess: Boolean) { + private fun extractEnumEntry(ee: IrEnumEntry, parentId: Label, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean) { with("enum entry", ee) { DeclarationStackAdjuster(ee).use { val id = useEnumEntry(ee) @@ -1169,7 +1279,7 @@ open class KotlinFileExtractor( tw.writeHasLocation(id, locId) tw.writeIsEnumConst(id) - if (extractTypeAccess) { + if (extractFunctionBodies) { val fieldDeclarationId = tw.getFreshIdLabel() tw.writeFielddecls(fieldDeclarationId, parentId) tw.writeFieldDeclaredIn(id, fieldDeclarationId, 0) @@ -1177,6 +1287,10 @@ open class KotlinFileExtractor( extractTypeAccess(type, locId, fieldDeclarationId, 0) } + + ee.correspondingClass?.let { + extractDeclaration(it, extractPrivateMembers, extractFunctionBodies) + } } } } @@ -1209,14 +1323,18 @@ open class KotlinFileExtractor( } } + private fun extractBlockBody(callable: Label, locId: Label) = + tw.getFreshIdLabel().also { + tw.writeStmts_block(it, callable, 0, callable) + tw.writeHasLocation(it, locId) + } + private fun extractBlockBody(b: IrBlockBody, callable: Label) { with("block body", b) { - val id = tw.getFreshIdLabel() - val locId = tw.getLocation(b) - tw.writeStmts_block(id, callable, 0, callable) - tw.writeHasLocation(id, locId) - for ((sIdx, stmt) in b.statements.withIndex()) { - extractStatement(stmt, callable, id, sIdx) + extractBlockBody(callable, tw.getLocation(b)).also { + for ((sIdx, stmt) in b.statements.withIndex()) { + extractStatement(stmt, callable, it, sIdx) + } } } } @@ -1239,11 +1357,8 @@ open class KotlinFileExtractor( } } - fun extractExpressionBody(callable: Label, locId: Label): Label { - val blockId = tw.getFreshIdLabel() - tw.writeStmts_block(blockId, callable, 0, callable) - tw.writeHasLocation(blockId, locId) - + fun extractExpressionBody(callable: Label, locId: Label): Label { + val blockId = extractBlockBody(callable, locId) return tw.getFreshIdLabel().also { returnId -> tw.writeStmts_returnstmt(returnId, blockId, 0, callable) tw.writeHasLocation(returnId, locId) @@ -1294,6 +1409,12 @@ open class KotlinFileExtractor( } } + private fun extractIfStmt(locId: Label, parent: Label, idx: Int, callable: Label) = + tw.getFreshIdLabel().also { + tw.writeStmts_ifstmt(it, parent, idx, callable) + tw.writeHasLocation(it, locId) + } + private fun extractStatement(s: IrStatement, callable: Label, parent: Label, idx: Int) { with("statement", s) { when(s) { @@ -1521,6 +1642,209 @@ open class KotlinFileExtractor( extractTypeAccessRecursive(pluginContext.irBuiltIns.anyType, locId, idNewexpr, -3, enclosingCallable, enclosingStmt) } + private fun extractMethodAccessWithoutArgs( + returnType: IrType, + locId: Label, + enclosingCallable: Label, + callsiteParent: Label, + childIdx: Int, + enclosingStmt: Label, + methodLabel: Label? + ) = tw.getFreshIdLabel().also { id -> + val type = useType(returnType) + + tw.writeExprs_methodaccess(id, type.javaResult.id, callsiteParent, childIdx) + tw.writeExprsKotlinType(id, type.kotlinResult.id) + tw.writeHasLocation(id, locId) + tw.writeCallableEnclosingExpr(id, enclosingCallable) + tw.writeStatementEnclosingExpr(id, enclosingStmt) + + // The caller should have warned about this before, so we don't repeat the warning here. + if (methodLabel != null) + tw.writeCallableBinding(id, methodLabel) + } + + private val defaultConstructorMarkerClass by lazy { + val result = pluginContext.referenceClass(FqName("kotlin.jvm.internal.DefaultConstructorMarker"))?.owner + result?.let { extractExternalClassLater(it) } + result + } + + private val defaultConstructorMarkerType by lazy { + defaultConstructorMarkerClass?.typeWith() + } + + private fun getDefaultsMethodLastArgType(f: IrFunction) = + ( + if (f is IrConstructor) + defaultConstructorMarkerType + else + null + ) ?: pluginContext.irBuiltIns.anyType + + private fun getDefaultsMethodArgTypes(f: IrFunction) = + // The $default method has type ([extensionReceiver], [dispatchReceiver], paramTypes..., int, Object) + // All parameter types are erased. The trailing int is a mask indicating which parameter values are real + // and which should be replaced by defaults. The final Object parameter is apparently always null. + ( + listOfNotNull(if (f.shouldExtractAsStatic) null else f.dispatchReceiverParameter?.type) + + f.valueParameters.map { it.type } + + listOf(pluginContext.irBuiltIns.intType, getDefaultsMethodLastArgType(f)) + ).map { erase(it) } + + private fun getDefaultsMethodName(f: IrFunction) = + if (f is IrConstructor) { + f.returnType.let { + when { + it.isAnonymous -> "" + else -> it.classFqName?.shortName()?.asString() ?: f.name.asString() + } + } + } else { + getFunctionShortName(f).nameInDB + "\$default" + } + + private fun getDefaultsMethodLabel(f: IrFunction): Label { + val defaultsMethodName = getDefaultsMethodName(f) + val normalArgTypes = getDefaultsMethodArgTypes(f) + val extensionParamType = f.extensionReceiverParameter?.let { erase(it.type) } + + val defaultMethodLabelStr = getFunctionLabel( + f.parent, + maybeParentId = null, + defaultsMethodName, + normalArgTypes, + erase(f.returnType), + extensionParamType, + listOf(), + classTypeArgsIncludingOuterClasses = null, + overridesCollectionsMethod = false, + javaSignature = null, + addParameterWildcardsByDefault = false + ) + + return tw.getLabelFor(defaultMethodLabelStr) + } + + private fun extractsDefaultsCall( + syntacticCallTarget: IrFunction, + locId: Label, + callsite: IrCall, + enclosingCallable: Label, + callsiteParent: Label, + childIdx: Int, + enclosingStmt: Label, + valueArguments: List, + dispatchReceiver: IrExpression?, + extensionReceiver: IrExpression? + ) { + val callTarget = syntacticCallTarget.target.realOverrideTarget + if (isExternalDeclaration(callTarget)) { + // Ensure the real target gets extracted, as we might not every directly touch it thanks to this call being redirected to a $default method. + useFunction(callTarget) + } + val defaultMethodLabel = getDefaultsMethodLabel(callTarget) + val id = extractMethodAccessWithoutArgs(callsite.type, locId, enclosingCallable, callsiteParent, childIdx, enclosingStmt, defaultMethodLabel) + + if (callTarget.isLocalFunction()) { + extractTypeAccess(getLocallyVisibleFunctionLabels(callTarget).type, locId, id, -1, enclosingCallable, enclosingStmt) + } else { + extractStaticTypeAccessQualifierUnchecked(callTarget.parent, id, locId, enclosingCallable, enclosingStmt) + } + + extractDefaultsCallArguments(id, callTarget, enclosingCallable, enclosingStmt, valueArguments, dispatchReceiver, extensionReceiver) + } + + private fun extractDefaultsCallArguments( + id: Label, + callTarget: IrFunction, + enclosingCallable: Label, + enclosingStmt: Label, + valueArguments: List, + dispatchReceiver: IrExpression?, + extensionReceiver: IrExpression? + ) { + var nextIdx = 0 + if (extensionReceiver != null) { + extractExpressionExpr(extensionReceiver, enclosingCallable, id, nextIdx++, enclosingStmt) + } + if (dispatchReceiver != null && !callTarget.shouldExtractAsStatic) { + extractExpressionExpr(dispatchReceiver, enclosingCallable, id, nextIdx++, enclosingStmt) + } + + val valueArgsWithDummies = valueArguments.zip(callTarget.valueParameters).map { + (expr, param) -> expr ?: IrConstImpl.defaultValueForType(0, 0, param.type) + } + + var realParamsMask = 0 + valueArguments.forEachIndexed { index, arg -> if (arg != null) realParamsMask = realParamsMask or (1 shl index) } + + val extraArgs = listOf( + IrConstImpl.int(0, 0, pluginContext.irBuiltIns.intType, realParamsMask), + IrConstImpl.defaultValueForType(0, 0, getDefaultsMethodLastArgType(callTarget)) + ) + + extractCallValueArguments(id, valueArgsWithDummies + extraArgs, enclosingStmt, enclosingCallable, nextIdx) + } + + private fun getFunctionInvokeMethod(typeArgs: List): IrFunction? { + // For `kotlin.FunctionX` and `kotlin.reflect.KFunctionX` interfaces, we're making sure that we + // extract the call to the `invoke` method that does exist, `kotlin.jvm.functions.FunctionX::invoke`. + val functionalInterface = getFunctionalInterfaceTypeWithTypeArgs(typeArgs) + if (functionalInterface == null) { + logger.warn("Cannot find functional interface type for raw method access") + return null + } + val functionalInterfaceClass = functionalInterface.classOrNull + if (functionalInterfaceClass == null) { + logger.warn("Cannot find functional interface class for raw method access") + return null + } + val interfaceType = functionalInterfaceClass.owner + val substituted = getJavaEquivalentClass(interfaceType) ?: interfaceType + val function = findFunction(substituted, OperatorNameConventions.INVOKE.asString()) + if (function == null) { + logger.warn("Cannot find invoke function for raw method access") + return null + } + return function + } + + private fun isFunctionInvoke(callTarget: IrFunction, drType: IrSimpleType) = + (drType.isFunctionOrKFunction() || drType.isSuspendFunctionOrKFunction()) && + callTarget.name.asString() == OperatorNameConventions.INVOKE.asString() + + private fun getCalleeMethodId(callTarget: IrFunction, drType: IrType?, allowInstantiatedGenericMethod: Boolean): Label? { + if (callTarget.isLocalFunction()) + return getLocallyVisibleFunctionLabels(callTarget).function + + if (allowInstantiatedGenericMethod && drType is IrSimpleType && !isUnspecialised(drType, logger)) { + val calleeIsInvoke = isFunctionInvoke(callTarget, drType) + + val extractionMethod = + if (calleeIsInvoke) + getFunctionInvokeMethod(drType.arguments) + else + callTarget + + return extractionMethod?.let { + val typeArgs = + if (calleeIsInvoke && drType.arguments.size > BuiltInFunctionArity.BIG_ARITY) { + // Big arity `invoke` methods have a special implementation on JVM, they are transformed to a call to + // `kotlin.jvm.functions.FunctionN::invoke(vararg args: Any?)`, so we only need to pass the type + // argument for the return type. Additionally, the arguments are extracted inside an array literal below. + listOf(drType.arguments.last()) + } else { + getDeclaringTypeArguments(callTarget, drType) + } + useFunction(extractionMethod, typeArgs) + } + } + else { + return useFunction(callTarget) + } + } + fun extractRawMethodAccess( syntacticCallTarget: IrFunction, callsite: IrCall, @@ -1537,27 +1861,40 @@ open class KotlinFileExtractor( val locId = tw.getLocation(callsite) - extractRawMethodAccess( - syntacticCallTarget, - locId, - callsite.type, - enclosingCallable, - callsiteParent, - childIdx, - enclosingStmt, - valueArguments.size, - { argParent, idxOffset -> extractCallValueArguments(argParent, valueArguments, enclosingStmt, enclosingCallable, idxOffset) }, - dispatchReceiver?.type, - dispatchReceiver?.let { { callId -> extractExpressionExpr(dispatchReceiver, enclosingCallable, callId, -1, enclosingStmt) } }, - extensionReceiver?.let { { argParent -> extractExpressionExpr(extensionReceiver, enclosingCallable, argParent, 0, enclosingStmt) } }, - typeArguments, - extractClassTypeArguments, - superQualifierSymbol - ) - + if (valueArguments.any { it == null }) { + extractsDefaultsCall( + syntacticCallTarget, + locId, + callsite, + enclosingCallable, + callsiteParent, + childIdx, + enclosingStmt, + valueArguments, + dispatchReceiver, + extensionReceiver + ) + } else { + extractRawMethodAccess( + syntacticCallTarget, + locId, + callsite.type, + enclosingCallable, + callsiteParent, + childIdx, + enclosingStmt, + valueArguments.size, + { argParent, idxOffset -> extractCallValueArguments(argParent, valueArguments, enclosingStmt, enclosingCallable, idxOffset) }, + dispatchReceiver?.type, + dispatchReceiver?.let { { callId -> extractExpressionExpr(dispatchReceiver, enclosingCallable, callId, -1, enclosingStmt) } }, + extensionReceiver?.let { { argParent -> extractExpressionExpr(extensionReceiver, enclosingCallable, argParent, 0, enclosingStmt) } }, + typeArguments, + extractClassTypeArguments, + superQualifierSymbol + ) + } } - fun extractRawMethodAccess( syntacticCallTarget: IrFunction, locId: Label, @@ -1576,98 +1913,32 @@ open class KotlinFileExtractor( superQualifierSymbol: IrClassSymbol? = null) { val callTarget = syntacticCallTarget.target.realOverrideTarget - val id = tw.getFreshIdLabel() - val type = useType(returnType) + val methodId = getCalleeMethodId(callTarget, drType, extractClassTypeArguments) + if (methodId == null) { + logger.warn("No method to bind call to for raw method access") + } - tw.writeExprs_methodaccess(id, type.javaResult.id, callsiteParent, childIdx) - tw.writeExprsKotlinType(id, type.kotlinResult.id) - tw.writeHasLocation(id, locId) - tw.writeCallableEnclosingExpr(id, enclosingCallable) - tw.writeStatementEnclosingExpr(id, enclosingStmt) + val id = extractMethodAccessWithoutArgs(returnType, locId, enclosingCallable, callsiteParent, childIdx, enclosingStmt, methodId) // type arguments at index -2, -3, ... extractTypeArguments(typeArguments, locId, id, enclosingCallable, enclosingStmt, -2, true) - val (isFunctionInvoke, isBigArityFunctionInvoke) = - if (drType is IrSimpleType && - (drType.isFunctionOrKFunction() || drType.isSuspendFunctionOrKFunction()) && - callTarget.name.asString() == OperatorNameConventions.INVOKE.asString()) { - Pair(true, drType.arguments.size > BuiltInFunctionArity.BIG_ARITY) - } else { - Pair(false, false) - } - if (callTarget.isLocalFunction()) { - val ids = getLocallyVisibleFunctionLabels(callTarget) - - val methodId = ids.function - tw.writeCallableBinding(id, methodId) - - extractNewExprForLocalFunction(ids, id, locId, enclosingCallable, enclosingStmt) - } else { - val methodId = - if (extractClassTypeArguments && drType is IrSimpleType && !isUnspecialised(drType, logger)) { - - val extractionMethod = if (isFunctionInvoke) { - // For `kotlin.FunctionX` and `kotlin.reflect.KFunctionX` interfaces, we're making sure that we - // extract the call to the `invoke` method that does exist, `kotlin.jvm.functions.FunctionX::invoke`. - val functionalInterface = getFunctionalInterfaceTypeWithTypeArgs(drType.arguments) - if (functionalInterface == null) { - logger.warn("Cannot find functional interface type for raw method access") - null - } else { - val functionalInterfaceClass = functionalInterface.classOrNull - if (functionalInterfaceClass == null) { - logger.warn("Cannot find functional interface class for raw method access") - null - } else { - val interfaceType = functionalInterfaceClass.owner - val substituted = getJavaEquivalentClass(interfaceType) ?: interfaceType - val function = findFunction(substituted, OperatorNameConventions.INVOKE.asString()) - if (function == null) { - logger.warn("Cannot find invoke function for raw method access") - null - } else { - function - } - } - } - } else { - callTarget - } - - if (extractionMethod == null) { - null - } else if (isBigArityFunctionInvoke) { - // Big arity `invoke` methods have a special implementation on JVM, they are transformed to a call to - // `kotlin.jvm.functions.FunctionN::invoke(vararg args: Any?)`, so we only need to pass the type - // argument for the return type. Additionally, the arguments are extracted inside an array literal below. - useFunction(extractionMethod, listOf(drType.arguments.last())) - } else { - useFunction(extractionMethod, getDeclaringTypeArguments(callTarget, drType)) - } - } - else { - useFunction(callTarget) - } - - if (methodId == null) { - logger.warn("No method to bind call to for raw method access") - } else { - tw.writeCallableBinding(id, methodId) - } - - if (callTarget.shouldExtractAsStatic) { - extractStaticTypeAccessQualifier(callTarget, id, locId, enclosingCallable, enclosingStmt) - } else if (superQualifierSymbol != null) { - extractSuperAccess(superQualifierSymbol.typeWith(), enclosingCallable, id, -1, enclosingStmt, locId) - } else if (extractDispatchReceiver != null) { - extractDispatchReceiver(id) - } + extractNewExprForLocalFunction(getLocallyVisibleFunctionLabels(callTarget), id, locId, enclosingCallable, enclosingStmt) + } else if (callTarget.shouldExtractAsStatic) { + extractStaticTypeAccessQualifier(callTarget, id, locId, enclosingCallable, enclosingStmt) + } else if (superQualifierSymbol != null) { + extractSuperAccess(superQualifierSymbol.typeWith(), enclosingCallable, id, -1, enclosingStmt, locId) + } else if (extractDispatchReceiver != null) { + extractDispatchReceiver(id) } val idxOffset = if (extractExtensionReceiver != null) 1 else 0 + val isBigArityFunctionInvoke = drType is IrSimpleType && + isFunctionInvoke(callTarget, drType) && + drType.arguments.size > BuiltInFunctionArity.BIG_ARITY + val argParent = if (isBigArityFunctionInvoke) { extractArrayCreationWithInitializer(id, nValueArguments + idxOffset, locId, enclosingCallable, enclosingStmt) } else { @@ -1681,16 +1952,19 @@ open class KotlinFileExtractor( extractValueArguments(argParent, idxOffset) } + private fun extractStaticTypeAccessQualifierUnchecked(parent: IrDeclarationParent, parentExpr: Label, locId: Label, enclosingCallable: Label, enclosingStmt: Label) { + if (parent is IrClass) { + extractTypeAccessRecursive(parent.toRawType(), locId, parentExpr, -1, enclosingCallable, enclosingStmt) + } else if (parent is IrFile) { + extractTypeAccess(useFileClassType(parent), locId, parentExpr, -1, enclosingCallable, enclosingStmt) + } else { + logger.warnElement("Unexpected static type access qualifier ${parent.javaClass}", parent) + } + } + private fun extractStaticTypeAccessQualifier(target: IrDeclaration, parentExpr: Label, locId: Label, enclosingCallable: Label, enclosingStmt: Label) { if (target.shouldExtractAsStatic) { - val parent = target.parent - if (parent is IrClass) { - extractTypeAccessRecursive(parent.toRawType(), locId, parentExpr, -1, enclosingCallable, enclosingStmt) - } else if (parent is IrFile) { - extractTypeAccess(useFileClassType(parent), locId, parentExpr, -1, enclosingCallable, enclosingStmt) - } else { - logger.warnElement("Unexpected static type access qualifer ${parent.javaClass}", target) - } + extractStaticTypeAccessQualifierUnchecked(target.parent, parentExpr, locId, enclosingCallable, enclosingStmt) } } @@ -2391,15 +2665,7 @@ open class KotlinFileExtractor( tw.writeStatementEnclosingExpr(initId, enclosingStmt) it.elements.forEachIndexed { i, arg -> extractVarargElement(arg, callable, initId, i, enclosingStmt) } - val dim = it.elements.size - val dimId = tw.getFreshIdLabel() - val dimType = useType(pluginContext.irBuiltIns.intType) - tw.writeExprs_integerliteral(dimId, dimType.javaResult.id, id, 0) - tw.writeExprsKotlinType(dimId, dimType.kotlinResult.id) - tw.writeHasLocation(dimId, locId) - tw.writeCallableEnclosingExpr(dimId, callable) - tw.writeStatementEnclosingExpr(dimId, enclosingStmt) - tw.writeNamestrings(dim.toString(), dim.toString(), dimId) + extractConstantInteger(it.elements.size, locId, id, 0, callable, enclosingStmt) } } } @@ -2471,27 +2737,21 @@ open class KotlinFileExtractor( if (array != null && arrayIdx != null && assignedValue != null) { - val assignId = tw.getFreshIdLabel() - val type = useType(c.type) val locId = tw.getLocation(c) - tw.writeExprs_assignexpr(assignId, type.javaResult.id, parent, idx) - tw.writeExprsKotlinType(assignId, type.kotlinResult.id) - tw.writeHasLocation(assignId, locId) - tw.writeCallableEnclosingExpr(assignId, callable) - tw.writeStatementEnclosingExpr(assignId, enclosingStmt) + extractAssignExpr(c.type, locId, parent, idx, callable, enclosingStmt).also { assignId -> + tw.getFreshIdLabel().also { arrayAccessId -> + val arrayType = useType(array.type) + tw.writeExprs_arrayaccess(arrayAccessId, arrayType.javaResult.id, assignId, 0) + tw.writeExprsKotlinType(arrayAccessId, arrayType.kotlinResult.id) + tw.writeHasLocation(arrayAccessId, locId) + tw.writeCallableEnclosingExpr(arrayAccessId, callable) + tw.writeStatementEnclosingExpr(arrayAccessId, enclosingStmt) - val arrayAccessId = tw.getFreshIdLabel() - val arrayType = useType(array.type) - tw.writeExprs_arrayaccess(arrayAccessId, arrayType.javaResult.id, assignId, 0) - tw.writeExprsKotlinType(arrayAccessId, arrayType.kotlinResult.id) - tw.writeHasLocation(arrayAccessId, locId) - tw.writeCallableEnclosingExpr(arrayAccessId, callable) - tw.writeStatementEnclosingExpr(arrayAccessId, enclosingStmt) - - extractExpressionExpr(array, callable, arrayAccessId, 0, enclosingStmt) - extractExpressionExpr(arrayIdx, callable, arrayAccessId, 1, enclosingStmt) - - extractExpressionExpr(assignedValue, callable, assignId, 1, enclosingStmt) + extractExpressionExpr(array, callable, arrayAccessId, 0, enclosingStmt) + extractExpressionExpr(arrayIdx, callable, arrayAccessId, 1, enclosingStmt) + } + extractExpressionExpr(assignedValue, callable, assignId, 1, enclosingStmt) + } } else { logger.errorElement("Unexpected Array.set function signature", c) @@ -2664,14 +2924,24 @@ open class KotlinFileExtractor( useType(eType) } val locId = tw.getLocation(e) - val id = extractNewExpr(e.symbol.owner, eType.arguments, type, locId, parent, idx, callable, enclosingStmt) + val valueArgs = (0 until e.valueArgumentsCount).map { e.getValueArgument(it) } + // For now, don't try to use default methods for enum constructor calls, + // which have null arguments even though the parameters don't give default values. + val anyDefaultArgs = e !is IrEnumConstructorCall && valueArgs.any { it == null } + val id = if (anyDefaultArgs) { + extractNewExpr(getDefaultsMethodLabel(e.symbol.owner).cast(), type, locId, parent, idx, callable, enclosingStmt).also { + extractDefaultsCallArguments(it, e.symbol.owner, callable, enclosingStmt, valueArgs, null, null) + } + } else { + extractNewExpr(e.symbol.owner, eType.arguments, type, locId, parent, idx, callable, enclosingStmt).also { + extractCallValueArguments(it, e, enclosingStmt, callable, 0) + } + } if (isAnonymous) { tw.writeIsAnonymClass(type.javaResult.id.cast(), id) } - extractCallValueArguments(id, e, enclosingStmt, callable, 0) - val dr = e.dispatchReceiver if (dr != null) { extractExpressionExpr(dr, callable, id, -2, enclosingStmt) @@ -2719,16 +2989,12 @@ open class KotlinFileExtractor( } inner class StmtParent(val parent: Label, val idx: Int): StmtExprParent() { - override fun stmt(e: IrExpression, callable: Label): StmtParent { - return this - } - override fun expr(e: IrExpression, callable: Label): ExprParent { - val id = tw.getFreshIdLabel() - val locId = tw.getLocation(e) - tw.writeStmts_exprstmt(id, parent, idx, callable) - tw.writeHasLocation(id, locId) - return ExprParent(id, 0, id) - } + override fun stmt(e: IrExpression, callable: Label) = this + + override fun expr(e: IrExpression, callable: Label) = + extractExpressionStmt(tw.getLocation(e), parent, idx, callable).let { id -> + ExprParent(id, 0, id) + } } inner class ExprParent(val parent: Label, val idx: Int, val enclosingStmt: Label): StmtExprParent() { override fun stmt(e: IrExpression, callable: Label): StmtParent { @@ -2870,6 +3136,12 @@ open class KotlinFileExtractor( return false } + private fun extractExpressionStmt(locId: Label, parent: Label, idx: Int, callable: Label) = + tw.getFreshIdLabel().also { + tw.writeStmts_exprstmt(it, parent, idx, callable) + tw.writeHasLocation(it, locId) + } + private fun extractExpressionStmt(e: IrExpression, callable: Label, parent: Label, idx: Int) { extractExpression(e, callable, StmtParent(parent, idx)) } @@ -2878,6 +3150,45 @@ open class KotlinFileExtractor( extractExpression(e, callable, ExprParent(parent, idx, enclosingStmt)) } + private fun extractExprContext(id: Label, locId: Label, callable: Label, enclosingStmt: Label) { + tw.writeHasLocation(id, locId) + tw.writeCallableEnclosingExpr(id, callable) + tw.writeStatementEnclosingExpr(id, enclosingStmt) + } + + private fun extractEqualsExpression(locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = + tw.getFreshIdLabel().also { + val type = useType(pluginContext.irBuiltIns.booleanType) + tw.writeExprs_eqexpr(it, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(it, type.kotlinResult.id) + extractExprContext(it, locId, callable, enclosingStmt) + } + + private fun extractAndbitExpression(type: IrType, locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = + tw.getFreshIdLabel().also { + val typeResults = useType(type) + tw.writeExprs_andbitexpr(it, typeResults.javaResult.id, parent, idx) + tw.writeExprsKotlinType(it, typeResults.kotlinResult.id) + extractExprContext(it, locId, callable, enclosingStmt) + } + + private fun extractConstantInteger(v: Int, locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = + tw.getFreshIdLabel().also { + val type = useType(pluginContext.irBuiltIns.intType) + tw.writeExprs_integerliteral(it, type.javaResult.id, parent, idx) + tw.writeExprsKotlinType(it, type.kotlinResult.id) + tw.writeNamestrings(v.toString(), v.toString(), it) + extractExprContext(it, locId, callable, enclosingStmt) + } + + private fun extractAssignExpr(type: IrType, locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = + tw.getFreshIdLabel().also { + val typeResults = useType(type) + tw.writeExprs_assignexpr(it, typeResults.javaResult.id, parent, idx) + tw.writeExprsKotlinType(it, typeResults.kotlinResult.id) + extractExprContext(it, locId, callable, enclosingStmt) + } + private fun extractExpression(e: IrExpression, callable: Label, parent: StmtExprParent) { with("expression", e) { when(e) { @@ -3128,7 +3439,7 @@ open class KotlinFileExtractor( val exprParent = parent.expr(e, callable) val owner = e.symbol.owner if (owner is IrValueParameter && owner.index == -1 && !owner.isExtensionReceiver()) { - extractThisAccess(e, exprParent, callable) + extractThisAccess(e, owner.parent, exprParent, callable) } else { val isAnnotationClassParameter = ((owner as? IrValueParameter)?.parent as? IrConstructor)?.parentClassOrNull?.kind == ClassKind.ANNOTATION_CLASS val extractType = if (isAnnotationClassParameter) kClassToJavaClass(e.type) else e.type @@ -3470,9 +3781,8 @@ open class KotlinFileExtractor( extractTypeAccessRecursive(irType, locId, it, 0) } - private fun extractThisAccess(irType: IrType, callable: Label, parent: Label, idx: Int, enclosingStmt: Label, locId: Label) = + private fun extractThisAccess(type: TypeResults, callable: Label, parent: Label, idx: Int, enclosingStmt: Label, locId: Label) = tw.getFreshIdLabel().also { - val type = useType(irType) tw.writeExprs_thisaccess(it, type.javaResult.id, parent, idx) tw.writeExprsKotlinType(it, type.kotlinResult.id) tw.writeHasLocation(it, locId) @@ -3480,7 +3790,10 @@ open class KotlinFileExtractor( tw.writeStatementEnclosingExpr(it, enclosingStmt) } - private fun extractThisAccess(e: IrGetValue, exprParent: ExprParent, callable: Label) { + private fun extractThisAccess(irType: IrType, callable: Label, parent: Label, idx: Int, enclosingStmt: Label, locId: Label) = + extractThisAccess(useType(irType), callable, parent, idx, enclosingStmt, locId) + + private fun extractThisAccess(e: IrGetValue, thisParamParent: IrDeclarationParent, exprParent: ExprParent, callable: Label) { val containingDeclaration = declarationStack.peek().first val locId = tw.getLocation(e) @@ -3492,6 +3805,20 @@ open class KotlinFileExtractor( extractStaticTypeAccessQualifier(containingDeclaration, varAccessId, locId, callable, exprParent.enclosingStmt) } } else { + if (thisParamParent is IrFunction) { + val overriddenAttributes = declarationStack.findOverriddenAttributes(thisParamParent) + val replaceWithParamIdx = overriddenAttributes?.valueParameters?.indexOf(e.symbol.owner) + if (replaceWithParamIdx != null && replaceWithParamIdx != -1) { + // Use of 'this' in a function where the dispatch receiver is passed like an ordinary parameter, + // such as a `$default` static function that substitutes in default arguments as needed. + val paramDeclarerId = overriddenAttributes.id ?: useDeclarationParent(thisParamParent, false) + val extensionParamOffset = if (thisParamParent.extensionReceiverParameter != null) 1 else 0 + val replacementParamId = tw.getLabelFor(getValueParameterLabel(paramDeclarerId, replaceWithParamIdx + extensionParamOffset)) + extractVariableAccess(replacementParamId, e.type, locId, exprParent.parent, exprParent.idx, callable, exprParent.enclosingStmt) + return + } + } + val id = extractThisAccess(e.type, callable, exprParent.parent, exprParent.idx, exprParent.enclosingStmt, locId) fun extractTypeAccess(parent: IrClass) { @@ -3524,9 +3851,8 @@ open class KotlinFileExtractor( } } - private fun extractVariableAccess(variable: Label?, irType: IrType, locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = + private fun extractVariableAccess(variable: Label?, type: TypeResults, locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = tw.getFreshIdLabel().also { - val type = useType(irType) tw.writeExprs_varaccess(it, type.javaResult.id, parent, idx) tw.writeExprsKotlinType(it, type.kotlinResult.id) tw.writeHasLocation(it, locId) @@ -3538,6 +3864,9 @@ open class KotlinFileExtractor( } } + private fun extractVariableAccess(variable: Label?, irType: IrType, locId: Label, parent: Label, idx: Int, callable: Label, enclosingStmt: Label) = + extractVariableAccess(variable, useType(irType), locId, parent, idx, callable, enclosingStmt) + private fun extractLoop( loop: IrLoop, stmtExprParent: StmtExprParent, @@ -3611,33 +3940,16 @@ open class KotlinFileExtractor( stmtIdx: Int ) { val paramId = tw.getFreshIdLabel() - val paramTypeRes = extractValueParameter(paramId, paramType, paramName, locId, ids.constructor, paramIdx, paramId, syntheticParameterNames = false, isVararg = false, isNoinline = false, isCrossinline = false) + extractValueParameter(paramId, paramType, paramName, locId, ids.constructor, paramIdx, paramId, syntheticParameterNames = false, isVararg = false, isNoinline = false, isCrossinline = false) - val assignmentStmtId = tw.getFreshIdLabel() - tw.writeStmts_exprstmt(assignmentStmtId, ids.constructorBlock, stmtIdx, ids.constructor) - tw.writeHasLocation(assignmentStmtId, locId) - - val assignmentId = tw.getFreshIdLabel() - tw.writeExprs_assignexpr(assignmentId, paramTypeRes.javaResult.id, assignmentStmtId, 0) - tw.writeExprsKotlinType(assignmentId, paramTypeRes.kotlinResult.id) - writeExpressionMetadataToTrapFile(assignmentId, ids.constructor, assignmentStmtId) - - val lhsId = tw.getFreshIdLabel() - tw.writeExprs_varaccess(lhsId, paramTypeRes.javaResult.id, assignmentId, 0) - tw.writeExprsKotlinType(lhsId, paramTypeRes.kotlinResult.id) - tw.writeVariableBinding(lhsId, fieldId) - writeExpressionMetadataToTrapFile(lhsId, ids.constructor, assignmentStmtId) - - val thisId = tw.getFreshIdLabel() - tw.writeExprs_thisaccess(thisId, ids.type.javaResult.id, lhsId, -1) - tw.writeExprsKotlinType(thisId, ids.type.kotlinResult.id) - writeExpressionMetadataToTrapFile(thisId, ids.constructor, assignmentStmtId) - - val rhsId = tw.getFreshIdLabel() - tw.writeExprs_varaccess(rhsId, paramTypeRes.javaResult.id, assignmentId, 1) - tw.writeExprsKotlinType(rhsId, paramTypeRes.kotlinResult.id) - tw.writeVariableBinding(rhsId, paramId) - writeExpressionMetadataToTrapFile(rhsId, ids.constructor, assignmentStmtId) + extractExpressionStmt(locId, ids.constructorBlock, stmtIdx, ids.constructor).also { assignmentStmtId -> + extractAssignExpr(paramType, locId, assignmentStmtId, 0, ids.constructor, assignmentStmtId).also { assignmentId -> + extractVariableAccess(fieldId, paramType, locId, assignmentId, 0, ids.constructor, assignmentStmtId).also { lhsId -> + extractThisAccess(ids.type, ids.constructor, lhsId, -1, assignmentStmtId, locId) + } + extractVariableAccess(paramId, paramType, locId, assignmentId, 1, ids.constructor, assignmentStmtId) + } + } } } @@ -3695,35 +4007,22 @@ open class KotlinFileExtractor( } protected fun writeThisAccess(parent: Label, callable: Label, stmt: Label) { - val thisId = tw.getFreshIdLabel() - tw.writeExprs_thisaccess(thisId, ids.type.javaResult.id, parent, -1) - tw.writeExprsKotlinType(thisId, ids.type.kotlinResult.id) - writeExpressionMetadataToTrapFile(thisId, callable, stmt) + extractThisAccess(ids.type, callable, parent, -1, stmt, locId) } fun extractFieldWriteOfReflectionTarget( labels: FunctionLabels, // labels of the containing function target: IrFieldSymbol, // the target field being accessed) ) { - // ...; - val exprStmtId = tw.getFreshIdLabel() - tw.writeStmts_exprstmt(exprStmtId, labels.blockId, 0, labels.methodId) - tw.writeHasLocation(exprStmtId, locId) - val fieldType = useType(target.owner.type) - // ... = ... - val assignExprId = tw.getFreshIdLabel() - tw.writeExprs_assignexpr(assignExprId, fieldType.javaResult.id, exprStmtId, 0) - tw.writeExprsKotlinType(assignExprId, fieldType.kotlinResult.id) - writeExpressionMetadataToTrapFile(assignExprId, labels.methodId, exprStmtId) - - // LHS - extractFieldAccess(fieldType, assignExprId, exprStmtId, labels, target) - - // RHS - val p = labels.parameters.first() - writeVariableAccessInFunctionBody(p.second, 1, p.first, assignExprId, labels.methodId, exprStmtId) + extractExpressionStmt(locId, labels.blockId, 0, labels.methodId).also { exprStmtId -> + extractAssignExpr(target.owner.type, locId, exprStmtId, 0, labels.methodId, exprStmtId).also { assignExprId -> + extractFieldAccess(fieldType, assignExprId, exprStmtId, labels, target) + val p = labels.parameters.first() + writeVariableAccessInFunctionBody(p.second, 1, p.first, assignExprId, labels.methodId, exprStmtId) + } + } } fun extractFieldReturnOfReflectionTarget( @@ -4299,12 +4598,7 @@ open class KotlinFileExtractor( addModifiers(methodId, "public") addModifiers(methodId, "override") - // Block - val blockId = tw.getFreshIdLabel() - tw.writeStmts_block(blockId, methodId, 0, methodId) - tw.writeHasLocation(blockId, locId) - - return FunctionLabels(methodId, blockId, parameters) + return FunctionLabels(methodId, extractBlockBody(methodId, locId), parameters) } /* @@ -4346,10 +4640,7 @@ open class KotlinFileExtractor( tw.writeCallableBinding(callId, calledMethodId) // this access - val thisId = tw.getFreshIdLabel() - tw.writeExprs_thisaccess(thisId, ids.type.javaResult.id, callId, -1) - tw.writeExprsKotlinType(thisId, ids.type.kotlinResult.id) - extractCommonExpr(thisId) + extractThisAccess(ids.type, funLabels.methodId, callId, -1, retId, locId) addArgumentsToInvocationInInvokeNBody(parameters.map { it.type }, funLabels, retId, callId, locId, ::extractCommonExpr) } @@ -4611,13 +4902,7 @@ open class KotlinFileExtractor( tw.writeExprsKotlinType(initId, at.kotlinResult.id) extractCommonExpr(initId) - val dim = arraySize.toString() - val dimId = tw.getFreshIdLabel() - val dimType = useType(pluginContext.irBuiltIns.intType) - tw.writeExprs_integerliteral(dimId, dimType.javaResult.id, arrayCreationId, 0) - tw.writeExprsKotlinType(dimId, dimType.kotlinResult.id) - extractCommonExpr(dimId) - tw.writeNamestrings(dim, dim, dimId) + extractConstantInteger(arraySize, locId, arrayCreationId, 0, enclosingCallable, enclosingStmt) return initId } @@ -4731,7 +5016,7 @@ open class KotlinFileExtractor( class extends Object implements IntPredicate { Function1 ; public (Function1 ) { this. = ; } - public Boolean accept(Integer i) { return .invoke(i); } + public override Boolean accept(Integer i) { return .invoke(i); } } IntPredicate x = (IntPredicate)new (...); @@ -4811,14 +5096,13 @@ open class KotlinFileExtractor( // the real underlying R Function.apply(T t). forceExtractFunction(samMember, classId, extractBody = false, extractMethodAndParameterTypeAccesses = true, typeSub, classTypeArgs, overriddenAttributes = OverriddenFunctionAttributes(id = ids.function, sourceLoc = tw.getLocation(e))) + addModifiers(ids.function, "override") if (st.isSuspendFunctionOrKFunction()) { addModifiers(ids.function, "suspend") } //body - val blockId = tw.getFreshIdLabel() - tw.writeStmts_block(blockId, ids.function, 0, ids.function) - tw.writeHasLocation(blockId, locId) + val blockId = extractBlockBody(ids.function, locId) //return stmt val returnId = tw.getFreshIdLabel() @@ -5018,10 +5302,19 @@ open class KotlinFileExtractor( fun peek() = stack.peek() fun findOverriddenAttributes(f: IrFunction) = - stack.firstOrNull { it.first == f } ?.second + stack.lastOrNull { it.first == f } ?.second + + fun findFirst(f: (Pair) -> Boolean) = + stack.findLast(f) } - data class OverriddenFunctionAttributes(val id: Label? = null, val sourceDeclarationId: Label? = null, val sourceLoc: Label? = null, val valueParameters: List? = null) + data class OverriddenFunctionAttributes( + val id: Label? = null, + val sourceDeclarationId: Label? = null, + val sourceLoc: Label? = null, + val valueParameters: List? = null, + val typeParameters: List? = null, + val isStatic: Boolean? = null) private fun peekDeclStackAsDeclarationParent(elementToReportOn: IrElement): IrDeclarationParent? { val trapWriter = tw @@ -5046,5 +5339,6 @@ open class KotlinFileExtractor( DELEGATED_PROPERTY_SETTER(7), JVMSTATIC_PROXY_METHOD(8), JVMOVERLOADS_METHOD(9), + DEFAULT_ARGUMENTS_METHOD(10) } } diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt index 957450474c5..1bd27278da0 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt @@ -411,16 +411,9 @@ open class KotlinUsesExtractor( if (replacedArgsIncludingOuterClasses == null || replacedArgsIncludingOuterClasses.isNotEmpty()) { // If this is a generic type instantiation or a raw type then it has no // source entity, so we need to extract it here - val extractorWithCSource by lazy { this.withFileOfClass(replacedClass) } - - if (!instanceSeenBefore) { - extractorWithCSource.extractClassInstance(replacedClass, replacedArgsIncludingOuterClasses) - } - - if (inReceiverContext && tw.lm.genericSpecialisationsExtracted.add(classLabelResult.classLabel)) { - val supertypeMode = if (replacedArgsIncludingOuterClasses == null) ExtractSupertypesMode.Raw else ExtractSupertypesMode.Specialised(replacedArgsIncludingOuterClasses) - extractorWithCSource.extractClassSupertypes(replacedClass, classLabel, supertypeMode, true) - extractorWithCSource.extractNonPrivateMemberPrototypes(replacedClass, replacedArgsIncludingOuterClasses, classLabel) + val shouldExtractClassDetails = inReceiverContext && tw.lm.genericSpecialisationsExtracted.add(classLabelResult.classLabel) + if (!instanceSeenBefore || shouldExtractClassDetails) { + this.withFileOfClass(replacedClass).extractClassInstance(classLabel, replacedClass, replacedArgsIncludingOuterClasses, !instanceSeenBefore, shouldExtractClassDetails) } } @@ -658,6 +651,26 @@ open class KotlinUsesExtractor( RETURN, GENERIC_ARGUMENT, OTHER } + private fun isOnDeclarationStackWithoutTypeParameters(f: IrFunction) = + this is KotlinFileExtractor && this.declarationStack.findOverriddenAttributes(f)?.typeParameters?.isEmpty() == true + + private fun isStaticFunctionOnStackBeforeClass(c: IrClass) = + this is KotlinFileExtractor && (this.declarationStack.findFirst { it.first == c || it.second?.isStatic == true })?.second?.isStatic == true + + private fun isUnavailableTypeParameter(t: IrType) = + t is IrSimpleType && t.classifier.owner.let { owner -> + owner is IrTypeParameter && owner.parent.let { parent -> + when (parent) { + is IrFunction -> isOnDeclarationStackWithoutTypeParameters(parent) + is IrClass -> isStaticFunctionOnStackBeforeClass(parent) + else -> false + } + } + } + + private fun argIsUnavailableTypeParameter(t: IrTypeArgument) = + t is IrTypeProjection && isUnavailableTypeParameter(t.type) + private fun useSimpleType(s: IrSimpleType, context: TypeContext): TypeResults { if (s.abbreviation != null) { // TODO: Extract this information @@ -729,11 +742,13 @@ open class KotlinUsesExtractor( } owner is IrClass -> { - val args = if (s.isRawType()) null else s.arguments + val args = if (s.isRawType() || s.arguments.any { argIsUnavailableTypeParameter(it) }) null else s.arguments return useSimpleTypeClass(owner, args, s.isNullable()) } owner is IrTypeParameter -> { + if (isUnavailableTypeParameter(s)) + return useType(erase(s), context) val javaResult = useTypeParameter(owner) val aClassId = makeClass("kotlin", "TypeParam") // TODO: Wrong val kotlinResult = if (true) TypeResult(fakeKotlinType(), "TODO", "TODO") else @@ -1043,9 +1058,9 @@ open class KotlinUsesExtractor( f.parent, maybeParentId, getFunctionShortName(f).nameInDB, - maybeParameterList ?: f.valueParameters, + (maybeParameterList ?: f.valueParameters).map { it.type }, getAdjustedReturnType(f), - f.extensionReceiverParameter, + f.extensionReceiverParameter?.type, getFunctionTypeParameters(f), classTypeArgsIncludingOuterClasses, overridesCollectionsMethodWithAlteredParameterTypes(f), @@ -1067,12 +1082,12 @@ open class KotlinUsesExtractor( maybeParentId: Label?, // The name of the function; normally f.name.asString(). name: String, - // The value parameters that the functions takes; normally f.valueParameters. - parameters: List, + // The types of the value parameters that the functions takes; normally f.valueParameters.map { it.type }. + parameterTypes: List, // The return type of the function; normally f.returnType. returnType: IrType, - // The extension receiver of the function, if any; normally f.extensionReceiverParameter. - extensionReceiverParameter: IrValueParameter?, + // The extension receiver of the function, if any; normally f.extensionReceiverParameter?.type. + extensionParamType: IrType?, // The type parameters of the function. This does not include type parameters of enclosing classes. functionTypeParameters: List, // The type arguments of enclosing classes of the function. @@ -1089,11 +1104,7 @@ open class KotlinUsesExtractor( prefix: String = "callable" ): String { val parentId = maybeParentId ?: useDeclarationParent(parent, false, classTypeArgsIncludingOuterClasses, true) - val allParams = if (extensionReceiverParameter == null) { - parameters - } else { - listOf(extensionReceiverParameter) + parameters - } + val allParamTypes = if (extensionParamType == null) parameterTypes else listOf(extensionParamType) + parameterTypes val substitutionMap = classTypeArgsIncludingOuterClasses?.let { notNullArgs -> if (notNullArgs.isEmpty()) { @@ -1103,11 +1114,11 @@ open class KotlinUsesExtractor( enclosingClass?.let { notNullClass -> makeTypeGenericSubstitutionMap(notNullClass, notNullArgs) } } } - val getIdForFunctionLabel = { it: IndexedValue -> + val getIdForFunctionLabel = { it: IndexedValue -> // Kotlin rewrites certain Java collections types adding additional generic constraints-- for example, // Collection.remove(Object) because Collection.remove(Collection::E) in the Kotlin universe. // If this has happened, erase the type again to get the correct Java signature. - val maybeAmendedForCollections = if (overridesCollectionsMethod) eraseCollectionsMethodParameterType(it.value.type, name, it.index) else it.value.type + val maybeAmendedForCollections = if (overridesCollectionsMethod) eraseCollectionsMethodParameterType(it.value, name, it.index) else it.value // Add any wildcard types that the Kotlin compiler would add in the Java lowering of this function: val withAddedWildcards = addJavaLoweringWildcards(maybeAmendedForCollections, addParameterWildcardsByDefault, javaSignature?.let { sig -> getJavaValueParameterType(sig, it.index) }) // Now substitute any class type parameters in: @@ -1117,7 +1128,7 @@ open class KotlinUsesExtractor( val maybeErased = if (functionTypeParameters.isEmpty()) maybeSubbed else erase(maybeSubbed) "{${useType(maybeErased).javaResult.id}}" } - val paramTypeIds = allParams.withIndex().joinToString(separator = ",", transform = getIdForFunctionLabel) + val paramTypeIds = allParamTypes.withIndex().joinToString(separator = ",", transform = getIdForFunctionLabel) val labelReturnType = if (name == "") pluginContext.irBuiltIns.unitType @@ -1551,7 +1562,7 @@ open class KotlinUsesExtractor( * Note that `Array` is retained (with `T` itself erased) because these are expected to be lowered to Java * arrays, which are not generic. */ - private fun erase (t: IrType): IrType { + fun erase (t: IrType): IrType { if (t is IrSimpleType) { val classifier = t.classifier val owner = classifier.owner @@ -1578,6 +1589,8 @@ open class KotlinUsesExtractor( private fun eraseTypeParameter(t: IrTypeParameter) = erase(t.superTypes[0]) + fun getValueParameterLabel(parentId: Label?, idx: Int) = "@\"params;{$parentId};$idx\"" + /** * Gets the label for `vp` in the context of function instance `parent`, or in that of its declaring function if * `parent` is null. @@ -1607,7 +1620,7 @@ open class KotlinUsesExtractor( logger.error("Unexpected negative index for parameter") } - return "@\"params;{$parentId};$idx\"" + return getValueParameterLabel(parentId, idx) } @@ -1669,7 +1682,7 @@ open class KotlinUsesExtractor( val returnType = getter?.returnType ?: setter?.valueParameters?.singleOrNull()?.type ?: pluginContext.irBuiltIns.unitType val typeParams = getFunctionTypeParameters(func) - getFunctionLabel(p.parent, parentId, p.name.asString(), listOf(), returnType, ext, typeParams, classTypeArgsIncludingOuterClasses, overridesCollectionsMethod = false, javaSignature = null, addParameterWildcardsByDefault = false, prefix = "property") + getFunctionLabel(p.parent, parentId, p.name.asString(), listOf(), returnType, ext.type, typeParams, classTypeArgsIncludingOuterClasses, overridesCollectionsMethod = false, javaSignature = null, addParameterWildcardsByDefault = false, prefix = "property") } } diff --git a/java/ql/consistency-queries/visibility.ql b/java/ql/consistency-queries/visibility.ql index 1b6744cea1d..eea402017d5 100644 --- a/java/ql/consistency-queries/visibility.ql +++ b/java/ql/consistency-queries/visibility.ql @@ -10,6 +10,8 @@ string visibility(Method m) { result = "internal" and m.isInternal() } +predicate hasPackagePrivateVisibility(Method m) { not exists(visibility(m)) } + // TODO: This ought to check more than just methods from Method m where @@ -19,5 +21,6 @@ where // TODO: This ought to have visibility information not m.getName() = "" and count(visibility(m)) != 1 and - not (count(visibility(m)) = 2 and visibility(m) = "public" and visibility(m) = "internal") // This is a reasonable result, since the JVM symbol is declared public, but Kotlin metadata flags it as internal + not (count(visibility(m)) = 2 and visibility(m) = "public" and visibility(m) = "internal") and // This is a reasonable result, since the JVM symbol is declared public, but Kotlin metadata flags it as internal + not (hasPackagePrivateVisibility(m) and m.getName().matches("%$default")) // This is a reasonable result because the $default forwarder methods corresponding to private methods are package-private. select m, concat(visibility(m), ", ") diff --git a/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/PrintAst.expected b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/PrintAst.expected index 1d4c7983c61..68363f41329 100644 --- a/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/PrintAst.expected +++ b/java/ql/integration-tests/posix-only/kotlin/gradle_kotlinx_serialization/PrintAst.expected @@ -65,7 +65,48 @@ app/src/main/kotlin/testProject/App.kt: # 0| -3: [TypeAccess] Project # 0| 0: [VarAccess] name # 0| 1: [VarAccess] language -# 0| 5: [Method] equals +# 0| 5: [Method] copy$default +# 0| 3: [TypeAccess] Project +#-----| 4: (Parameters) +# 0| 0: [Parameter] p0 +# 0| 0: [TypeAccess] Project +# 0| 1: [Parameter] p1 +# 0| 0: [TypeAccess] String +# 0| 2: [Parameter] p2 +# 0| 0: [TypeAccess] int +# 0| 3: [Parameter] p3 +# 0| 0: [TypeAccess] int +# 0| 4: [Parameter] p4 +# 0| 0: [TypeAccess] Object +# 0| 5: [BlockStmt] { ... } +# 0| 0: [IfStmt] if (...) +# 0| 0: [EQExpr] ... == ... +# 0| 0: [AndBitwiseExpr] ... & ... +# 0| 0: [IntegerLiteral] 1 +# 0| 1: [VarAccess] p3 +# 0| 1: [IntegerLiteral] 0 +# 0| 1: [ExprStmt] ; +# 0| 0: [AssignExpr] ...=... +# 0| 0: [VarAccess] p1 +# 0| 1: [VarAccess] p0.name +# 0| -1: [VarAccess] p0 +# 0| 1: [IfStmt] if (...) +# 0| 0: [EQExpr] ... == ... +# 0| 0: [AndBitwiseExpr] ... & ... +# 0| 0: [IntegerLiteral] 2 +# 0| 1: [VarAccess] p3 +# 0| 1: [IntegerLiteral] 0 +# 0| 1: [ExprStmt] ; +# 0| 0: [AssignExpr] ...=... +# 0| 0: [VarAccess] p2 +# 0| 1: [VarAccess] p0.language +# 0| -1: [VarAccess] p0 +# 0| 2: [ReturnStmt] return ... +# 0| 0: [MethodAccess] copy(...) +# 0| -1: [VarAccess] p0 +# 0| 0: [VarAccess] p1 +# 0| 1: [VarAccess] p2 +# 0| 6: [Method] equals # 0| 3: [TypeAccess] boolean #-----| 4: (Parameters) # 0| 0: [Parameter] other @@ -114,7 +155,7 @@ app/src/main/kotlin/testProject/App.kt: # 0| 0: [BooleanLiteral] false # 0| 5: [ReturnStmt] return ... # 0| 0: [BooleanLiteral] true -# 0| 6: [Method] hashCode +# 0| 7: [Method] hashCode # 0| 3: [TypeAccess] int # 0| 5: [BlockStmt] { ... } # 0| 0: [LocalVariableDeclStmt] var ...; @@ -134,7 +175,7 @@ app/src/main/kotlin/testProject/App.kt: # 0| -1: [ThisAccess] this # 0| 2: [ReturnStmt] return ... # 0| 0: [VarAccess] result -# 0| 7: [Method] toString +# 0| 8: [Method] toString # 0| 3: [TypeAccess] String # 0| 5: [BlockStmt] { ... } # 0| 0: [ReturnStmt] return ... @@ -148,7 +189,7 @@ app/src/main/kotlin/testProject/App.kt: # 0| 5: [VarAccess] this.language # 0| -1: [ThisAccess] this # 0| 6: [StringLiteral] ) -# 0| 8: [Method] write$Self +# 0| 9: [Method] write$Self # 0| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 0| 0: [Parameter] self @@ -172,7 +213,7 @@ app/src/main/kotlin/testProject/App.kt: # 7| 1: [IntegerLiteral] 1 # 7| 2: [MethodAccess] getLanguage(...) # 7| -1: [VarAccess] self -# 7| 9: [Class] $serializer +# 7| 10: [Class] $serializer # 0| 1: [FieldDeclaration] SerialDescriptor descriptor; # 0| -1: [TypeAccess] SerialDescriptor # 0| 2: [Method] childSerializers @@ -384,7 +425,7 @@ app/src/main/kotlin/testProject/App.kt: # 7| -1: [ThisAccess] $serializer.this # 7| 0: [TypeAccess] $serializer # 7| 1: [VarAccess] tmp0_serialDesc -# 7| 10: [Class] Companion +# 7| 11: [Class] Companion # 0| 1: [Method] serializer # 0| 3: [TypeAccess] KSerializer # 0| 0: [TypeAccess] Project @@ -395,7 +436,7 @@ app/src/main/kotlin/testProject/App.kt: # 7| 5: [BlockStmt] { ... } # 7| 0: [SuperConstructorInvocationStmt] super(...) # 7| 1: [BlockStmt] { ... } -# 8| 11: [Constructor] Project +# 8| 12: [Constructor] Project #-----| 4: (Parameters) # 8| 0: [Parameter] name # 8| 0: [TypeAccess] String @@ -410,21 +451,21 @@ app/src/main/kotlin/testProject/App.kt: # 8| 1: [ExprStmt] ; # 8| 0: [KtInitializerAssignExpr] ...=... # 8| 0: [VarAccess] language -# 8| 12: [FieldDeclaration] String name; +# 8| 13: [FieldDeclaration] String name; # 8| -1: [TypeAccess] String # 8| 0: [VarAccess] name -# 8| 13: [Method] getName +# 8| 14: [Method] getName # 8| 3: [TypeAccess] String # 8| 5: [BlockStmt] { ... } # 8| 0: [ReturnStmt] return ... # 8| 0: [VarAccess] this.name # 8| -1: [ThisAccess] this -# 8| 14: [Method] getLanguage +# 8| 15: [Method] getLanguage # 8| 3: [TypeAccess] int # 8| 5: [BlockStmt] { ... } # 8| 0: [ReturnStmt] return ... # 8| 0: [VarAccess] this.language # 8| -1: [ThisAccess] this -# 8| 15: [FieldDeclaration] int language; +# 8| 16: [FieldDeclaration] int language; # 8| -1: [TypeAccess] int # 8| 0: [VarAccess] language diff --git a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/User.java b/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/User.java deleted file mode 100644 index a5bc5ccfeee..00000000000 --- a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/User.java +++ /dev/null @@ -1,39 +0,0 @@ -public class User { - - public static String source() { return "taint"; } - - public static void test(Test2 t2, GenericTest gt) { - - Test.taintSuppliedAsDefault(1, "no taint", 2); - Test.taintSuppliedAsDefault(1, 2); - Test.noTaintByDefault(1, source(), 2, 3); - Test.noTaintByDefault(1, source(), 2); - - Test2.taintSuppliedAsDefaultStatic(1, "no taint", 2); - Test2.taintSuppliedAsDefaultStatic(1, 2); - Test2.noTaintByDefaultStatic(1, source(), 2, 3); - Test2.noTaintByDefaultStatic(1, source(), 2); - - t2.taintSuppliedAsDefault(1, "no taint", 2); - t2.taintSuppliedAsDefault(1, 2); - t2.noTaintByDefault(1, source(), 2, 3); - t2.noTaintByDefault(1, source(), 2); - - gt.taintSuppliedAsDefault(1, "no taint", 2); - gt.taintSuppliedAsDefault(1, 2); - gt.noTaintByDefault(1, source(), 2, 3); - gt.noTaintByDefault(1, source(), 2); - - new ConstructorTaintsByDefault(1, "no taint", 2); - new ConstructorTaintsByDefault(1, 2); - new ConstructorDoesNotTaintByDefault(1, source(), 2, 3); - new ConstructorDoesNotTaintByDefault(1, source(), 2); - - new GenericConstructorTaintsByDefault(1, "no taint", 2); - new GenericConstructorTaintsByDefault(1, 2); - new GenericConstructorDoesNotTaintByDefault(1, source(), 2, 3); - new GenericConstructorDoesNotTaintByDefault(1, source(), 2); - - } - -} diff --git a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.expected b/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.expected deleted file mode 100644 index 6d9ee0d2718..00000000000 --- a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.expected +++ /dev/null @@ -1,19 +0,0 @@ -| User.java:9:30:9:37 | source(...) | test.kt:13:97:13:97 | s | -| User.java:10:30:10:37 | source(...) | test.kt:13:97:13:97 | s | -| User.java:14:37:14:44 | source(...) | test.kt:25:105:25:105 | s | -| User.java:15:37:15:44 | source(...) | test.kt:25:105:25:105 | s | -| User.java:19:28:19:35 | source(...) | test.kt:33:97:33:97 | s | -| User.java:20:28:20:35 | source(...) | test.kt:33:97:33:97 | s | -| User.java:24:28:24:35 | source(...) | test.kt:43:93:43:93 | s | -| User.java:25:28:25:35 | source(...) | test.kt:43:93:43:93 | s | -| User.java:29:45:29:52 | source(...) | test.kt:58:10:58:10 | s | -| User.java:30:45:30:52 | source(...) | test.kt:58:10:58:10 | s | -| User.java:34:61:34:68 | source(...) | test.kt:74:10:74:10 | s | -| User.java:35:61:35:68 | source(...) | test.kt:74:10:74:10 | s | -| test.kt:10:55:10:62 | source(...) | test.kt:10:84:10:84 | s | -| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | -| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | -| test.kt:30:55:30:62 | source(...) | test.kt:30:84:30:84 | s | -| test.kt:40:53:40:60 | source(...) | test.kt:40:80:40:80 | s | -| test.kt:47:92:47:99 | source(...) | test.kt:50:10:50:10 | s | -| test.kt:63:100:63:107 | source(...) | test.kt:66:10:66:10 | s | diff --git a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.kt b/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.kt deleted file mode 100644 index a0e43a6717d..00000000000 --- a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.kt +++ /dev/null @@ -1,78 +0,0 @@ -fun getString() = "Hello world" - -fun source() = "tainted" - -fun sink(s: String) { } - -object Test { - - @JvmOverloads @JvmStatic - fun taintSuppliedAsDefault(before: Int, s: String = source(), after: Int) { sink(s) } - - @JvmOverloads @JvmStatic - fun noTaintByDefault(before: Int, s: String = "no taint", after: Int, after2: Int = 1) { sink(s) } - -} - -public class Test2 { - - companion object { - - @JvmOverloads @JvmStatic - fun taintSuppliedAsDefaultStatic(before: Int, s: String = source(), after: Int) { sink(s) } - - @JvmOverloads @JvmStatic - fun noTaintByDefaultStatic(before: Int, s: String = "no taint", after: Int, after2: Int = 1) { sink(s) } - - } - - @JvmOverloads - fun taintSuppliedAsDefault(before: Int, s: String = source(), after: Int) { sink(s) } - - @JvmOverloads - fun noTaintByDefault(before: Int, s: String = "no taint", after: Int, after2: Int = 1) { sink(s) } - -} - -public class GenericTest { - - @JvmOverloads - fun taintSuppliedAsDefault(before: T, s: String = source(), after: T) { sink(s) } - - @JvmOverloads - fun noTaintByDefault(before: T, s: String = "no taint", after: T, after2: Int = 1) { sink(s) } - -} - -public class ConstructorTaintsByDefault @JvmOverloads constructor(before: Int, s: String = source(), after: Int) { - - init { - sink(s) - } - -} - -public class ConstructorDoesNotTaintByDefault @JvmOverloads constructor(before: Int, s: String = "no taint", after: Int, after2: Int = 1) { - - init { - sink(s) - } - -} - -public class GenericConstructorTaintsByDefault @JvmOverloads constructor(before: T, s: String = source(), after: T) { - - init { - sink(s) - } - -} - -public class GenericConstructorDoesNotTaintByDefault @JvmOverloads constructor(before: T, s: String = "no taint", after: T, after2: T? = null) { - - init { - sink(s) - } - -} - diff --git a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.py b/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.py deleted file mode 100644 index 507cd38a68c..00000000000 --- a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.py +++ /dev/null @@ -1,4 +0,0 @@ -from create_database_utils import * - -os.mkdir('kbuild') -run_codeql_database_create(["kotlinc test.kt -d kbuild", "javac User.java -cp kbuild"], lang="java") diff --git a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.ql b/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.ql deleted file mode 100644 index 4ed01f80da8..00000000000 --- a/java/ql/integration-tests/posix-only/kotlin/jvmoverloads_flow/test.ql +++ /dev/null @@ -1,18 +0,0 @@ -import java -import semmle.code.java.dataflow.DataFlow - -class Config extends DataFlow::Configuration { - Config() { this = "config" } - - override predicate isSource(DataFlow::Node n) { - n.asExpr().(MethodAccess).getCallee().getName() = "source" - } - - override predicate isSink(DataFlow::Node n) { - n.asExpr().(Argument).getCall().getCallee().getName() = "sink" - } -} - -from Config c, DataFlow::Node source, DataFlow::Node sink -where c.hasFlow(source, sink) -select source, sink diff --git a/java/ql/lib/CHANGELOG.md b/java/ql/lib/CHANGELOG.md index 0f9512eabda..2724a6d3cef 100644 --- a/java/ql/lib/CHANGELOG.md +++ b/java/ql/lib/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.4.1 + +### Minor Analysis Improvements + +* Added external flow sources for the intents received in exported Android services. + ## 0.4.0 ### Breaking Changes diff --git a/java/ql/lib/change-notes/2022-09-22-android-deeplink-flow-steps.md b/java/ql/lib/change-notes/2022-09-22-android-deeplink-flow-steps.md new file mode 100644 index 00000000000..1ed229b1e05 --- /dev/null +++ b/java/ql/lib/change-notes/2022-09-22-android-deeplink-flow-steps.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- +* Added data flow steps for tainted Android intents that are sent to services and receivers. +* Improved the data flow step for tainted Android intents that are sent to activities so that more cases are covered. diff --git a/java/ql/lib/change-notes/2022-09-22-android-deprecate-contextstartactivitymethod.md b/java/ql/lib/change-notes/2022-09-22-android-deprecate-contextstartactivitymethod.md new file mode 100644 index 00000000000..3500322afad --- /dev/null +++ b/java/ql/lib/change-notes/2022-09-22-android-deprecate-contextstartactivitymethod.md @@ -0,0 +1,4 @@ +--- +category: deprecated +--- +* Deprecated `ContextStartActivityMethod`. Use `StartActivityMethod` instead. diff --git a/java/ql/lib/change-notes/2022-09-23-android-service-sources.md b/java/ql/lib/change-notes/released/0.4.1.md similarity index 66% rename from java/ql/lib/change-notes/2022-09-23-android-service-sources.md rename to java/ql/lib/change-notes/released/0.4.1.md index 812ff07422d..866a6cf524b 100644 --- a/java/ql/lib/change-notes/2022-09-23-android-service-sources.md +++ b/java/ql/lib/change-notes/released/0.4.1.md @@ -1,4 +1,5 @@ ---- -category: minorAnalysis ---- +## 0.4.1 + +### Minor Analysis Improvements + * Added external flow sources for the intents received in exported Android services. diff --git a/java/ql/lib/codeql-pack.release.yml b/java/ql/lib/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/java/ql/lib/codeql-pack.release.yml +++ b/java/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index df1ad196123..fc774265862 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-all -version: 0.4.1-dev +version: 0.4.2-dev groups: java dbscheme: config/semmlecode.dbscheme extractor: java diff --git a/java/ql/lib/semmle/code/java/Element.qll b/java/ql/lib/semmle/code/java/Element.qll index d2cbfbc120e..0120cdc158f 100644 --- a/java/ql/lib/semmle/code/java/Element.qll +++ b/java/ql/lib/semmle/code/java/Element.qll @@ -65,6 +65,8 @@ class Element extends @element, Top { i = 8 and result = "Proxy static method for a @JvmStatic-annotated function or property" or i = 9 and result = "Forwarder for a @JvmOverloads-annotated function" + or + i = 10 and result = "Forwarder for Kotlin calls that need default arguments filling in" ) } } diff --git a/java/ql/lib/semmle/code/java/GeneratedFiles.qll b/java/ql/lib/semmle/code/java/GeneratedFiles.qll index a7d1ae628f0..79197653848 100644 --- a/java/ql/lib/semmle/code/java/GeneratedFiles.qll +++ b/java/ql/lib/semmle/code/java/GeneratedFiles.qll @@ -51,9 +51,9 @@ library class MarkerCommentGeneratedFile extends GeneratedFile { /** * A marker comment that indicates that it is in a generated file. */ -private class GeneratedFileMarker extends Top instanceof JavadocElement { +private class GeneratedFileMarker extends Top { GeneratedFileMarker() { - exists(string msg | msg = this.getText() | + exists(string msg | msg = this.(JavadocElement).getText() or msg = this.(KtComment).getText() | msg.regexpMatch("(?i).*\\bGenerated By\\b.*\\bDo not edit\\b.*") or msg.regexpMatch("(?i).*\\bThis (file|class|interface|art[ei]fact) (was|is|(has been)) (?:auto[ -]?)?gener(e?)ated.*") or msg.regexpMatch("(?i).*\\bAny modifications to this file will be lost\\b.*") or 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll index ad260c9545c..be38b83e5a7 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll @@ -3,9 +3,7 @@ private import semmle.code.java.dataflow.DataFlow private import semmle.code.java.dataflow.ExternalFlow private import semmle.code.java.dataflow.FlowSteps -/** - * The class `android.content.Intent`. - */ +/** The class `android.content.Intent`. */ class TypeIntent extends Class { TypeIntent() { this.hasQualifiedName("android.content", "Intent") } } @@ -15,23 +13,17 @@ class TypeComponentName extends Class { TypeComponentName() { this.hasQualifiedName("android.content", "ComponentName") } } -/** - * The class `android.app.Activity`. - */ +/** The class `android.app.Activity`. */ class TypeActivity extends Class { TypeActivity() { this.hasQualifiedName("android.app", "Activity") } } -/** - * The class `android.app.Service`. - */ +/** The class `android.app.Service`. */ class TypeService extends Class { TypeService() { this.hasQualifiedName("android.app", "Service") } } -/** - * The class `android.content.Context`. - */ +/** The class `android.content.Context`. */ class TypeContext extends RefType { // Not inlining this makes it more likely to be used as a sentinel, // which is useful when running Android queries on non-Android projects. @@ -39,25 +31,19 @@ class TypeContext extends RefType { TypeContext() { this.hasQualifiedName("android.content", "Context") } } -/** - * The class `android.content.BroadcastReceiver`. - */ +/** The class `android.content.BroadcastReceiver`. */ class TypeBroadcastReceiver extends Class { TypeBroadcastReceiver() { this.hasQualifiedName("android.content", "BroadcastReceiver") } } -/** - * The method `Activity.getIntent` - */ +/** The method `Activity.getIntent` */ class AndroidGetIntentMethod extends Method { AndroidGetIntentMethod() { this.hasName("getIntent") and this.getDeclaringType() instanceof TypeActivity } } -/** - * The method `BroadcastReceiver.onReceive`. - */ +/** The method `BroadcastReceiver.onReceive`. */ class AndroidReceiveIntentMethod extends Method { AndroidReceiveIntentMethod() { this.hasName("onReceive") and this.getDeclaringType() instanceof TypeBroadcastReceiver @@ -77,8 +63,10 @@ class AndroidServiceIntentMethod extends Method { /** * The method `Context.startActivity` or `startActivities`. + * + * DEPRECATED: Use `StartActivityMethod` instead. */ -class ContextStartActivityMethod extends Method { +deprecated class ContextStartActivityMethod extends Method { ContextStartActivityMethod() { (this.hasName("startActivity") or this.hasName("startActivities")) and this.getDeclaringType() instanceof TypeContext @@ -86,16 +74,57 @@ class ContextStartActivityMethod extends Method { } /** - * Specifies that if an `Intent` is tainted, then so are its synthetic fields. + * The method `Context.startActivity`, `Context.startActivities`, + * `Activity.startActivity`,`Activity.startActivities`, + * `Activity.startActivityForResult`, `Activity.startActivityIfNeeded`, + * `Activity.startNextMatchingActivity`, `Activity.startActivityFromChild`, + * or `Activity.startActivityFromFragment`. */ +class StartActivityMethod extends Method { + StartActivityMethod() { + this.getName().matches("start%Activit%") and + ( + this.getDeclaringType() instanceof TypeContext or + this.getDeclaringType() instanceof TypeActivity + ) + } +} + +/** + * The method `Context.sendBroadcast`, `sendBroadcastAsUser`, + * `sendOrderedBroadcast`, `sendOrderedBroadcastAsUser`, + * `sendStickyBroadcast`, `sendStickyBroadcastAsUser`, + * `sendStickyOrderedBroadcast`, `sendStickyOrderedBroadcastAsUser`, + * or `sendBroadcastWithMultiplePermissions`. + */ +class SendBroadcastMethod extends Method { + SendBroadcastMethod() { + this.getName().matches("send%Broadcast%") and + this.getDeclaringType() instanceof TypeContext + } +} + +/** + * The method `Context.startService`, `startForegroundService`, + * `bindIsolatedService`, `bindService`, or `bindServiceAsUser`. + */ +class StartServiceMethod extends Method { + StartServiceMethod() { + this.hasName([ + "startService", "startForegroundService", "bindIsolatedService", "bindService", + "bindServiceAsUser" + ]) and + this.getDeclaringType() instanceof TypeContext + } +} + +/** Specifies that if an `Intent` is tainted, then so are its synthetic fields. */ private class IntentFieldsInheritTaint extends DataFlow::SyntheticFieldContent, TaintInheritingContent { IntentFieldsInheritTaint() { this.getField().matches("android.content.Intent.%") } } -/** - * The method `Intent.getParcelableExtra`. - */ +/** The method `Intent.getParcelableExtra`. */ class IntentGetParcelableExtraMethod extends Method { IntentGetParcelableExtraMethod() { this.hasName("getParcelableExtra") and @@ -157,9 +186,7 @@ private class BundleExtrasSyntheticField extends SyntheticField { override RefType getType() { result instanceof AndroidBundle } } -/** - * Holds if extras may be implicitly read from the Intent `node`. - */ +/** Holds if extras may be implicitly read from the Intent `node`. */ predicate allowIntentExtrasImplicitRead(DataFlow::Node node, DataFlow::Content c) { node.getType() instanceof TypeIntent and ( @@ -194,25 +221,90 @@ class GrantWriteUriPermissionFlag extends GrantUriPermissionFlag { GrantWriteUriPermissionFlag() { this.hasName("FLAG_GRANT_WRITE_URI_PERMISSION") } } +/** An instantiation of `android.content.Intent`. */ +private class NewIntent extends ClassInstanceExpr { + NewIntent() { this.getConstructedType() instanceof TypeIntent } + + /** Gets the `Class` argument of this call. */ + Argument getClassArg() { + result.getType() instanceof TypeClass and + result = this.getAnArgument() + } +} + +/** A call to a method that starts an Android component. */ +private class StartComponentMethodAccess extends MethodAccess { + StartComponentMethodAccess() { + this.getMethod().overrides*(any(StartActivityMethod m)) or + this.getMethod().overrides*(any(StartServiceMethod m)) or + this.getMethod().overrides*(any(SendBroadcastMethod m)) + } + + /** Gets the intent argument of this call. */ + Argument getIntentArg() { + result.getType() instanceof TypeIntent and + result = this.getAnArgument() + } + + /** Holds if this targets a component of type `targetType`. */ + predicate targetsComponentType(RefType targetType) { + exists(NewIntent newIntent | + DataFlow::localExprFlow(newIntent, this.getIntentArg()) and + newIntent.getClassArg().getType().(ParameterizedType).getATypeArgument() = targetType + ) + } +} + /** - * A value-preserving step from the Intent argument of a `startActivity` call to - * a `getIntent` call in the Activity the Intent pointed to in its constructor. + * A value-preserving step from the intent argument of a `startActivity` call to + * a `getIntent` call in the activity the intent targeted in its constructor. */ private class StartActivityIntentStep extends AdditionalValueStep { override predicate step(DataFlow::Node n1, DataFlow::Node n2) { - exists(MethodAccess startActivity, MethodAccess getIntent, ClassInstanceExpr newIntent | - startActivity.getMethod().overrides*(any(ContextStartActivityMethod m)) and + exists(StartComponentMethodAccess startActivity, MethodAccess getIntent | + startActivity.getMethod().overrides*(any(StartActivityMethod m)) and getIntent.getMethod().overrides*(any(AndroidGetIntentMethod m)) and - newIntent.getConstructedType() instanceof TypeIntent and - DataFlow::localExprFlow(newIntent, startActivity.getArgument(0)) and - newIntent.getArgument(1).getType().(ParameterizedType).getATypeArgument() = - getIntent.getReceiverType() and - n1.asExpr() = startActivity.getArgument(0) and + startActivity.targetsComponentType(getIntent.getReceiverType()) and + n1.asExpr() = startActivity.getIntentArg() and n2.asExpr() = getIntent ) } } +/** + * A value-preserving step from the intent argument of a `sendBroadcast` call to + * the intent parameter in the `onReceive` method of the receiver the + * intent targeted in its constructor. + */ +private class SendBroadcastReceiverIntentStep extends AdditionalValueStep { + override predicate step(DataFlow::Node n1, DataFlow::Node n2) { + exists(StartComponentMethodAccess sendBroadcast, Method onReceive | + sendBroadcast.getMethod().overrides*(any(SendBroadcastMethod m)) and + onReceive.overrides*(any(AndroidReceiveIntentMethod m)) and + sendBroadcast.targetsComponentType(onReceive.getDeclaringType()) and + n1.asExpr() = sendBroadcast.getIntentArg() and + n2.asParameter() = onReceive.getParameter(1) + ) + } +} + +/** + * A value-preserving step from the intent argument of a `startService` call to + * the intent parameter in an `AndroidServiceIntentMethod` of the service the + * intent targeted in its constructor. + */ +private class StartServiceIntentStep extends AdditionalValueStep { + override predicate step(DataFlow::Node n1, DataFlow::Node n2) { + exists(StartComponentMethodAccess startService, Method serviceIntent | + startService.getMethod().overrides*(any(StartServiceMethod m)) and + serviceIntent.overrides*(any(AndroidServiceIntentMethod m)) and + startService.targetsComponentType(serviceIntent.getDeclaringType()) and + n1.asExpr() = startService.getIntentArg() and + n2.asParameter() = serviceIntent.getParameter(0) + ) + } +} + private class IntentBundleFlowSteps extends SummaryModelCsv { override predicate row(string row) { row = diff --git a/java/ql/src/CHANGELOG.md b/java/ql/src/CHANGELOG.md index 4f6633176f4..055d1327b06 100644 --- a/java/ql/src/CHANGELOG.md +++ b/java/ql/src/CHANGELOG.md @@ -1,3 +1,15 @@ +## 0.4.1 + +### New Queries + +* Added a new query, `java/android/webview-debugging-enabled`, to detect instances of WebView debugging being enabled in production builds. + +### Minor Analysis Improvements + +* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. +* `PathSanitizer.qll` has been promoted from experimental to the main query pack. This sanitizer was originally [submitted as part of an experimental query by @luchua-bc](https://github.com/github/codeql/pull/7286). +* The queries `java/path-injection`, `java/path-injection-local` and `java/zipslip` now use the sanitizers provided by `PathSanitizer.qll`. + ## 0.4.0 ### New Queries diff --git a/java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql b/java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql index 999edaa0b38..1f05298878a 100644 --- a/java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql +++ b/java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql @@ -30,6 +30,8 @@ predicate hasTypeTest(Variable v) { or any(SafeCastExpr sce).getExpr() = v.getAnAccess() or + any(ClassExpr c).getExpr() = v.getAnAccess() + or exists(MethodAccess ma | ma.getMethod().getName() = "getClass" and ma.getQualifier() = v.getAnAccess() diff --git a/java/ql/src/Violations of Best Practice/Implementation Hiding/ExposeRepresentation.ql b/java/ql/src/Violations of Best Practice/Implementation Hiding/ExposeRepresentation.ql index 8fe3d4e6ba6..9f24744fa0c 100644 --- a/java/ql/src/Violations of Best Practice/Implementation Hiding/ExposeRepresentation.ql +++ b/java/ql/src/Violations of Best Practice/Implementation Hiding/ExposeRepresentation.ql @@ -120,8 +120,12 @@ predicate exposesByStore(Callable c, Field f, Expr why, string whyText) { from Callable c, Field f, Expr why, string whyText where - exposesByReturn(c, f, why, whyText) or - exposesByStore(c, f, why, whyText) + ( + exposesByReturn(c, f, why, whyText) or + exposesByStore(c, f, why, whyText) + ) and + // Kotlin properties expose internal representation, but it's not accidental, so ignore them + not exists(Property p | p.getBackingField() = f) select c, c.getName() + " exposes the internal representation stored in field " + f.getName() + ". The value may be modified $@.", why.getLocation(), whyText diff --git a/java/ql/src/change-notes/2022-08-25-path-sanitizer.md b/java/ql/src/change-notes/2022-08-25-path-sanitizer.md deleted file mode 100644 index a883561d59c..00000000000 --- a/java/ql/src/change-notes/2022-08-25-path-sanitizer.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -category: minorAnalysis ---- - -* `PathSanitizer.qll` has been promoted from experimental to the main query pack. This sanitizer was originally [submitted as part of an experimental query by @luchua-bc](https://github.com/github/codeql/pull/7286). -* The queries `java/path-injection`, `java/path-injection-local` and `java/zipslip` now use the sanitizers provided by `PathSanitizer.qll`. \ No newline at end of file diff --git a/java/ql/src/change-notes/2022-08-31-webview-dubugging.md b/java/ql/src/change-notes/2022-08-31-webview-dubugging.md deleted file mode 100644 index 8e6295efeb3..00000000000 --- a/java/ql/src/change-notes/2022-08-31-webview-dubugging.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: newQuery ---- -* Added a new query, `java/android/webview-debugging-enabled`, to detect instances of WebView debugging being enabled in production builds. \ No newline at end of file diff --git a/java/ql/src/change-notes/released/0.4.1.md b/java/ql/src/change-notes/released/0.4.1.md new file mode 100644 index 00000000000..0ac482407a7 --- /dev/null +++ b/java/ql/src/change-notes/released/0.4.1.md @@ -0,0 +1,11 @@ +## 0.4.1 + +### New Queries + +* Added a new query, `java/android/webview-debugging-enabled`, to detect instances of WebView debugging being enabled in production builds. + +### Minor Analysis Improvements + +* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. +* `PathSanitizer.qll` has been promoted from experimental to the main query pack. This sanitizer was originally [submitted as part of an experimental query by @luchua-bc](https://github.com/github/codeql/pull/7286). +* The queries `java/path-injection`, `java/path-injection-local` and `java/zipslip` now use the sanitizers provided by `PathSanitizer.qll`. diff --git a/java/ql/src/codeql-pack.release.yml b/java/ql/src/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/java/ql/src/codeql-pack.release.yml +++ b/java/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml index 5f93a953ea6..d74415382a4 100644 --- a/java/ql/src/qlpack.yml +++ b/java/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-queries -version: 0.4.1-dev +version: 0.4.2-dev groups: - java - queries diff --git a/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.expected b/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.expected new file mode 100644 index 00000000000..6b4abd0e1a4 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.expected @@ -0,0 +1 @@ +| Generated.kt:0:0:0:0 | Generated | diff --git a/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.kt b/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.kt new file mode 100644 index 00000000000..4aa496a1b7d --- /dev/null +++ b/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.kt @@ -0,0 +1,3 @@ +// This file was auto generated by me + +class B \ No newline at end of file diff --git a/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.ql b/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.ql new file mode 100644 index 00000000000..131acde1993 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/GeneratedFiles/Generated.ql @@ -0,0 +1,4 @@ +import java + +from GeneratedFile f +select f diff --git a/java/ql/test/kotlin/library-tests/GeneratedFiles/NonGenerated.kt b/java/ql/test/kotlin/library-tests/GeneratedFiles/NonGenerated.kt new file mode 100644 index 00000000000..4fd8af3f7a3 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/GeneratedFiles/NonGenerated.kt @@ -0,0 +1,3 @@ +// This file was not generated + +class A \ No newline at end of file diff --git a/java/ql/test/kotlin/library-tests/data-classes/PrintAst.expected b/java/ql/test/kotlin/library-tests/data-classes/PrintAst.expected index b850cf492e7..d52888544dc 100644 --- a/java/ql/test/kotlin/library-tests/data-classes/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/data-classes/PrintAst.expected @@ -28,7 +28,48 @@ dc.kt: # 0| -3: [TypeAccess] ProtoMapValue # 0| 0: [VarAccess] bytes # 0| 1: [VarAccess] strs -# 0| 4: [Method] equals +# 0| 4: [Method] copy$default +# 0| 3: [TypeAccess] ProtoMapValue +#-----| 4: (Parameters) +# 0| 0: [Parameter] p0 +# 0| 0: [TypeAccess] ProtoMapValue +# 0| 1: [Parameter] p1 +# 0| 0: [TypeAccess] byte[] +# 0| 2: [Parameter] p2 +# 0| 0: [TypeAccess] String[] +# 0| 3: [Parameter] p3 +# 0| 0: [TypeAccess] int +# 0| 4: [Parameter] p4 +# 0| 0: [TypeAccess] Object +# 0| 5: [BlockStmt] { ... } +# 0| 0: [IfStmt] if (...) +# 0| 0: [EQExpr] ... == ... +# 0| 0: [AndBitwiseExpr] ... & ... +# 0| 0: [IntegerLiteral] 1 +# 0| 1: [VarAccess] p3 +# 0| 1: [IntegerLiteral] 0 +# 0| 1: [ExprStmt] ; +# 0| 0: [AssignExpr] ...=... +# 0| 0: [VarAccess] p1 +# 0| 1: [VarAccess] p0.bytes +# 0| -1: [VarAccess] p0 +# 0| 1: [IfStmt] if (...) +# 0| 0: [EQExpr] ... == ... +# 0| 0: [AndBitwiseExpr] ... & ... +# 0| 0: [IntegerLiteral] 2 +# 0| 1: [VarAccess] p3 +# 0| 1: [IntegerLiteral] 0 +# 0| 1: [ExprStmt] ; +# 0| 0: [AssignExpr] ...=... +# 0| 0: [VarAccess] p2 +# 0| 1: [VarAccess] p0.strs +# 0| -1: [VarAccess] p0 +# 0| 2: [ReturnStmt] return ... +# 0| 0: [MethodAccess] copy(...) +# 0| -1: [VarAccess] p0 +# 0| 0: [VarAccess] p1 +# 0| 1: [VarAccess] p2 +# 0| 5: [Method] equals # 0| 3: [TypeAccess] boolean #-----| 4: (Parameters) # 0| 0: [Parameter] other @@ -77,7 +118,7 @@ dc.kt: # 0| 0: [BooleanLiteral] false # 0| 5: [ReturnStmt] return ... # 0| 0: [BooleanLiteral] true -# 0| 5: [Method] hashCode +# 0| 6: [Method] hashCode # 0| 3: [TypeAccess] int # 0| 5: [BlockStmt] { ... } # 0| 0: [LocalVariableDeclStmt] var ...; @@ -99,7 +140,7 @@ dc.kt: # 0| -1: [ThisAccess] this # 0| 2: [ReturnStmt] return ... # 0| 0: [VarAccess] result -# 0| 6: [Method] toString +# 0| 7: [Method] toString # 0| 3: [TypeAccess] String # 0| 5: [BlockStmt] { ... } # 0| 0: [ReturnStmt] return ... @@ -117,7 +158,7 @@ dc.kt: # 0| 0: [VarAccess] this.strs # 0| -1: [ThisAccess] this # 0| 6: [StringLiteral] ) -# 1| 7: [Constructor] ProtoMapValue +# 1| 8: [Constructor] ProtoMapValue #-----| 4: (Parameters) # 1| 0: [Parameter] bytes # 1| 0: [TypeAccess] byte[] @@ -133,20 +174,20 @@ dc.kt: # 1| 1: [ExprStmt] ; # 1| 0: [KtInitializerAssignExpr] ...=... # 1| 0: [VarAccess] strs -# 1| 8: [FieldDeclaration] byte[] bytes; +# 1| 9: [FieldDeclaration] byte[] bytes; # 1| -1: [TypeAccess] byte[] # 1| 0: [VarAccess] bytes -# 1| 9: [Method] getBytes +# 1| 10: [Method] getBytes # 1| 3: [TypeAccess] byte[] # 1| 5: [BlockStmt] { ... } # 1| 0: [ReturnStmt] return ... # 1| 0: [VarAccess] this.bytes # 1| -1: [ThisAccess] this -# 1| 10: [FieldDeclaration] String[] strs; +# 1| 11: [FieldDeclaration] String[] strs; # 1| -1: [TypeAccess] String[] # 1| 0: [TypeAccess] String # 1| 0: [VarAccess] strs -# 1| 11: [Method] getStrs +# 1| 12: [Method] getStrs # 1| 3: [TypeAccess] String[] # 1| 0: [TypeAccess] String # 1| 5: [BlockStmt] { ... } diff --git a/java/ql/test/kotlin/library-tests/data-classes/callees.expected b/java/ql/test/kotlin/library-tests/data-classes/callees.expected index 7e7250a1d18..f16c4ffb435 100644 --- a/java/ql/test/kotlin/library-tests/data-classes/callees.expected +++ b/java/ql/test/kotlin/library-tests/data-classes/callees.expected @@ -1,3 +1,4 @@ +| dc.kt:0:0:0:0 | copy(...) | ProtoMapValue.copy | | dc.kt:0:0:0:0 | hashCode(...) | java.util.Arrays.hashCode | | dc.kt:0:0:0:0 | hashCode(...) | java.util.Arrays.hashCode | | dc.kt:0:0:0:0 | new ProtoMapValue(...) | ProtoMapValue.ProtoMapValue | diff --git a/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected b/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected index 8b4da235ba0..7e636762d16 100644 --- a/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected +++ b/java/ql/test/kotlin/library-tests/exprs/funcExprs.expected @@ -42,7 +42,7 @@ memberRefExprs | kFunctionInvoke.kt:8:44:8:47 | ...::... | kFunctionInvoke.kt:8:44:8:47 | invoke | invoke(java.lang.String) | kFunctionInvoke.kt:8:44:8:47 | new Function1(...) { ... } | | samConversion.kt:5:27:5:31 | ...::... | samConversion.kt:5:27:5:31 | invoke | invoke(int,int) | samConversion.kt:5:27:5:31 | new Function2(...) { ... } | | samConversion.kt:41:13:41:16 | ...::... | samConversion.kt:41:13:41:16 | invoke | invoke(java.lang.Object[]) | samConversion.kt:41:13:41:16 | new FunctionN(...) { ... } | -modifiers +lambda_modifiers | delegatedProperties.kt:6:32:9:9 | ...->... | delegatedProperties.kt:6:32:9:9 | invoke | override, public | | funcExprs.kt:22:26:22:33 | ...->... | funcExprs.kt:22:26:22:33 | invoke | override, public | | funcExprs.kt:23:26:23:33 | ...->... | funcExprs.kt:23:26:23:33 | invoke | override, public | @@ -74,6 +74,173 @@ modifiers | samConversion.kt:43:31:45:68 | ...->... | samConversion.kt:43:31:45:68 | invoke | public | | samConversion.kt:46:32:46:44 | ...->... | samConversion.kt:46:32:46:44 | invoke | override, public | | samConversion.kt:58:30:58:45 | ...->... | samConversion.kt:58:30:58:45 | invoke | override, public, suspend | +anon_class_member_modifiers +| delegatedProperties.kt:6:24:9:9 | new KProperty0(...) { ... } | delegatedProperties.kt:6:24:9:9 | get | override, public | +| delegatedProperties.kt:6:24:9:9 | new KProperty0(...) { ... } | delegatedProperties.kt:6:24:9:9 | invoke | override, public | +| delegatedProperties.kt:6:32:9:9 | new Function0(...) { ... } | delegatedProperties.kt:6:32:9:9 | invoke | override, public | +| delegatedProperties.kt:19:31:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:31:19:51 | get | override, public | +| delegatedProperties.kt:19:31:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:31:19:51 | get | override, public | +| delegatedProperties.kt:19:31:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:31:19:51 | invoke | override, public | +| delegatedProperties.kt:19:31:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:31:19:51 | invoke | override, public | +| delegatedProperties.kt:19:31:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:31:19:51 | set | override, public | +| delegatedProperties.kt:19:31:19:51 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:19:31:19:51 | set | override, public | +| delegatedProperties.kt:23:26:23:31 | new KProperty0(...) { ... } | delegatedProperties.kt:23:26:23:31 | get | override, public | +| delegatedProperties.kt:23:26:23:31 | new KProperty0(...) { ... } | delegatedProperties.kt:23:26:23:31 | invoke | override, public | +| delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:26:13:26:28 | getCurValue | public | +| delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:26:13:26:28 | setCurValue | public | +| delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:27:22:27:88 | getValue | override, public | +| delegatedProperties.kt:25:64:31:9 | new ReadWriteProperty(...) { ... } | delegatedProperties.kt:28:22:30:13 | setValue | override, public | +| delegatedProperties.kt:33:27:33:47 | new KProperty0(...) { ... } | delegatedProperties.kt:33:27:33:47 | get | override, public | +| delegatedProperties.kt:33:27:33:47 | new KProperty0(...) { ... } | delegatedProperties.kt:33:27:33:47 | invoke | override, public | +| delegatedProperties.kt:34:28:34:48 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:34:28:34:48 | get | override, public | +| delegatedProperties.kt:34:28:34:48 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:34:28:34:48 | get | override, public | +| delegatedProperties.kt:34:28:34:48 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:34:28:34:48 | invoke | override, public | +| delegatedProperties.kt:34:28:34:48 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:34:28:34:48 | invoke | override, public | +| delegatedProperties.kt:34:28:34:48 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:34:28:34:48 | set | override, public | +| delegatedProperties.kt:34:28:34:48 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:34:28:34:48 | set | override, public | +| delegatedProperties.kt:39:31:39:51 | new KProperty0(...) { ... } | delegatedProperties.kt:39:31:39:51 | get | override, public | +| delegatedProperties.kt:39:31:39:51 | new KProperty0(...) { ... } | delegatedProperties.kt:39:31:39:51 | get | override, public | +| delegatedProperties.kt:39:31:39:51 | new KProperty0(...) { ... } | delegatedProperties.kt:39:31:39:51 | invoke | override, public | +| delegatedProperties.kt:39:31:39:51 | new KProperty0(...) { ... } | delegatedProperties.kt:39:31:39:51 | invoke | override, public | +| delegatedProperties.kt:42:27:42:47 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:42:27:42:47 | get | override, public | +| delegatedProperties.kt:42:27:42:47 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:42:27:42:47 | get | override, public | +| delegatedProperties.kt:42:27:42:47 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:42:27:42:47 | invoke | override, public | +| delegatedProperties.kt:42:27:42:47 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:42:27:42:47 | invoke | override, public | +| delegatedProperties.kt:42:27:42:47 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:42:27:42:47 | set | override, public | +| delegatedProperties.kt:42:27:42:47 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:42:27:42:47 | set | override, public | +| delegatedProperties.kt:66:33:66:50 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:66:33:66:50 | get | override, public | +| delegatedProperties.kt:66:33:66:50 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:66:33:66:50 | get | override, public | +| delegatedProperties.kt:66:33:66:50 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:66:33:66:50 | invoke | override, public | +| delegatedProperties.kt:66:33:66:50 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:66:33:66:50 | invoke | override, public | +| delegatedProperties.kt:66:33:66:50 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:66:33:66:50 | set | override, public | +| delegatedProperties.kt:66:33:66:50 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:66:33:66:50 | set | override, public | +| delegatedProperties.kt:66:36:66:50 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:66:36:66:50 | get | override, public | +| delegatedProperties.kt:66:36:66:50 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:66:36:66:50 | invoke | override, public | +| delegatedProperties.kt:66:36:66:50 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:66:36:66:50 | set | override, public | +| delegatedProperties.kt:67:33:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:33:67:53 | get | override, public | +| delegatedProperties.kt:67:33:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:33:67:53 | get | override, public | +| delegatedProperties.kt:67:33:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:33:67:53 | invoke | override, public | +| delegatedProperties.kt:67:33:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:33:67:53 | invoke | override, public | +| delegatedProperties.kt:67:33:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:33:67:53 | set | override, public | +| delegatedProperties.kt:67:33:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:33:67:53 | set | override, public | +| delegatedProperties.kt:67:36:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:36:67:53 | get | override, public | +| delegatedProperties.kt:67:36:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:36:67:53 | invoke | override, public | +| delegatedProperties.kt:67:36:67:53 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:67:36:67:53 | set | override, public | +| delegatedProperties.kt:69:36:69:56 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:69:36:69:56 | get | override, public | +| delegatedProperties.kt:69:36:69:56 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:69:36:69:56 | get | override, public | +| delegatedProperties.kt:69:36:69:56 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:69:36:69:56 | invoke | override, public | +| delegatedProperties.kt:69:36:69:56 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:69:36:69:56 | invoke | override, public | +| delegatedProperties.kt:69:36:69:56 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:69:36:69:56 | set | override, public | +| delegatedProperties.kt:69:36:69:56 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:69:36:69:56 | set | override, public | +| delegatedProperties.kt:69:39:69:56 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:69:39:69:56 | get | override, public | +| delegatedProperties.kt:69:39:69:56 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:69:39:69:56 | invoke | override, public | +| delegatedProperties.kt:69:39:69:56 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:69:39:69:56 | set | override, public | +| delegatedProperties.kt:70:36:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:36:70:59 | get | override, public | +| delegatedProperties.kt:70:36:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:36:70:59 | get | override, public | +| delegatedProperties.kt:70:36:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:36:70:59 | invoke | override, public | +| delegatedProperties.kt:70:36:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:36:70:59 | invoke | override, public | +| delegatedProperties.kt:70:36:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:36:70:59 | set | override, public | +| delegatedProperties.kt:70:36:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:36:70:59 | set | override, public | +| delegatedProperties.kt:70:39:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:39:70:59 | get | override, public | +| delegatedProperties.kt:70:39:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:39:70:59 | invoke | override, public | +| delegatedProperties.kt:70:39:70:59 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:70:39:70:59 | set | override, public | +| delegatedProperties.kt:72:36:72:56 | new KProperty1(...) { ... } | delegatedProperties.kt:72:36:72:56 | get | override, public | +| delegatedProperties.kt:72:36:72:56 | new KProperty1(...) { ... } | delegatedProperties.kt:72:36:72:56 | invoke | override, public | +| delegatedProperties.kt:72:39:72:56 | new KProperty0(...) { ... } | delegatedProperties.kt:72:39:72:56 | get | override, public | +| delegatedProperties.kt:72:39:72:56 | new KProperty0(...) { ... } | delegatedProperties.kt:72:39:72:56 | invoke | override, public | +| delegatedProperties.kt:73:36:73:56 | new KProperty1(...) { ... } | delegatedProperties.kt:73:36:73:56 | get | override, public | +| delegatedProperties.kt:73:36:73:56 | new KProperty1(...) { ... } | delegatedProperties.kt:73:36:73:56 | invoke | override, public | +| delegatedProperties.kt:73:39:73:56 | new KProperty1(...) { ... } | delegatedProperties.kt:73:39:73:56 | get | override, public | +| delegatedProperties.kt:73:39:73:56 | new KProperty1(...) { ... } | delegatedProperties.kt:73:39:73:56 | invoke | override, public | +| delegatedProperties.kt:75:39:75:78 | new KProperty1(...) { ... } | delegatedProperties.kt:75:39:75:78 | get | override, public | +| delegatedProperties.kt:75:39:75:78 | new KProperty1(...) { ... } | delegatedProperties.kt:75:39:75:78 | invoke | override, public | +| delegatedProperties.kt:75:42:75:78 | new KProperty0(...) { ... } | delegatedProperties.kt:75:42:75:78 | get | override, public | +| delegatedProperties.kt:75:42:75:78 | new KProperty0(...) { ... } | delegatedProperties.kt:75:42:75:78 | invoke | override, public | +| delegatedProperties.kt:77:34:77:49 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:77:34:77:49 | get | override, public | +| delegatedProperties.kt:77:34:77:49 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:77:34:77:49 | get | override, public | +| delegatedProperties.kt:77:34:77:49 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:77:34:77:49 | invoke | override, public | +| delegatedProperties.kt:77:34:77:49 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:77:34:77:49 | invoke | override, public | +| delegatedProperties.kt:77:34:77:49 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:77:34:77:49 | set | override, public | +| delegatedProperties.kt:77:34:77:49 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:77:34:77:49 | set | override, public | +| delegatedProperties.kt:77:37:77:49 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:77:37:77:49 | get | override, public | +| delegatedProperties.kt:77:37:77:49 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:77:37:77:49 | invoke | override, public | +| delegatedProperties.kt:77:37:77:49 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:77:37:77:49 | set | override, public | +| delegatedProperties.kt:79:18:79:38 | new KProperty1(...) { ... } | delegatedProperties.kt:79:18:79:38 | get | override, public | +| delegatedProperties.kt:79:18:79:38 | new KProperty1(...) { ... } | delegatedProperties.kt:79:18:79:38 | invoke | override, public | +| delegatedProperties.kt:79:21:79:38 | new KProperty0(...) { ... } | delegatedProperties.kt:79:21:79:38 | get | override, public | +| delegatedProperties.kt:79:21:79:38 | new KProperty0(...) { ... } | delegatedProperties.kt:79:21:79:38 | invoke | override, public | +| delegatedProperties.kt:82:37:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:37:82:54 | get | override, public | +| delegatedProperties.kt:82:37:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:37:82:54 | get | override, public | +| delegatedProperties.kt:82:37:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:37:82:54 | invoke | override, public | +| delegatedProperties.kt:82:37:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:37:82:54 | invoke | override, public | +| delegatedProperties.kt:82:37:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:37:82:54 | set | override, public | +| delegatedProperties.kt:82:37:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:37:82:54 | set | override, public | +| delegatedProperties.kt:82:40:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:40:82:54 | get | override, public | +| delegatedProperties.kt:82:40:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:40:82:54 | invoke | override, public | +| delegatedProperties.kt:82:40:82:54 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:82:40:82:54 | set | override, public | +| delegatedProperties.kt:87:31:87:46 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:87:31:87:46 | get | override, public | +| delegatedProperties.kt:87:31:87:46 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:87:31:87:46 | get | override, public | +| delegatedProperties.kt:87:31:87:46 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:87:31:87:46 | invoke | override, public | +| delegatedProperties.kt:87:31:87:46 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:87:31:87:46 | invoke | override, public | +| delegatedProperties.kt:87:31:87:46 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:87:31:87:46 | set | override, public | +| delegatedProperties.kt:87:31:87:46 | new KMutableProperty1(...) { ... } | delegatedProperties.kt:87:31:87:46 | set | override, public | +| delegatedProperties.kt:87:34:87:46 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:87:34:87:46 | get | override, public | +| delegatedProperties.kt:87:34:87:46 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:87:34:87:46 | invoke | override, public | +| delegatedProperties.kt:87:34:87:46 | new KMutableProperty0(...) { ... } | delegatedProperties.kt:87:34:87:46 | set | override, public | +| exprs.kt:189:16:191:9 | new Interface1(...) { ... } | exprs.kt:190:13:190:49 | getA3 | public | +| funcExprs.kt:22:26:22:33 | new Function0(...) { ... } | funcExprs.kt:22:26:22:33 | invoke | override, public | +| funcExprs.kt:23:26:23:33 | new Function0(...) { ... } | funcExprs.kt:23:26:23:33 | invoke | override, public | +| funcExprs.kt:24:26:24:33 | new Function0(...) { ... } | funcExprs.kt:24:26:24:33 | invoke | override, public | +| funcExprs.kt:25:29:25:38 | new Function1(...) { ... } | funcExprs.kt:25:29:25:38 | invoke | override, public | +| funcExprs.kt:26:29:26:34 | new Function1(...) { ... } | funcExprs.kt:26:29:26:34 | invoke | override, public | +| funcExprs.kt:27:29:27:42 | new Function1(...) { ... } | funcExprs.kt:27:29:27:42 | invoke | override, public | +| funcExprs.kt:29:29:29:37 | new Function1(...) { ... } | funcExprs.kt:29:29:29:37 | invoke | override, public | +| funcExprs.kt:30:28:30:50 | new Function2(...) { ... } | funcExprs.kt:30:28:30:50 | invoke | override, public | +| funcExprs.kt:31:28:31:40 | new Function2(...) { ... } | funcExprs.kt:31:28:31:40 | invoke | override, public | +| funcExprs.kt:32:28:32:44 | new Function2(...) { ... } | funcExprs.kt:32:28:32:44 | invoke | override, public | +| funcExprs.kt:33:28:33:51 | new Function1>(...) { ... } | funcExprs.kt:33:28:33:51 | invoke | override, public | +| funcExprs.kt:33:37:33:47 | new Function1(...) { ... } | funcExprs.kt:33:37:33:47 | invoke | override, public | +| funcExprs.kt:35:29:35:112 | new Function22(...) { ... } | funcExprs.kt:35:29:35:112 | invoke | override, public | +| funcExprs.kt:36:29:36:117 | new FunctionN(...) { ... } | funcExprs.kt:36:29:36:117 | invoke | override, public | +| funcExprs.kt:36:29:36:117 | new FunctionN(...) { ... } | funcExprs.kt:36:29:36:117 | invoke | public | +| funcExprs.kt:38:26:38:38 | new Function0(...) { ... } | funcExprs.kt:38:26:38:38 | invoke | override, public | +| funcExprs.kt:39:26:39:36 | new Function0(...) { ... } | funcExprs.kt:39:26:39:36 | invoke | override, public | +| funcExprs.kt:40:29:40:41 | new Function1(...) { ... } | funcExprs.kt:40:29:40:41 | invoke | override, public | +| funcExprs.kt:41:29:41:39 | new Function2(...) { ... } | funcExprs.kt:41:29:41:39 | invoke | override, public | +| funcExprs.kt:42:29:42:33 | new Function1(...) { ... } | funcExprs.kt:42:29:42:33 | invoke | override, public | +| funcExprs.kt:43:28:43:34 | new Function2(...) { ... } | funcExprs.kt:43:28:43:34 | invoke | override, public | +| funcExprs.kt:44:29:44:42 | new Function22(...) { ... } | funcExprs.kt:44:29:44:42 | invoke | override, public | +| funcExprs.kt:45:29:45:42 | new FunctionN(...) { ... } | funcExprs.kt:45:29:45:42 | invoke | override, public | +| funcExprs.kt:46:30:46:41 | new FunctionN(...) { ... } | funcExprs.kt:46:30:46:41 | invoke | override, public | +| funcExprs.kt:49:26:49:32 | new Function0(...) { ... } | funcExprs.kt:49:26:49:32 | invoke | override, public | +| funcExprs.kt:51:8:51:16 | new Function0(...) { ... } | funcExprs.kt:51:8:51:16 | invoke | override, public | +| funcExprs.kt:75:12:75:22 | new Function1>,String>(...) { ... } | funcExprs.kt:75:12:75:22 | invoke | override, public | +| funcExprs.kt:83:31:83:51 | new Function1(...) { ... } | funcExprs.kt:83:31:83:51 | invoke | override, public | +| funcExprs.kt:86:39:86:59 | new Function1(...) { ... } | funcExprs.kt:86:39:86:59 | invoke | override, public, suspend | +| funcExprs.kt:90:15:90:69 | new FunctionN(...) { ... } | funcExprs.kt:90:15:90:69 | invoke | override, public | +| funcExprs.kt:90:15:90:69 | new FunctionN(...) { ... } | funcExprs.kt:90:15:90:69 | invoke | public | +| funcExprs.kt:94:15:94:67 | new Function22(...) { ... } | funcExprs.kt:94:15:94:67 | invoke | override, public, suspend | +| kFunctionInvoke.kt:8:44:8:47 | new Function1(...) { ... } | kFunctionInvoke.kt:8:44:8:47 | invoke | override, public | +| samConversion.kt:2:18:2:45 | new IntPredicate(...) { ... } | samConversion.kt:2:18:2:45 | accept | override, public | +| samConversion.kt:2:31:2:45 | new Function1(...) { ... } | samConversion.kt:2:31:2:45 | invoke | override, public | +| samConversion.kt:4:14:4:42 | new InterfaceFn1(...) { ... } | samConversion.kt:4:14:4:42 | fn1 | override, public | +| samConversion.kt:4:27:4:42 | new Function2(...) { ... } | samConversion.kt:4:27:4:42 | invoke | override, public | +| samConversion.kt:5:14:5:32 | new InterfaceFn1(...) { ... } | samConversion.kt:5:14:5:32 | fn1 | override, public | +| samConversion.kt:5:27:5:31 | new Function2(...) { ... } | samConversion.kt:5:27:5:31 | invoke | override, public | +| samConversion.kt:7:13:7:46 | new InterfaceFnExt1(...) { ... } | samConversion.kt:7:13:7:46 | ext | override, public | +| samConversion.kt:7:29:7:46 | new Function2(...) { ... } | samConversion.kt:7:29:7:46 | invoke | override, public | +| samConversion.kt:9:13:13:6 | new IntPredicate(...) { ... } | samConversion.kt:9:13:13:6 | accept | override, public | +| samConversion.kt:9:33:11:5 | new Function1(...) { ... } | samConversion.kt:9:33:11:5 | invoke | override, public | +| samConversion.kt:11:12:13:5 | new Function1(...) { ... } | samConversion.kt:11:12:13:5 | invoke | override, public | +| samConversion.kt:41:13:41:16 | new FunctionN(...) { ... } | samConversion.kt:41:13:41:16 | invoke | override, public | +| samConversion.kt:42:13:42:32 | new BigArityPredicate(...) { ... } | samConversion.kt:42:13:42:32 | accept | override, public | +| samConversion.kt:43:13:45:68 | new BigArityPredicate(...) { ... } | samConversion.kt:43:13:45:68 | accept | override, public | +| samConversion.kt:43:31:45:68 | new FunctionN(...) { ... } | samConversion.kt:43:31:45:68 | invoke | override, public | +| samConversion.kt:43:31:45:68 | new FunctionN(...) { ... } | samConversion.kt:43:31:45:68 | invoke | public | +| samConversion.kt:46:13:46:44 | new SomePredicate(...) { ... } | samConversion.kt:46:13:46:44 | fn | override, public | +| samConversion.kt:46:32:46:44 | new Function1(...) { ... } | samConversion.kt:46:32:46:44 | invoke | override, public | +| samConversion.kt:58:14:58:45 | new InterfaceFn1Sus(...) { ... } | samConversion.kt:58:14:58:45 | fn1 | override, public, suspend | +| samConversion.kt:58:30:58:45 | new Function2(...) { ... } | samConversion.kt:58:30:58:45 | invoke | override, public, suspend | nonOverrideInvoke | funcExprs.kt:36:29:36:117 | ...->... | funcExprs.kt:36:29:36:117 | invoke | 23 | | funcExprs.kt:90:15:90:69 | ...->... | funcExprs.kt:90:15:90:69 | invoke | 23 | diff --git a/java/ql/test/kotlin/library-tests/exprs/funcExprs.ql b/java/ql/test/kotlin/library-tests/exprs/funcExprs.ql index fa2b5fda2a2..f6e233336f3 100644 --- a/java/ql/test/kotlin/library-tests/exprs/funcExprs.ql +++ b/java/ql/test/kotlin/library-tests/exprs/funcExprs.ql @@ -19,11 +19,16 @@ query predicate memberRefExprs(MemberRefExpr e, Method m, string signature, Anon e.getAnonymousClass() = an } -query predicate modifiers(LambdaExpr le, Method m, string modifiers) { +query predicate lambda_modifiers(LambdaExpr le, Method m, string modifiers) { le.getAnonymousClass().getAMethod() = m and modifiers = concat(string s | m.hasModifier(s) | s, ", ") } +query predicate anon_class_member_modifiers(AnonymousClass ac, Method m, string modifiers) { + ac.getAMethod() = m and + modifiers = concat(string s | m.hasModifier(s) | s, ", ") +} + query predicate nonOverrideInvoke(LambdaExpr le, Method m, int pCount) { le.getAnonymousClass().getAMethod() = m and not m.hasModifier("override") and diff --git a/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected b/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected index 44e1e5f5950..4c7b75edc3a 100644 --- a/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected @@ -69,6 +69,56 @@ test.kt: # 45| 5: [BlockStmt] { ... } # 45| 0: [ReturnStmt] return ... # 45| 0: [VarAccess] a +# 45| 5: [Method] testExtensionFunction$default +# 45| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 45| 0: [Parameter] p0 +# 45| 0: [TypeAccess] Test +# 45| 1: [Parameter] p1 +# 45| 0: [TypeAccess] int +# 45| 2: [Parameter] p2 +# 45| 0: [TypeAccess] String +# 45| 3: [Parameter] p3 +# 45| 0: [TypeAccess] double +# 45| 4: [Parameter] p4 +# 45| 0: [TypeAccess] float +# 45| 5: [Parameter] p5 +# 45| 0: [TypeAccess] boolean +# 45| 6: [Parameter] p6 +# 45| 0: [TypeAccess] int +# 45| 7: [Parameter] p7 +# 45| 0: [TypeAccess] Object +# 45| 5: [BlockStmt] { ... } +# 45| 0: [IfStmt] if (...) +# 45| 0: [EQExpr] ... == ... +# 45| 0: [AndBitwiseExpr] ... & ... +# 45| 0: [IntegerLiteral] 2 +# 45| 1: [VarAccess] p6 +# 45| 1: [IntegerLiteral] 0 +# 45| 1: [ExprStmt] ; +# 45| 0: [AssignExpr] ...=... +# 45| 0: [VarAccess] p2 +# 45| 1: [MethodAccess] getString(...) +# 45| -1: [TypeAccess] TestKt +# 45| 1: [IfStmt] if (...) +# 45| 0: [EQExpr] ... == ... +# 45| 0: [AndBitwiseExpr] ... & ... +# 45| 0: [IntegerLiteral] 8 +# 45| 1: [VarAccess] p6 +# 45| 1: [IntegerLiteral] 0 +# 45| 1: [ExprStmt] ; +# 45| 0: [AssignExpr] ...=... +# 45| 0: [VarAccess] p4 +# 45| 1: [FloatLiteral] 1.0 +# 45| 2: [ReturnStmt] return ... +# 45| 0: [MethodAccess] testExtensionFunction(...) +# 45| -1: [TypeAccess] TestKt +# 45| 0: [VarAccess] p0 +# 45| 1: [VarAccess] p1 +# 45| 2: [VarAccess] p2 +# 45| 3: [VarAccess] p3 +# 45| 4: [VarAccess] p4 +# 45| 5: [VarAccess] p5 # 3| 2: [Class] Test # 3| 1: [Constructor] Test # 3| 5: [BlockStmt] { ... } @@ -129,7 +179,54 @@ test.kt: # 6| 5: [BlockStmt] { ... } # 6| 0: [ReturnStmt] return ... # 6| 0: [VarAccess] a -# 9| 5: [Method] testMemberFunction +# 6| 5: [Method] testStaticFunction$default +# 6| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 6| 0: [Parameter] p0 +# 6| 0: [TypeAccess] int +# 6| 1: [Parameter] p1 +# 6| 0: [TypeAccess] String +# 6| 2: [Parameter] p2 +# 6| 0: [TypeAccess] double +# 6| 3: [Parameter] p3 +# 6| 0: [TypeAccess] float +# 6| 4: [Parameter] p4 +# 6| 0: [TypeAccess] boolean +# 6| 5: [Parameter] p5 +# 6| 0: [TypeAccess] int +# 6| 6: [Parameter] p6 +# 6| 0: [TypeAccess] Object +# 6| 5: [BlockStmt] { ... } +# 6| 0: [IfStmt] if (...) +# 6| 0: [EQExpr] ... == ... +# 6| 0: [AndBitwiseExpr] ... & ... +# 6| 0: [IntegerLiteral] 2 +# 6| 1: [VarAccess] p5 +# 6| 1: [IntegerLiteral] 0 +# 6| 1: [ExprStmt] ; +# 6| 0: [AssignExpr] ...=... +# 6| 0: [VarAccess] p1 +# 6| 1: [MethodAccess] getString(...) +# 6| -1: [TypeAccess] TestKt +# 6| 1: [IfStmt] if (...) +# 6| 0: [EQExpr] ... == ... +# 6| 0: [AndBitwiseExpr] ... & ... +# 6| 0: [IntegerLiteral] 8 +# 6| 1: [VarAccess] p5 +# 6| 1: [IntegerLiteral] 0 +# 6| 1: [ExprStmt] ; +# 6| 0: [AssignExpr] ...=... +# 6| 0: [VarAccess] p3 +# 6| 1: [FloatLiteral] 1.0 +# 6| 2: [ReturnStmt] return ... +# 6| 0: [MethodAccess] testStaticFunction(...) +# 6| -1: [TypeAccess] Test +# 6| 0: [VarAccess] p0 +# 6| 1: [VarAccess] p1 +# 6| 2: [VarAccess] p2 +# 6| 3: [VarAccess] p3 +# 6| 4: [VarAccess] p4 +# 9| 6: [Method] testMemberFunction # 9| 3: [TypeAccess] int #-----| 4: (Parameters) # 9| 0: [Parameter] a @@ -148,7 +245,7 @@ test.kt: # 9| 2: [VarAccess] c # 9| 3: [FloatLiteral] 1.0 # 9| 4: [VarAccess] e -# 9| 6: [Method] testMemberFunction +# 9| 7: [Method] testMemberFunction # 9| 3: [TypeAccess] int #-----| 4: (Parameters) # 9| 0: [Parameter] a @@ -168,7 +265,7 @@ test.kt: # 9| 2: [VarAccess] c # 9| 3: [FloatLiteral] 1.0 # 9| 4: [VarAccess] e -# 9| 7: [Method] testMemberFunction +# 9| 8: [Method] testMemberFunction # 9| 3: [TypeAccess] int #-----| 4: (Parameters) # 9| 0: [Parameter] a @@ -184,7 +281,56 @@ test.kt: # 9| 5: [BlockStmt] { ... } # 9| 0: [ReturnStmt] return ... # 9| 0: [VarAccess] a -# 12| 8: [ExtensionMethod] testMemberExtensionFunction +# 9| 9: [Method] testMemberFunction$default +# 9| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 9| 0: [Parameter] p0 +# 9| 0: [TypeAccess] Test +# 9| 1: [Parameter] p1 +# 9| 0: [TypeAccess] int +# 9| 2: [Parameter] p2 +# 9| 0: [TypeAccess] String +# 9| 3: [Parameter] p3 +# 9| 0: [TypeAccess] double +# 9| 4: [Parameter] p4 +# 9| 0: [TypeAccess] float +# 9| 5: [Parameter] p5 +# 9| 0: [TypeAccess] boolean +# 9| 6: [Parameter] p6 +# 9| 0: [TypeAccess] int +# 9| 7: [Parameter] p7 +# 9| 0: [TypeAccess] Object +# 9| 5: [BlockStmt] { ... } +# 9| 0: [IfStmt] if (...) +# 9| 0: [EQExpr] ... == ... +# 9| 0: [AndBitwiseExpr] ... & ... +# 9| 0: [IntegerLiteral] 2 +# 9| 1: [VarAccess] p6 +# 9| 1: [IntegerLiteral] 0 +# 9| 1: [ExprStmt] ; +# 9| 0: [AssignExpr] ...=... +# 9| 0: [VarAccess] p2 +# 9| 1: [MethodAccess] getString(...) +# 9| -1: [TypeAccess] TestKt +# 9| 1: [IfStmt] if (...) +# 9| 0: [EQExpr] ... == ... +# 9| 0: [AndBitwiseExpr] ... & ... +# 9| 0: [IntegerLiteral] 8 +# 9| 1: [VarAccess] p6 +# 9| 1: [IntegerLiteral] 0 +# 9| 1: [ExprStmt] ; +# 9| 0: [AssignExpr] ...=... +# 9| 0: [VarAccess] p4 +# 9| 1: [FloatLiteral] 1.0 +# 9| 2: [ReturnStmt] return ... +# 9| 0: [MethodAccess] testMemberFunction(...) +# 9| -1: [VarAccess] p0 +# 9| 0: [VarAccess] p1 +# 9| 1: [VarAccess] p2 +# 9| 2: [VarAccess] p3 +# 9| 3: [VarAccess] p4 +# 9| 4: [VarAccess] p5 +# 12| 10: [ExtensionMethod] testMemberExtensionFunction # 12| 3: [TypeAccess] int #-----| 4: (Parameters) # 12| 0: [Parameter] @@ -206,7 +352,7 @@ test.kt: # 12| 3: [VarAccess] c # 12| 4: [FloatLiteral] 1.0 # 12| 5: [VarAccess] e -# 12| 9: [ExtensionMethod] testMemberExtensionFunction +# 12| 11: [ExtensionMethod] testMemberExtensionFunction # 12| 3: [TypeAccess] int #-----| 4: (Parameters) # 12| 0: [Parameter] @@ -229,7 +375,7 @@ test.kt: # 12| 3: [VarAccess] c # 12| 4: [FloatLiteral] 1.0 # 12| 5: [VarAccess] e -# 12| 10: [ExtensionMethod] testMemberExtensionFunction +# 12| 12: [ExtensionMethod] testMemberExtensionFunction # 12| 3: [TypeAccess] int #-----| 4: (Parameters) # 12| 0: [Parameter] @@ -247,6 +393,58 @@ test.kt: # 12| 5: [BlockStmt] { ... } # 12| 0: [ReturnStmt] return ... # 12| 0: [VarAccess] a +# 12| 13: [Method] testMemberExtensionFunction$default +# 12| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 12| 0: [Parameter] p0 +# 12| 0: [TypeAccess] Test2 +# 12| 1: [Parameter] p1 +# 12| 0: [TypeAccess] Test +# 12| 2: [Parameter] p2 +# 12| 0: [TypeAccess] int +# 12| 3: [Parameter] p3 +# 12| 0: [TypeAccess] String +# 12| 4: [Parameter] p4 +# 12| 0: [TypeAccess] double +# 12| 5: [Parameter] p5 +# 12| 0: [TypeAccess] float +# 12| 6: [Parameter] p6 +# 12| 0: [TypeAccess] boolean +# 12| 7: [Parameter] p7 +# 12| 0: [TypeAccess] int +# 12| 8: [Parameter] p8 +# 12| 0: [TypeAccess] Object +# 12| 5: [BlockStmt] { ... } +# 12| 0: [IfStmt] if (...) +# 12| 0: [EQExpr] ... == ... +# 12| 0: [AndBitwiseExpr] ... & ... +# 12| 0: [IntegerLiteral] 2 +# 12| 1: [VarAccess] p7 +# 12| 1: [IntegerLiteral] 0 +# 12| 1: [ExprStmt] ; +# 12| 0: [AssignExpr] ...=... +# 12| 0: [VarAccess] p3 +# 12| 1: [MethodAccess] getString(...) +# 12| -1: [TypeAccess] TestKt +# 12| 1: [IfStmt] if (...) +# 12| 0: [EQExpr] ... == ... +# 12| 0: [AndBitwiseExpr] ... & ... +# 12| 0: [IntegerLiteral] 8 +# 12| 1: [VarAccess] p7 +# 12| 1: [IntegerLiteral] 0 +# 12| 1: [ExprStmt] ; +# 12| 0: [AssignExpr] ...=... +# 12| 0: [VarAccess] p5 +# 12| 1: [FloatLiteral] 1.0 +# 12| 2: [ReturnStmt] return ... +# 12| 0: [MethodAccess] testMemberExtensionFunction(...) +# 12| -1: [VarAccess] p1 +# 12| 0: [VarAccess] p0 +# 12| 1: [VarAccess] p2 +# 12| 2: [VarAccess] p3 +# 12| 3: [VarAccess] p4 +# 12| 4: [VarAccess] p5 +# 12| 5: [VarAccess] p6 # 16| 3: [Class] Test2 # 16| 1: [Constructor] Test2 #-----| 4: (Parameters) @@ -296,7 +494,51 @@ test.kt: # 16| 5: [BlockStmt] { ... } # 16| 0: [SuperConstructorInvocationStmt] super(...) # 16| 1: [BlockStmt] { ... } -# 18| 4: [Class] Companion +# 16| 4: [Constructor] Test2 +#-----| 4: (Parameters) +# 16| 0: [Parameter] p0 +# 16| 0: [TypeAccess] int +# 16| 1: [Parameter] p1 +# 16| 0: [TypeAccess] String +# 16| 2: [Parameter] p2 +# 16| 0: [TypeAccess] double +# 16| 3: [Parameter] p3 +# 16| 0: [TypeAccess] float +# 16| 4: [Parameter] p4 +# 16| 0: [TypeAccess] boolean +# 16| 5: [Parameter] p5 +# 16| 0: [TypeAccess] int +# 16| 6: [Parameter] p6 +# 16| 0: [TypeAccess] DefaultConstructorMarker +# 16| 5: [BlockStmt] { ... } +# 16| 0: [IfStmt] if (...) +# 16| 0: [EQExpr] ... == ... +# 16| 0: [AndBitwiseExpr] ... & ... +# 16| 0: [IntegerLiteral] 2 +# 16| 1: [VarAccess] p5 +# 16| 1: [IntegerLiteral] 0 +# 16| 1: [ExprStmt] ; +# 16| 0: [AssignExpr] ...=... +# 16| 0: [VarAccess] p1 +# 16| 1: [MethodAccess] getString(...) +# 16| -1: [TypeAccess] TestKt +# 16| 1: [IfStmt] if (...) +# 16| 0: [EQExpr] ... == ... +# 16| 0: [AndBitwiseExpr] ... & ... +# 16| 0: [IntegerLiteral] 8 +# 16| 1: [VarAccess] p5 +# 16| 1: [IntegerLiteral] 0 +# 16| 1: [ExprStmt] ; +# 16| 0: [AssignExpr] ...=... +# 16| 0: [VarAccess] p3 +# 16| 1: [FloatLiteral] 1.0 +# 16| 2: [ThisConstructorInvocationStmt] this(...) +# 16| 0: [VarAccess] p0 +# 16| 1: [VarAccess] p1 +# 16| 2: [VarAccess] p2 +# 16| 3: [VarAccess] p3 +# 16| 4: [VarAccess] p4 +# 18| 5: [Class] Companion # 18| 1: [Constructor] Companion # 18| 5: [BlockStmt] { ... } # 18| 0: [SuperConstructorInvocationStmt] super(...) @@ -356,7 +598,56 @@ test.kt: # 21| 5: [BlockStmt] { ... } # 21| 0: [ReturnStmt] return ... # 21| 0: [VarAccess] a -# 24| 5: [Method] testStaticCompanionFunction +# 21| 5: [Method] testCompanionFunction$default +# 21| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 21| 0: [Parameter] p0 +# 21| 0: [TypeAccess] Companion +# 21| 1: [Parameter] p1 +# 21| 0: [TypeAccess] int +# 21| 2: [Parameter] p2 +# 21| 0: [TypeAccess] String +# 21| 3: [Parameter] p3 +# 21| 0: [TypeAccess] double +# 21| 4: [Parameter] p4 +# 21| 0: [TypeAccess] float +# 21| 5: [Parameter] p5 +# 21| 0: [TypeAccess] boolean +# 21| 6: [Parameter] p6 +# 21| 0: [TypeAccess] int +# 21| 7: [Parameter] p7 +# 21| 0: [TypeAccess] Object +# 21| 5: [BlockStmt] { ... } +# 21| 0: [IfStmt] if (...) +# 21| 0: [EQExpr] ... == ... +# 21| 0: [AndBitwiseExpr] ... & ... +# 21| 0: [IntegerLiteral] 2 +# 21| 1: [VarAccess] p6 +# 21| 1: [IntegerLiteral] 0 +# 21| 1: [ExprStmt] ; +# 21| 0: [AssignExpr] ...=... +# 21| 0: [VarAccess] p2 +# 21| 1: [MethodAccess] getString(...) +# 21| -1: [TypeAccess] TestKt +# 21| 1: [IfStmt] if (...) +# 21| 0: [EQExpr] ... == ... +# 21| 0: [AndBitwiseExpr] ... & ... +# 21| 0: [IntegerLiteral] 8 +# 21| 1: [VarAccess] p6 +# 21| 1: [IntegerLiteral] 0 +# 21| 1: [ExprStmt] ; +# 21| 0: [AssignExpr] ...=... +# 21| 0: [VarAccess] p4 +# 21| 1: [FloatLiteral] 1.0 +# 21| 2: [ReturnStmt] return ... +# 21| 0: [MethodAccess] testCompanionFunction(...) +# 21| -1: [VarAccess] p0 +# 21| 0: [VarAccess] p1 +# 21| 1: [VarAccess] p2 +# 21| 2: [VarAccess] p3 +# 21| 3: [VarAccess] p4 +# 21| 4: [VarAccess] p5 +# 24| 6: [Method] testStaticCompanionFunction # 24| 3: [TypeAccess] int #-----| 4: (Parameters) # 24| 0: [Parameter] a @@ -375,7 +666,7 @@ test.kt: # 24| 2: [VarAccess] c # 24| 3: [FloatLiteral] 1.0 # 24| 4: [VarAccess] e -# 24| 6: [Method] testStaticCompanionFunction +# 24| 7: [Method] testStaticCompanionFunction # 24| 3: [TypeAccess] int #-----| 4: (Parameters) # 24| 0: [Parameter] a @@ -395,7 +686,7 @@ test.kt: # 24| 2: [VarAccess] c # 24| 3: [FloatLiteral] 1.0 # 24| 4: [VarAccess] e -# 24| 7: [Method] testStaticCompanionFunction +# 24| 8: [Method] testStaticCompanionFunction # 24| 3: [TypeAccess] int #-----| 4: (Parameters) # 24| 0: [Parameter] a @@ -411,7 +702,56 @@ test.kt: # 24| 5: [BlockStmt] { ... } # 24| 0: [ReturnStmt] return ... # 24| 0: [VarAccess] a -# 24| 5: [Method] testStaticCompanionFunction +# 24| 9: [Method] testStaticCompanionFunction$default +# 24| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 24| 0: [Parameter] p0 +# 24| 0: [TypeAccess] Companion +# 24| 1: [Parameter] p1 +# 24| 0: [TypeAccess] int +# 24| 2: [Parameter] p2 +# 24| 0: [TypeAccess] String +# 24| 3: [Parameter] p3 +# 24| 0: [TypeAccess] double +# 24| 4: [Parameter] p4 +# 24| 0: [TypeAccess] float +# 24| 5: [Parameter] p5 +# 24| 0: [TypeAccess] boolean +# 24| 6: [Parameter] p6 +# 24| 0: [TypeAccess] int +# 24| 7: [Parameter] p7 +# 24| 0: [TypeAccess] Object +# 24| 5: [BlockStmt] { ... } +# 24| 0: [IfStmt] if (...) +# 24| 0: [EQExpr] ... == ... +# 24| 0: [AndBitwiseExpr] ... & ... +# 24| 0: [IntegerLiteral] 2 +# 24| 1: [VarAccess] p6 +# 24| 1: [IntegerLiteral] 0 +# 24| 1: [ExprStmt] ; +# 24| 0: [AssignExpr] ...=... +# 24| 0: [VarAccess] p2 +# 24| 1: [MethodAccess] getString(...) +# 24| -1: [TypeAccess] TestKt +# 24| 1: [IfStmt] if (...) +# 24| 0: [EQExpr] ... == ... +# 24| 0: [AndBitwiseExpr] ... & ... +# 24| 0: [IntegerLiteral] 8 +# 24| 1: [VarAccess] p6 +# 24| 1: [IntegerLiteral] 0 +# 24| 1: [ExprStmt] ; +# 24| 0: [AssignExpr] ...=... +# 24| 0: [VarAccess] p4 +# 24| 1: [FloatLiteral] 1.0 +# 24| 2: [ReturnStmt] return ... +# 24| 0: [MethodAccess] testStaticCompanionFunction(...) +# 24| -1: [VarAccess] p0 +# 24| 0: [VarAccess] p1 +# 24| 1: [VarAccess] p2 +# 24| 2: [VarAccess] p3 +# 24| 3: [VarAccess] p4 +# 24| 4: [VarAccess] p5 +# 24| 6: [Method] testStaticCompanionFunction # 24| 3: [TypeAccess] int #-----| 4: (Parameters) # 24| 0: [Parameter] a @@ -430,7 +770,7 @@ test.kt: # 24| 2: [VarAccess] c # 24| 3: [FloatLiteral] 1.0 # 24| 4: [VarAccess] e -# 24| 6: [Method] testStaticCompanionFunction +# 24| 7: [Method] testStaticCompanionFunction # 24| 3: [TypeAccess] int #-----| 4: (Parameters) # 24| 0: [Parameter] a @@ -450,7 +790,7 @@ test.kt: # 24| 2: [VarAccess] c # 24| 3: [FloatLiteral] 1.0 # 24| 4: [VarAccess] e -# 24| 7: [Method] testStaticCompanionFunction +# 24| 8: [Method] testStaticCompanionFunction # 24| 3: [TypeAccess] int #-----| 4: (Parameters) # 24| 0: [Parameter] a @@ -515,7 +855,47 @@ test.kt: # 30| 5: [BlockStmt] { ... } # 30| 0: [SuperConstructorInvocationStmt] super(...) # 30| 1: [BlockStmt] { ... } -# 33| 4: [Method] testMemberFunction +# 30| 4: [Constructor] GenericTest +#-----| 4: (Parameters) +# 30| 0: [Parameter] p0 +# 30| 0: [TypeAccess] int +# 30| 1: [Parameter] p1 +# 30| 0: [TypeAccess] Object +# 30| 2: [Parameter] p2 +# 30| 0: [TypeAccess] String +# 30| 3: [Parameter] p3 +# 30| 0: [TypeAccess] Object +# 30| 4: [Parameter] p4 +# 30| 0: [TypeAccess] int +# 30| 5: [Parameter] p5 +# 30| 0: [TypeAccess] DefaultConstructorMarker +# 30| 5: [BlockStmt] { ... } +# 30| 0: [IfStmt] if (...) +# 30| 0: [EQExpr] ... == ... +# 30| 0: [AndBitwiseExpr] ... & ... +# 30| 0: [IntegerLiteral] 1 +# 30| 1: [VarAccess] p4 +# 30| 1: [IntegerLiteral] 0 +# 30| 1: [ExprStmt] ; +# 30| 0: [AssignExpr] ...=... +# 30| 0: [VarAccess] p0 +# 30| 1: [IntegerLiteral] 1 +# 30| 1: [IfStmt] if (...) +# 30| 0: [EQExpr] ... == ... +# 30| 0: [AndBitwiseExpr] ... & ... +# 30| 0: [IntegerLiteral] 4 +# 30| 1: [VarAccess] p4 +# 30| 1: [IntegerLiteral] 0 +# 30| 1: [ExprStmt] ; +# 30| 0: [AssignExpr] ...=... +# 30| 0: [VarAccess] p2 +# 30| 1: [StringLiteral] Hello world +# 30| 2: [ThisConstructorInvocationStmt] this(...) +# 30| 0: [VarAccess] p0 +# 30| 1: [VarAccess] p1 +# 30| 2: [VarAccess] p2 +# 30| 3: [VarAccess] p3 +# 33| 5: [Method] testMemberFunction # 33| 3: [TypeAccess] int #-----| 4: (Parameters) # 33| 0: [Parameter] b @@ -530,7 +910,7 @@ test.kt: # 33| 1: [VarAccess] b # 33| 2: [StringLiteral] Hello world # 33| 3: [VarAccess] d -# 33| 5: [Method] testMemberFunction +# 33| 6: [Method] testMemberFunction # 33| 3: [TypeAccess] int #-----| 4: (Parameters) # 33| 0: [Parameter] a @@ -547,7 +927,7 @@ test.kt: # 33| 1: [VarAccess] b # 33| 2: [StringLiteral] Hello world # 33| 3: [VarAccess] d -# 33| 6: [Method] testMemberFunction +# 33| 7: [Method] testMemberFunction # 33| 3: [TypeAccess] int #-----| 4: (Parameters) # 33| 0: [Parameter] a @@ -561,7 +941,52 @@ test.kt: # 33| 5: [BlockStmt] { ... } # 33| 0: [ReturnStmt] return ... # 33| 0: [VarAccess] a -# 35| 7: [Method] useSpecialised +# 33| 8: [Method] testMemberFunction$default +# 33| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 33| 0: [Parameter] p0 +# 33| 0: [TypeAccess] GenericTest<> +# 33| 1: [Parameter] p1 +# 33| 0: [TypeAccess] int +# 33| 2: [Parameter] p2 +# 33| 0: [TypeAccess] Object +# 33| 3: [Parameter] p3 +# 33| 0: [TypeAccess] String +# 33| 4: [Parameter] p4 +# 33| 0: [TypeAccess] Object +# 33| 5: [Parameter] p5 +# 33| 0: [TypeAccess] int +# 33| 6: [Parameter] p6 +# 33| 0: [TypeAccess] Object +# 33| 5: [BlockStmt] { ... } +# 33| 0: [IfStmt] if (...) +# 33| 0: [EQExpr] ... == ... +# 33| 0: [AndBitwiseExpr] ... & ... +# 33| 0: [IntegerLiteral] 1 +# 33| 1: [VarAccess] p5 +# 33| 1: [IntegerLiteral] 0 +# 33| 1: [ExprStmt] ; +# 33| 0: [AssignExpr] ...=... +# 33| 0: [VarAccess] p1 +# 33| 1: [IntegerLiteral] 1 +# 33| 1: [IfStmt] if (...) +# 33| 0: [EQExpr] ... == ... +# 33| 0: [AndBitwiseExpr] ... & ... +# 33| 0: [IntegerLiteral] 4 +# 33| 1: [VarAccess] p5 +# 33| 1: [IntegerLiteral] 0 +# 33| 1: [ExprStmt] ; +# 33| 0: [AssignExpr] ...=... +# 33| 0: [VarAccess] p3 +# 33| 1: [StringLiteral] Hello world +# 33| 2: [ReturnStmt] return ... +# 33| 0: [MethodAccess] testMemberFunction(...) +# 33| -1: [VarAccess] p0 +# 33| 0: [VarAccess] p1 +# 33| 1: [VarAccess] p2 +# 33| 2: [VarAccess] p3 +# 33| 3: [VarAccess] p4 +# 35| 9: [Method] useSpecialised # 35| 3: [TypeAccess] Unit #-----| 4: (Parameters) # 35| 0: [Parameter] spec1 diff --git a/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/test.expected b/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/test.expected index 7f77cb28b81..00654e8929f 100644 --- a/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/test.expected +++ b/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/test.expected @@ -16,19 +16,24 @@ | test.kt:0:0:0:0 | TestKt | test.kt:45:1:45:112 | testExtensionFunction | testExtensionFunction(Test,int,double,boolean) | | test.kt:0:0:0:0 | TestKt | test.kt:45:1:45:112 | testExtensionFunction | testExtensionFunction(Test,int,java.lang.String,double,boolean) | | test.kt:0:0:0:0 | TestKt | test.kt:45:1:45:112 | testExtensionFunction | testExtensionFunction(Test,int,java.lang.String,double,float,boolean) | +| test.kt:0:0:0:0 | TestKt | test.kt:45:1:45:112 | testExtensionFunction$default | testExtensionFunction$default(Test,int,java.lang.String,double,float,boolean,int,java.lang.Object) | | test.kt:3:1:14:1 | Test | test.kt:3:1:14:1 | Test | Test() | | test.kt:3:1:14:1 | Test | test.kt:6:3:6:106 | testStaticFunction | testStaticFunction(int,double,boolean) | | test.kt:3:1:14:1 | Test | test.kt:6:3:6:106 | testStaticFunction | testStaticFunction(int,java.lang.String,double,boolean) | | test.kt:3:1:14:1 | Test | test.kt:6:3:6:106 | testStaticFunction | testStaticFunction(int,java.lang.String,double,float,boolean) | +| test.kt:3:1:14:1 | Test | test.kt:6:3:6:106 | testStaticFunction$default | testStaticFunction$default(int,java.lang.String,double,float,boolean,int,java.lang.Object) | | test.kt:3:1:14:1 | Test | test.kt:9:3:9:106 | testMemberFunction | testMemberFunction(int,double,boolean) | | test.kt:3:1:14:1 | Test | test.kt:9:3:9:106 | testMemberFunction | testMemberFunction(int,java.lang.String,double,boolean) | | test.kt:3:1:14:1 | Test | test.kt:9:3:9:106 | testMemberFunction | testMemberFunction(int,java.lang.String,double,float,boolean) | +| test.kt:3:1:14:1 | Test | test.kt:9:3:9:106 | testMemberFunction$default | testMemberFunction$default(Test,int,java.lang.String,double,float,boolean,int,java.lang.Object) | | test.kt:3:1:14:1 | Test | test.kt:12:3:12:121 | testMemberExtensionFunction | testMemberExtensionFunction(Test2,int,double,boolean) | | test.kt:3:1:14:1 | Test | test.kt:12:3:12:121 | testMemberExtensionFunction | testMemberExtensionFunction(Test2,int,java.lang.String,double,boolean) | | test.kt:3:1:14:1 | Test | test.kt:12:3:12:121 | testMemberExtensionFunction | testMemberExtensionFunction(Test2,int,java.lang.String,double,float,boolean) | +| test.kt:3:1:14:1 | Test | test.kt:12:3:12:121 | testMemberExtensionFunction$default | testMemberExtensionFunction$default(Test2,Test,int,java.lang.String,double,float,boolean,int,java.lang.Object) | | test.kt:16:1:28:1 | Test2 | test.kt:16:34:28:1 | Test2 | Test2(int,double,boolean) | | test.kt:16:1:28:1 | Test2 | test.kt:16:34:28:1 | Test2 | Test2(int,java.lang.String,double,boolean) | | test.kt:16:1:28:1 | Test2 | test.kt:16:34:28:1 | Test2 | Test2(int,java.lang.String,double,float,boolean) | +| test.kt:16:1:28:1 | Test2 | test.kt:16:34:28:1 | Test2 | Test2(int,java.lang.String,double,float,boolean,int,kotlin.jvm.internal.DefaultConstructorMarker) | | test.kt:16:1:28:1 | Test2 | test.kt:24:5:24:117 | testStaticCompanionFunction | testStaticCompanionFunction(int,double,boolean) | | test.kt:16:1:28:1 | Test2 | test.kt:24:5:24:117 | testStaticCompanionFunction | testStaticCompanionFunction(int,java.lang.String,double,boolean) | | test.kt:16:1:28:1 | Test2 | test.kt:24:5:24:117 | testStaticCompanionFunction | testStaticCompanionFunction(int,java.lang.String,double,float,boolean) | @@ -36,13 +41,17 @@ | test.kt:18:3:26:3 | Companion | test.kt:21:5:21:111 | testCompanionFunction | testCompanionFunction(int,double,boolean) | | test.kt:18:3:26:3 | Companion | test.kt:21:5:21:111 | testCompanionFunction | testCompanionFunction(int,java.lang.String,double,boolean) | | test.kt:18:3:26:3 | Companion | test.kt:21:5:21:111 | testCompanionFunction | testCompanionFunction(int,java.lang.String,double,float,boolean) | +| test.kt:18:3:26:3 | Companion | test.kt:21:5:21:111 | testCompanionFunction$default | testCompanionFunction$default(Test2.Companion,int,java.lang.String,double,float,boolean,int,java.lang.Object) | | test.kt:18:3:26:3 | Companion | test.kt:24:5:24:117 | testStaticCompanionFunction | testStaticCompanionFunction(int,double,boolean) | | test.kt:18:3:26:3 | Companion | test.kt:24:5:24:117 | testStaticCompanionFunction | testStaticCompanionFunction(int,java.lang.String,double,boolean) | | test.kt:18:3:26:3 | Companion | test.kt:24:5:24:117 | testStaticCompanionFunction | testStaticCompanionFunction(int,java.lang.String,double,float,boolean) | +| test.kt:18:3:26:3 | Companion | test.kt:24:5:24:117 | testStaticCompanionFunction$default | testStaticCompanionFunction$default(Test2.Companion,int,java.lang.String,double,float,boolean,int,java.lang.Object) | | test.kt:30:1:42:1 | GenericTest | test.kt:30:43:42:1 | GenericTest | GenericTest(int,java.lang.Object,java.lang.Object) | | test.kt:30:1:42:1 | GenericTest | test.kt:30:43:42:1 | GenericTest | GenericTest(int,java.lang.Object,java.lang.String,java.lang.Object) | +| test.kt:30:1:42:1 | GenericTest | test.kt:30:43:42:1 | GenericTest | GenericTest(int,java.lang.Object,java.lang.String,java.lang.Object,int,kotlin.jvm.internal.DefaultConstructorMarker) | | test.kt:30:1:42:1 | GenericTest | test.kt:30:43:42:1 | GenericTest | GenericTest(java.lang.Object,java.lang.Object) | | test.kt:30:1:42:1 | GenericTest | test.kt:33:3:33:84 | testMemberFunction | testMemberFunction(int,java.lang.Object,java.lang.Object) | | test.kt:30:1:42:1 | GenericTest | test.kt:33:3:33:84 | testMemberFunction | testMemberFunction(int,java.lang.Object,java.lang.String,java.lang.Object) | | test.kt:30:1:42:1 | GenericTest | test.kt:33:3:33:84 | testMemberFunction | testMemberFunction(java.lang.Object,java.lang.Object) | +| test.kt:30:1:42:1 | GenericTest | test.kt:33:3:33:84 | testMemberFunction$default | testMemberFunction$default(GenericTest,int,java.lang.Object,java.lang.String,java.lang.Object,int,java.lang.Object) | | test.kt:30:1:42:1 | GenericTest | test.kt:35:3:40:3 | useSpecialised | useSpecialised(GenericTest,GenericTest) | diff --git a/java/ql/test/kotlin/library-tests/jvmoverloads_flow/test.expected b/java/ql/test/kotlin/library-tests/jvmoverloads_flow/test.expected index 831de93ea2d..d2740fc010a 100644 --- a/java/ql/test/kotlin/library-tests/jvmoverloads_flow/test.expected +++ b/java/ql/test/kotlin/library-tests/jvmoverloads_flow/test.expected @@ -1,21 +1,27 @@ -| User.java:9:30:9:37 | source(...) | test.kt:13:97:13:97 | s | -| User.java:10:30:10:37 | source(...) | test.kt:13:97:13:97 | s | -| User.java:14:37:14:44 | source(...) | test.kt:25:105:25:105 | s | -| User.java:15:37:15:44 | source(...) | test.kt:25:105:25:105 | s | -| User.java:19:28:19:35 | source(...) | test.kt:33:97:33:97 | s | -| User.java:20:28:20:35 | source(...) | test.kt:33:97:33:97 | s | -| User.java:24:28:24:35 | source(...) | test.kt:43:93:43:93 | s | -| User.java:25:28:25:35 | source(...) | test.kt:43:93:43:93 | s | -| User.java:29:45:29:52 | source(...) | test.kt:58:10:58:10 | s | -| User.java:30:45:30:52 | source(...) | test.kt:58:10:58:10 | s | -| User.java:34:61:34:68 | source(...) | test.kt:74:10:74:10 | s | -| User.java:35:61:35:68 | source(...) | test.kt:74:10:74:10 | s | -| User.java:38:28:38:35 | source(...) | test.kt:84:10:84:10 | y | -| User.java:39:20:39:27 | source(...) | test.kt:84:10:84:10 | y | -| test.kt:10:55:10:62 | source(...) | test.kt:10:84:10:84 | s | -| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | -| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | -| test.kt:30:55:30:62 | source(...) | test.kt:30:84:30:84 | s | -| test.kt:40:53:40:60 | source(...) | test.kt:40:80:40:80 | s | -| test.kt:47:92:47:99 | source(...) | test.kt:50:10:50:10 | s | -| test.kt:63:100:63:107 | source(...) | test.kt:66:10:66:10 | s | +| User.java:9:30:9:37 | source(...) | test.kt:13:97:13:97 | s | User.java:5:22:5:25 | test | +| User.java:10:30:10:37 | source(...) | test.kt:13:97:13:97 | s | User.java:5:22:5:25 | test | +| User.java:14:37:14:44 | source(...) | test.kt:25:105:25:105 | s | User.java:5:22:5:25 | test | +| User.java:15:37:15:44 | source(...) | test.kt:25:105:25:105 | s | User.java:5:22:5:25 | test | +| User.java:19:28:19:35 | source(...) | test.kt:33:97:33:97 | s | User.java:5:22:5:25 | test | +| User.java:20:28:20:35 | source(...) | test.kt:33:97:33:97 | s | User.java:5:22:5:25 | test | +| User.java:24:28:24:35 | source(...) | test.kt:43:93:43:93 | s | User.java:5:22:5:25 | test | +| User.java:25:28:25:35 | source(...) | test.kt:43:93:43:93 | s | User.java:5:22:5:25 | test | +| User.java:29:45:29:52 | source(...) | test.kt:58:10:58:10 | s | User.java:5:22:5:25 | test | +| User.java:30:45:30:52 | source(...) | test.kt:58:10:58:10 | s | User.java:5:22:5:25 | test | +| User.java:34:61:34:68 | source(...) | test.kt:74:10:74:10 | s | User.java:5:22:5:25 | test | +| User.java:35:61:35:68 | source(...) | test.kt:74:10:74:10 | s | User.java:5:22:5:25 | test | +| User.java:38:28:38:35 | source(...) | test.kt:84:10:84:10 | y | User.java:5:22:5:25 | test | +| User.java:39:20:39:27 | source(...) | test.kt:84:10:84:10 | y | User.java:5:22:5:25 | test | +| test.kt:10:55:10:62 | source(...) | test.kt:10:84:10:84 | s | test.kt:10:3:10:87 | taintSuppliedAsDefault | +| test.kt:10:55:10:62 | source(...) | test.kt:10:84:10:84 | s | test.kt:10:3:10:87 | taintSuppliedAsDefault$default | +| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | test.kt:22:5:22:95 | taintSuppliedAsDefaultStatic | +| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | test.kt:22:5:22:95 | taintSuppliedAsDefaultStatic | +| test.kt:22:63:22:70 | source(...) | test.kt:22:92:22:92 | s | test.kt:22:5:22:95 | taintSuppliedAsDefaultStatic$default | +| test.kt:30:55:30:62 | source(...) | test.kt:30:84:30:84 | s | test.kt:30:3:30:87 | taintSuppliedAsDefault | +| test.kt:30:55:30:62 | source(...) | test.kt:30:84:30:84 | s | test.kt:30:3:30:87 | taintSuppliedAsDefault$default | +| test.kt:40:53:40:60 | source(...) | test.kt:40:80:40:80 | s | test.kt:40:3:40:83 | taintSuppliedAsDefault | +| test.kt:40:53:40:60 | source(...) | test.kt:40:80:40:80 | s | test.kt:40:3:40:83 | taintSuppliedAsDefault$default | +| test.kt:47:92:47:99 | source(...) | test.kt:50:10:50:10 | s | test.kt:47:55:53:1 | ConstructorTaintsByDefault | +| test.kt:47:92:47:99 | source(...) | test.kt:50:10:50:10 | s | test.kt:47:55:53:1 | ConstructorTaintsByDefault | +| test.kt:63:100:63:107 | source(...) | test.kt:66:10:66:10 | s | test.kt:63:65:69:1 | GenericConstructorTaintsByDefault | +| test.kt:63:100:63:107 | source(...) | test.kt:66:10:66:10 | s | test.kt:63:65:69:1 | GenericConstructorTaintsByDefault | diff --git a/java/ql/test/kotlin/library-tests/jvmoverloads_flow/test.ql b/java/ql/test/kotlin/library-tests/jvmoverloads_flow/test.ql index 4ed01f80da8..05bdca7b7c9 100644 --- a/java/ql/test/kotlin/library-tests/jvmoverloads_flow/test.ql +++ b/java/ql/test/kotlin/library-tests/jvmoverloads_flow/test.ql @@ -15,4 +15,4 @@ class Config extends DataFlow::Configuration { from Config c, DataFlow::Node source, DataFlow::Node sink where c.hasFlow(source, sink) -select source, sink +select source, sink, source.getEnclosingCallable() diff --git a/java/ql/test/kotlin/library-tests/methods/clinit.expected b/java/ql/test/kotlin/library-tests/methods/clinit.expected index ea5b5392d82..3bf5f170f08 100644 --- a/java/ql/test/kotlin/library-tests/methods/clinit.expected +++ b/java/ql/test/kotlin/library-tests/methods/clinit.expected @@ -1,2 +1,3 @@ | clinit.kt:0:0:0:0 | | file://:0:0:0:0 | void | | enumClass.kt:0:0:0:0 | | file://:0:0:0:0 | void | +| enumClass.kt:0:0:0:0 | | file://:0:0:0:0 | void | diff --git a/java/ql/test/kotlin/library-tests/methods/enumClass.kt b/java/ql/test/kotlin/library-tests/methods/enumClass.kt index 89568c0d5f4..9f3acad608a 100644 --- a/java/ql/test/kotlin/library-tests/methods/enumClass.kt +++ b/java/ql/test/kotlin/library-tests/methods/enumClass.kt @@ -2,3 +2,15 @@ enum class EnumClass(val v: Int) { enum1(1), enum2(1) } + +enum class EnumWithFunctions { + + VAL { + override fun f(i: Int) = i + override fun g(i: Int) = this.f(i) + i + }; + + abstract fun f(i: Int): Int + abstract fun g(i: Int): Int + +} diff --git a/java/ql/test/kotlin/library-tests/methods/exprs.expected b/java/ql/test/kotlin/library-tests/methods/exprs.expected index 82122a7e9af..bf15f66b6ef 100644 --- a/java/ql/test/kotlin/library-tests/methods/exprs.expected +++ b/java/ql/test/kotlin/library-tests/methods/exprs.expected @@ -12,27 +12,42 @@ | clinit.kt:3:1:3:24 | int | TypeAccess | | clinit.kt:3:1:3:24 | int | TypeAccess | | clinit.kt:3:24:3:24 | 0 | IntegerLiteral | +| dataClass.kt:0:0:0:0 | 0 | IntegerLiteral | +| dataClass.kt:0:0:0:0 | 0 | IntegerLiteral | +| dataClass.kt:0:0:0:0 | 1 | IntegerLiteral | +| dataClass.kt:0:0:0:0 | 2 | IntegerLiteral | | dataClass.kt:0:0:0:0 | 31 | IntegerLiteral | | dataClass.kt:0:0:0:0 | "..." | StringTemplateExpr | | dataClass.kt:0:0:0:0 | (...)... | CastExpr | | dataClass.kt:0:0:0:0 | ) | StringLiteral | | dataClass.kt:0:0:0:0 | , | StringLiteral | | dataClass.kt:0:0:0:0 | ... !is ... | NotInstanceOfExpr | +| dataClass.kt:0:0:0:0 | ... & ... | AndBitwiseExpr | +| dataClass.kt:0:0:0:0 | ... & ... | AndBitwiseExpr | | dataClass.kt:0:0:0:0 | ... (value not-equals) ... | ValueNEExpr | | dataClass.kt:0:0:0:0 | ... (value not-equals) ... | ValueNEExpr | | dataClass.kt:0:0:0:0 | ... * ... | MulExpr | | dataClass.kt:0:0:0:0 | ... + ... | AddExpr | | dataClass.kt:0:0:0:0 | ... == ... | EQExpr | +| dataClass.kt:0:0:0:0 | ... == ... | EQExpr | +| dataClass.kt:0:0:0:0 | ... == ... | EQExpr | | dataClass.kt:0:0:0:0 | ...=... | AssignExpr | +| dataClass.kt:0:0:0:0 | ...=... | AssignExpr | +| dataClass.kt:0:0:0:0 | ...=... | AssignExpr | +| dataClass.kt:0:0:0:0 | DataClass | TypeAccess | +| dataClass.kt:0:0:0:0 | DataClass | TypeAccess | | dataClass.kt:0:0:0:0 | DataClass | TypeAccess | | dataClass.kt:0:0:0:0 | DataClass | TypeAccess | | dataClass.kt:0:0:0:0 | DataClass | TypeAccess | | dataClass.kt:0:0:0:0 | DataClass | TypeAccess | | dataClass.kt:0:0:0:0 | DataClass( | StringLiteral | | dataClass.kt:0:0:0:0 | Object | TypeAccess | +| dataClass.kt:0:0:0:0 | Object | TypeAccess | +| dataClass.kt:0:0:0:0 | String | TypeAccess | | dataClass.kt:0:0:0:0 | String | TypeAccess | | dataClass.kt:0:0:0:0 | String | TypeAccess | | dataClass.kt:0:0:0:0 | boolean | TypeAccess | +| dataClass.kt:0:0:0:0 | copy(...) | MethodAccess | | dataClass.kt:0:0:0:0 | false | BooleanLiteral | | dataClass.kt:0:0:0:0 | false | BooleanLiteral | | dataClass.kt:0:0:0:0 | false | BooleanLiteral | @@ -40,10 +55,23 @@ | dataClass.kt:0:0:0:0 | hashCode(...) | MethodAccess | | dataClass.kt:0:0:0:0 | int | TypeAccess | | dataClass.kt:0:0:0:0 | int | TypeAccess | +| dataClass.kt:0:0:0:0 | int | TypeAccess | +| dataClass.kt:0:0:0:0 | int | TypeAccess | | dataClass.kt:0:0:0:0 | new DataClass(...) | ClassInstanceExpr | | dataClass.kt:0:0:0:0 | other | VarAccess | | dataClass.kt:0:0:0:0 | other | VarAccess | | dataClass.kt:0:0:0:0 | other | VarAccess | +| dataClass.kt:0:0:0:0 | p0 | VarAccess | +| dataClass.kt:0:0:0:0 | p0 | VarAccess | +| dataClass.kt:0:0:0:0 | p0 | VarAccess | +| dataClass.kt:0:0:0:0 | p0.x | VarAccess | +| dataClass.kt:0:0:0:0 | p0.y | VarAccess | +| dataClass.kt:0:0:0:0 | p1 | VarAccess | +| dataClass.kt:0:0:0:0 | p1 | VarAccess | +| dataClass.kt:0:0:0:0 | p2 | VarAccess | +| dataClass.kt:0:0:0:0 | p2 | VarAccess | +| dataClass.kt:0:0:0:0 | p3 | VarAccess | +| dataClass.kt:0:0:0:0 | p3 | VarAccess | | dataClass.kt:0:0:0:0 | result | LocalVariableDeclExpr | | dataClass.kt:0:0:0:0 | result | VarAccess | | dataClass.kt:0:0:0:0 | result | VarAccess | @@ -198,6 +226,10 @@ | enumClass.kt:0:0:0:0 | EnumClass | TypeAccess | | enumClass.kt:0:0:0:0 | EnumClass | TypeAccess | | enumClass.kt:0:0:0:0 | EnumClass[] | TypeAccess | +| enumClass.kt:0:0:0:0 | EnumWithFunctions | TypeAccess | +| enumClass.kt:0:0:0:0 | EnumWithFunctions | TypeAccess | +| enumClass.kt:0:0:0:0 | EnumWithFunctions[] | TypeAccess | +| enumClass.kt:0:0:0:0 | String | TypeAccess | | enumClass.kt:0:0:0:0 | String | TypeAccess | | enumClass.kt:1:1:4:1 | Enum | TypeAccess | | enumClass.kt:1:1:4:1 | EnumClass | TypeAccess | @@ -224,6 +256,33 @@ | enumClass.kt:3:5:3:12 | EnumClass.enum2 | VarAccess | | enumClass.kt:3:5:3:12 | new EnumClass(...) | ClassInstanceExpr | | enumClass.kt:3:11:3:11 | 1 | IntegerLiteral | +| enumClass.kt:6:1:16:1 | Enum | TypeAccess | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | TypeAccess | +| enumClass.kt:6:1:16:1 | new Enum(...) | ClassInstanceExpr | +| enumClass.kt:8:3:11:4 | ...=... | KtInitializerAssignExpr | +| enumClass.kt:8:3:11:4 | | ImplicitCoercionToUnitExpr | +| enumClass.kt:8:3:11:4 | EnumWithFunctions | TypeAccess | +| enumClass.kt:8:3:11:4 | EnumWithFunctions | TypeAccess | +| enumClass.kt:8:3:11:4 | EnumWithFunctions | TypeAccess | +| enumClass.kt:8:3:11:4 | EnumWithFunctions.VAL | VarAccess | +| enumClass.kt:8:3:11:4 | Unit | TypeAccess | +| enumClass.kt:8:3:11:4 | VAL | TypeAccess | +| enumClass.kt:8:3:11:4 | new EnumWithFunctions(...) | ClassInstanceExpr | +| enumClass.kt:8:3:11:4 | new VAL(...) | ClassInstanceExpr | +| enumClass.kt:9:14:9:30 | int | TypeAccess | +| enumClass.kt:9:20:9:25 | int | TypeAccess | +| enumClass.kt:9:30:9:30 | i | VarAccess | +| enumClass.kt:10:14:10:42 | int | TypeAccess | +| enumClass.kt:10:20:10:25 | int | TypeAccess | +| enumClass.kt:10:30:10:33 | this | ThisAccess | +| enumClass.kt:10:30:10:42 | ... + ... | AddExpr | +| enumClass.kt:10:35:10:38 | f(...) | MethodAccess | +| enumClass.kt:10:37:10:37 | i | VarAccess | +| enumClass.kt:10:42:10:42 | i | VarAccess | +| enumClass.kt:13:12:13:29 | int | TypeAccess | +| enumClass.kt:13:18:13:23 | int | TypeAccess | +| enumClass.kt:14:12:14:29 | int | TypeAccess | +| enumClass.kt:14:18:14:23 | int | TypeAccess | | methods2.kt:4:1:5:1 | Unit | TypeAccess | | methods2.kt:4:26:4:31 | int | TypeAccess | | methods2.kt:4:34:4:39 | int | TypeAccess | diff --git a/java/ql/test/kotlin/library-tests/methods/methods.expected b/java/ql/test/kotlin/library-tests/methods/methods.expected index e68bc650ce6..8ee20aac587 100644 --- a/java/ql/test/kotlin/library-tests/methods/methods.expected +++ b/java/ql/test/kotlin/library-tests/methods/methods.expected @@ -5,6 +5,7 @@ methods | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | component1 | component1() | public | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | component2 | component2() | public | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | copy | copy(int,java.lang.String) | public | Compiler generated | +| dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | copy$default | copy$default(DataClass,int,java.lang.String,int,java.lang.Object) | public, static | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | equals | equals(java.lang.Object) | override, public | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | hashCode | hashCode() | override, public | Compiler generated | | dataClass.kt:1:1:1:47 | DataClass | dataClass.kt:0:0:0:0 | toString | toString() | override, public | Compiler generated | @@ -28,6 +29,13 @@ methods | enumClass.kt:1:1:4:1 | EnumClass | enumClass.kt:0:0:0:0 | valueOf | valueOf(java.lang.String) | public, static | Compiler generated | | enumClass.kt:1:1:4:1 | EnumClass | enumClass.kt:0:0:0:0 | values | values() | public, static | Compiler generated | | enumClass.kt:1:1:4:1 | EnumClass | enumClass.kt:1:22:1:31 | getV | getV() | public | Compiler generated | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:0:0:0:0 | | () | | Compiler generated | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:0:0:0:0 | valueOf | valueOf(java.lang.String) | public, static | Compiler generated | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:0:0:0:0 | values | values() | public, static | Compiler generated | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:13:12:13:29 | f | f(int) | public | | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:14:12:14:29 | g | g(int) | public | | +| enumClass.kt:8:3:11:4 | VAL | enumClass.kt:9:14:9:30 | f | f(int) | override, public | | +| enumClass.kt:8:3:11:4 | VAL | enumClass.kt:10:14:10:42 | g | g(int) | override, public | | | methods2.kt:0:0:0:0 | Methods2Kt | methods2.kt:4:1:5:1 | fooBarTopLevelMethod | fooBarTopLevelMethod(int,int) | public, static | | | methods2.kt:7:1:10:1 | Class2 | methods2.kt:8:5:9:5 | fooBarClassMethod | fooBarClassMethod(int,int) | public | | | methods3.kt:0:0:0:0 | Methods3Kt | methods3.kt:3:1:3:42 | fooBarTopLevelMethodExt | fooBarTopLevelMethodExt(int,int) | public, static | | @@ -55,6 +63,8 @@ constructors | delegates.kt:8:32:11:5 | new KMutableProperty1(...) { ... } | delegates.kt:8:32:11:5 | | | | delegates.kt:8:66:11:5 | new Function3,String,String,Unit>(...) { ... } | delegates.kt:8:66:11:5 | | | | enumClass.kt:1:1:4:1 | EnumClass | enumClass.kt:1:6:4:1 | EnumClass | EnumClass(int) | +| enumClass.kt:6:1:16:1 | EnumWithFunctions | enumClass.kt:6:6:16:1 | EnumWithFunctions | EnumWithFunctions() | +| enumClass.kt:8:3:11:4 | VAL | enumClass.kt:8:3:11:4 | VAL | VAL() | | methods2.kt:7:1:10:1 | Class2 | methods2.kt:7:1:10:1 | Class2 | Class2() | | methods3.kt:5:1:7:1 | Class3 | methods3.kt:5:1:7:1 | Class3 | Class3() | | methods4.kt:3:1:11:1 | NestedTest | methods4.kt:3:1:11:1 | NestedTest | NestedTest() | diff --git a/java/ql/test/kotlin/library-tests/methods/parameters.expected b/java/ql/test/kotlin/library-tests/methods/parameters.expected index 2b35e69e502..4475aeba459 100644 --- a/java/ql/test/kotlin/library-tests/methods/parameters.expected +++ b/java/ql/test/kotlin/library-tests/methods/parameters.expected @@ -1,6 +1,11 @@ | clinit.kt:3:1:3:24 | setTopLevelInt | clinit.kt:3:1:3:24 | | 0 | | dataClass.kt:0:0:0:0 | copy | dataClass.kt:1:22:1:31 | x | 0 | | dataClass.kt:0:0:0:0 | copy | dataClass.kt:1:34:1:46 | y | 1 | +| dataClass.kt:0:0:0:0 | copy$default | dataClass.kt:0:0:0:0 | p0 | 0 | +| dataClass.kt:0:0:0:0 | copy$default | dataClass.kt:0:0:0:0 | p1 | 1 | +| dataClass.kt:0:0:0:0 | copy$default | dataClass.kt:0:0:0:0 | p2 | 2 | +| dataClass.kt:0:0:0:0 | copy$default | dataClass.kt:0:0:0:0 | p3 | 3 | +| dataClass.kt:0:0:0:0 | copy$default | dataClass.kt:0:0:0:0 | p4 | 4 | | dataClass.kt:0:0:0:0 | equals | dataClass.kt:0:0:0:0 | other | 0 | | dataClass.kt:1:34:1:46 | setY | dataClass.kt:1:34:1:46 | | 0 | | delegates.kt:4:18:6:5 | get | delegates.kt:4:18:6:5 | a0 | 0 | @@ -18,6 +23,11 @@ | delegates.kt:8:66:11:5 | invoke | delegates.kt:9:15:9:17 | old | 1 | | delegates.kt:8:66:11:5 | invoke | delegates.kt:9:20:9:22 | new | 2 | | enumClass.kt:0:0:0:0 | valueOf | enumClass.kt:0:0:0:0 | value | 0 | +| enumClass.kt:0:0:0:0 | valueOf | enumClass.kt:0:0:0:0 | value | 0 | +| enumClass.kt:9:14:9:30 | f | enumClass.kt:9:20:9:25 | i | 0 | +| enumClass.kt:10:14:10:42 | g | enumClass.kt:10:20:10:25 | i | 0 | +| enumClass.kt:13:12:13:29 | f | enumClass.kt:13:18:13:23 | i | 0 | +| enumClass.kt:14:12:14:29 | g | enumClass.kt:14:18:14:23 | i | 0 | | methods2.kt:4:1:5:1 | fooBarTopLevelMethod | methods2.kt:4:26:4:31 | x | 0 | | methods2.kt:4:1:5:1 | fooBarTopLevelMethod | methods2.kt:4:34:4:39 | y | 1 | | methods2.kt:8:5:9:5 | fooBarClassMethod | methods2.kt:8:27:8:32 | x | 0 | diff --git a/java/ql/test/kotlin/library-tests/multiple_extensions/calls.expected b/java/ql/test/kotlin/library-tests/multiple_extensions/calls.expected index dd9c60f1a80..cb0e0eaf085 100644 --- a/java/ql/test/kotlin/library-tests/multiple_extensions/calls.expected +++ b/java/ql/test/kotlin/library-tests/multiple_extensions/calls.expected @@ -1,4 +1,4 @@ | PropertyReferenceDelegatesKt | getValue(KProperty0, Object, KProperty) | | PropertyReferenceDelegatesKt | getValue(KProperty1, T, KProperty) | | StringsKt | removePrefix(String, CharSequence) | -| StringsKt | startsWith(String, String, boolean) | +| StringsKt | startsWith$default(String, String, boolean, int, Object) | diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected new file mode 100644 index 00000000000..95198f2beaa --- /dev/null +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected @@ -0,0 +1,1223 @@ +test.kt: +# 0| [CompilationUnit] test +# 0| 1: [Class] TestKt +# 1| 1: [Method] sink +# 1| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 1| 0: [Parameter] a +# 1| 0: [TypeAccess] Object +# 1| 5: [BlockStmt] { ... } +# 3| 2: [Class] TestMember +# 3| 1: [Constructor] TestMember +# 3| 5: [BlockStmt] { ... } +# 3| 0: [SuperConstructorInvocationStmt] super(...) +# 3| 1: [BlockStmt] { ... } +# 5| 2: [Method] f +# 5| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 5| 0: [Parameter] x +# 5| 0: [TypeAccess] String +# 5| 1: [Parameter] y +# 5| 0: [TypeAccess] String +# 5| 2: [Parameter] z +# 5| 0: [TypeAccess] String +# 5| 5: [BlockStmt] { ... } +# 6| 0: [ExprStmt] ; +# 6| 0: [MethodAccess] sink(...) +# 6| -1: [TypeAccess] TestKt +# 6| 0: [VarAccess] y +# 5| 3: [Method] f$default +# 5| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 5| 0: [Parameter] p0 +# 5| 0: [TypeAccess] TestMember +# 5| 1: [Parameter] p1 +# 5| 0: [TypeAccess] String +# 5| 2: [Parameter] p2 +# 5| 0: [TypeAccess] String +# 5| 3: [Parameter] p3 +# 5| 0: [TypeAccess] String +# 5| 4: [Parameter] p4 +# 5| 0: [TypeAccess] int +# 5| 5: [Parameter] p5 +# 5| 0: [TypeAccess] Object +# 5| 5: [BlockStmt] { ... } +# 5| 0: [IfStmt] if (...) +# 5| 0: [EQExpr] ... == ... +# 5| 0: [AndBitwiseExpr] ... & ... +# 5| 0: [IntegerLiteral] 2 +# 5| 1: [VarAccess] p4 +# 5| 1: [IntegerLiteral] 0 +# 5| 1: [ExprStmt] ; +# 5| 0: [AssignExpr] ...=... +# 5| 0: [VarAccess] p2 +# 5| 1: [VarAccess] p1 +# 5| 1: [IfStmt] if (...) +# 5| 0: [EQExpr] ... == ... +# 5| 0: [AndBitwiseExpr] ... & ... +# 5| 0: [IntegerLiteral] 4 +# 5| 1: [VarAccess] p4 +# 5| 1: [IntegerLiteral] 0 +# 5| 1: [ExprStmt] ; +# 5| 0: [AssignExpr] ...=... +# 5| 0: [VarAccess] p3 +# 5| 1: [StringLiteral] hello world +# 5| 2: [ReturnStmt] return ... +# 5| 0: [MethodAccess] f(...) +# 5| -1: [VarAccess] p0 +# 5| 0: [VarAccess] p1 +# 5| 1: [VarAccess] p2 +# 5| 2: [VarAccess] p3 +# 9| 4: [Method] user +# 9| 3: [TypeAccess] Unit +# 9| 5: [BlockStmt] { ... } +# 10| 0: [ExprStmt] ; +# 10| 0: [MethodAccess] f$default(...) +# 10| -1: [TypeAccess] TestMember +# 10| 0: [ThisAccess] this +# 10| 1: [StringLiteral] member sunk +# 1| 2: [NullLiteral] null +# 1| 3: [NullLiteral] null +# 1| 4: [IntegerLiteral] 1 +# 1| 5: [NullLiteral] null +# 11| 1: [ExprStmt] ; +# 11| 0: [MethodAccess] f$default(...) +# 11| -1: [TypeAccess] TestMember +# 11| 0: [ThisAccess] this +# 11| 1: [StringLiteral] member sunk fp +# 11| 2: [StringLiteral] member sunk 2 +# 1| 3: [NullLiteral] null +# 1| 4: [IntegerLiteral] 3 +# 1| 5: [NullLiteral] null +# 12| 2: [ExprStmt] ; +# 12| 0: [MethodAccess] f(...) +# 12| -1: [ThisAccess] this +# 12| 0: [StringLiteral] not sunk +# 12| 1: [StringLiteral] member sunk 3 +# 12| 2: [StringLiteral] not sunk +# 17| 3: [Class] TestExtensionMember +# 17| 1: [Constructor] TestExtensionMember +# 17| 5: [BlockStmt] { ... } +# 17| 0: [SuperConstructorInvocationStmt] super(...) +# 17| 1: [BlockStmt] { ... } +# 19| 2: [ExtensionMethod] f +# 19| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 19| 0: [Parameter] +# 19| 0: [TypeAccess] String +# 19| 1: [Parameter] x +# 19| 0: [TypeAccess] String +# 19| 2: [Parameter] y +# 19| 0: [TypeAccess] String +# 19| 3: [Parameter] z +# 19| 0: [TypeAccess] String +# 19| 5: [BlockStmt] { ... } +# 20| 0: [ExprStmt] ; +# 20| 0: [MethodAccess] sink(...) +# 20| -1: [TypeAccess] TestKt +# 20| 0: [ExtensionReceiverAccess] this +# 21| 1: [ExprStmt] ; +# 21| 0: [MethodAccess] sink(...) +# 21| -1: [TypeAccess] TestKt +# 21| 0: [VarAccess] y +# 19| 3: [Method] f$default +# 19| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 19| 0: [Parameter] p0 +# 19| 0: [TypeAccess] String +# 19| 1: [Parameter] p1 +# 19| 0: [TypeAccess] TestExtensionMember +# 19| 2: [Parameter] p2 +# 19| 0: [TypeAccess] String +# 19| 3: [Parameter] p3 +# 19| 0: [TypeAccess] String +# 19| 4: [Parameter] p4 +# 19| 0: [TypeAccess] String +# 19| 5: [Parameter] p5 +# 19| 0: [TypeAccess] int +# 19| 6: [Parameter] p6 +# 19| 0: [TypeAccess] Object +# 19| 5: [BlockStmt] { ... } +# 19| 0: [IfStmt] if (...) +# 19| 0: [EQExpr] ... == ... +# 19| 0: [AndBitwiseExpr] ... & ... +# 19| 0: [IntegerLiteral] 2 +# 19| 1: [VarAccess] p5 +# 19| 1: [IntegerLiteral] 0 +# 19| 1: [ExprStmt] ; +# 19| 0: [AssignExpr] ...=... +# 19| 0: [VarAccess] p3 +# 19| 1: [VarAccess] p2 +# 19| 1: [IfStmt] if (...) +# 19| 0: [EQExpr] ... == ... +# 19| 0: [AndBitwiseExpr] ... & ... +# 19| 0: [IntegerLiteral] 4 +# 19| 1: [VarAccess] p5 +# 19| 1: [IntegerLiteral] 0 +# 19| 1: [ExprStmt] ; +# 19| 0: [AssignExpr] ...=... +# 19| 0: [VarAccess] p4 +# 19| 1: [StringLiteral] hello world +# 19| 2: [ReturnStmt] return ... +# 19| 0: [MethodAccess] f(...) +# 19| -1: [VarAccess] p1 +# 19| 0: [VarAccess] p0 +# 19| 1: [VarAccess] p2 +# 19| 2: [VarAccess] p3 +# 19| 3: [VarAccess] p4 +# 24| 4: [Method] user +# 24| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 24| 0: [Parameter] sunk +# 24| 0: [TypeAccess] String +# 24| 5: [BlockStmt] { ... } +# 25| 0: [ExprStmt] ; +# 25| 0: [MethodAccess] f$default(...) +# 25| -1: [TypeAccess] TestExtensionMember +# 25| 0: [VarAccess] sunk +# 25| 1: [ThisAccess] this +# 25| 2: [StringLiteral] extension sunk +# 1| 3: [NullLiteral] null +# 1| 4: [NullLiteral] null +# 1| 5: [IntegerLiteral] 1 +# 1| 6: [NullLiteral] null +# 26| 1: [ExprStmt] ; +# 26| 0: [MethodAccess] f$default(...) +# 26| -1: [TypeAccess] TestExtensionMember +# 26| 0: [VarAccess] sunk +# 26| 1: [ThisAccess] this +# 26| 2: [StringLiteral] extension sunk fp +# 26| 3: [StringLiteral] extension sunk 2 +# 1| 4: [NullLiteral] null +# 1| 5: [IntegerLiteral] 3 +# 1| 6: [NullLiteral] null +# 27| 2: [ExprStmt] ; +# 27| 0: [MethodAccess] f(...) +# 27| -1: [ThisAccess] this +# 27| 0: [VarAccess] sunk +# 27| 1: [StringLiteral] not sunk +# 27| 2: [StringLiteral] extension sunk 3 +# 27| 3: [StringLiteral] not sunk +# 32| 4: [Class] TestStaticMember +# 32| 1: [Constructor] TestStaticMember +# 32| 5: [BlockStmt] { ... } +# 32| 0: [SuperConstructorInvocationStmt] super(...) +# 32| 1: [BlockStmt] { ... } +# 34| 2: [Method] f +# 34| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 34| 0: [Parameter] x +# 34| 0: [TypeAccess] String +# 34| 1: [Parameter] y +# 34| 0: [TypeAccess] String +# 34| 2: [Parameter] z +# 34| 0: [TypeAccess] String +# 34| 5: [BlockStmt] { ... } +# 35| 0: [ExprStmt] ; +# 35| 0: [MethodAccess] sink(...) +# 35| -1: [TypeAccess] TestKt +# 35| 0: [VarAccess] y +# 34| 3: [Method] f$default +# 34| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 34| 0: [Parameter] p0 +# 34| 0: [TypeAccess] String +# 34| 1: [Parameter] p1 +# 34| 0: [TypeAccess] String +# 34| 2: [Parameter] p2 +# 34| 0: [TypeAccess] String +# 34| 3: [Parameter] p3 +# 34| 0: [TypeAccess] int +# 34| 4: [Parameter] p4 +# 34| 0: [TypeAccess] Object +# 34| 5: [BlockStmt] { ... } +# 34| 0: [IfStmt] if (...) +# 34| 0: [EQExpr] ... == ... +# 34| 0: [AndBitwiseExpr] ... & ... +# 34| 0: [IntegerLiteral] 2 +# 34| 1: [VarAccess] p3 +# 34| 1: [IntegerLiteral] 0 +# 34| 1: [ExprStmt] ; +# 34| 0: [AssignExpr] ...=... +# 34| 0: [VarAccess] p1 +# 34| 1: [VarAccess] p0 +# 34| 1: [IfStmt] if (...) +# 34| 0: [EQExpr] ... == ... +# 34| 0: [AndBitwiseExpr] ... & ... +# 34| 0: [IntegerLiteral] 4 +# 34| 1: [VarAccess] p3 +# 34| 1: [IntegerLiteral] 0 +# 34| 1: [ExprStmt] ; +# 34| 0: [AssignExpr] ...=... +# 34| 0: [VarAccess] p2 +# 34| 1: [StringLiteral] hello world +# 34| 2: [ReturnStmt] return ... +# 34| 0: [MethodAccess] f(...) +# 34| -1: [TypeAccess] TestStaticMember +# 34| 0: [VarAccess] p0 +# 34| 1: [VarAccess] p1 +# 34| 2: [VarAccess] p2 +# 38| 4: [Method] user +# 38| 3: [TypeAccess] Unit +# 38| 5: [BlockStmt] { ... } +# 39| 0: [ExprStmt] ; +# 39| 0: [MethodAccess] f$default(...) +# 39| -1: [TypeAccess] TestStaticMember +# 39| 0: [StringLiteral] static sunk +# 1| 1: [NullLiteral] null +# 1| 2: [NullLiteral] null +# 1| 3: [IntegerLiteral] 1 +# 1| 4: [NullLiteral] null +# 40| 1: [ExprStmt] ; +# 40| 0: [MethodAccess] f$default(...) +# 40| -1: [TypeAccess] TestStaticMember +# 40| 0: [StringLiteral] static sunk fp +# 40| 1: [StringLiteral] static sunk 2 +# 1| 2: [NullLiteral] null +# 1| 3: [IntegerLiteral] 3 +# 1| 4: [NullLiteral] null +# 41| 2: [ExprStmt] ; +# 41| 0: [MethodAccess] f(...) +# 41| -1: [TypeAccess] TestStaticMember +# 41| 0: [StringLiteral] not sunk +# 41| 1: [StringLiteral] static sunk 3 +# 41| 2: [StringLiteral] not sunk +# 46| 5: [Class] ExtendMe +# 46| 1: [Constructor] ExtendMe +# 46| 5: [BlockStmt] { ... } +# 46| 0: [SuperConstructorInvocationStmt] super(...) +# 46| 1: [BlockStmt] { ... } +# 48| 2: [Method] f +# 48| 3: [TypeAccess] String +#-----| 4: (Parameters) +# 48| 0: [Parameter] x +# 48| 0: [TypeAccess] String +# 48| 5: [BlockStmt] { ... } +# 48| 0: [ReturnStmt] return ... +# 48| 0: [VarAccess] x +# 52| 6: [Class] TestReceiverReferences +# 52| 1: [Constructor] TestReceiverReferences +# 52| 5: [BlockStmt] { ... } +# 52| 0: [SuperConstructorInvocationStmt] super(...) +# 52| 1: [BlockStmt] { ... } +# 54| 2: [Method] g +# 54| 3: [TypeAccess] String +#-----| 4: (Parameters) +# 54| 0: [Parameter] x +# 54| 0: [TypeAccess] String +# 54| 5: [BlockStmt] { ... } +# 54| 0: [ReturnStmt] return ... +# 54| 0: [VarAccess] x +# 56| 3: [ExtensionMethod] test +# 56| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 56| 0: [Parameter] +# 56| 0: [TypeAccess] ExtendMe +# 56| 1: [Parameter] x +# 56| 0: [TypeAccess] String +# 56| 2: [Parameter] y +# 56| 0: [TypeAccess] String +# 56| 3: [Parameter] z +# 56| 0: [TypeAccess] String +# 56| 5: [BlockStmt] { ... } +# 57| 0: [ExprStmt] ; +# 57| 0: [MethodAccess] sink(...) +# 57| -1: [TypeAccess] TestKt +# 57| 0: [VarAccess] y +# 56| 4: [Method] test$default +# 56| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 56| 0: [Parameter] p0 +# 56| 0: [TypeAccess] ExtendMe +# 56| 1: [Parameter] p1 +# 56| 0: [TypeAccess] TestReceiverReferences +# 56| 2: [Parameter] p2 +# 56| 0: [TypeAccess] String +# 56| 3: [Parameter] p3 +# 56| 0: [TypeAccess] String +# 56| 4: [Parameter] p4 +# 56| 0: [TypeAccess] String +# 56| 5: [Parameter] p5 +# 56| 0: [TypeAccess] int +# 56| 6: [Parameter] p6 +# 56| 0: [TypeAccess] Object +# 56| 5: [BlockStmt] { ... } +# 56| 0: [IfStmt] if (...) +# 56| 0: [EQExpr] ... == ... +# 56| 0: [AndBitwiseExpr] ... & ... +# 56| 0: [IntegerLiteral] 2 +# 56| 1: [VarAccess] p5 +# 56| 1: [IntegerLiteral] 0 +# 56| 1: [ExprStmt] ; +# 56| 0: [AssignExpr] ...=... +# 56| 0: [VarAccess] p3 +# 56| 1: [MethodAccess] f(...) +# 56| -1: [VarAccess] p0 +# 56| 0: [MethodAccess] g(...) +# 56| -1: [VarAccess] p1 +# 56| 0: [VarAccess] p2 +# 56| 1: [IfStmt] if (...) +# 56| 0: [EQExpr] ... == ... +# 56| 0: [AndBitwiseExpr] ... & ... +# 56| 0: [IntegerLiteral] 4 +# 56| 1: [VarAccess] p5 +# 56| 1: [IntegerLiteral] 0 +# 56| 1: [ExprStmt] ; +# 56| 0: [AssignExpr] ...=... +# 56| 0: [VarAccess] p4 +# 56| 1: [StringLiteral] hello world +# 56| 2: [ReturnStmt] return ... +# 56| 0: [MethodAccess] test(...) +# 56| -1: [VarAccess] p1 +# 56| 0: [VarAccess] p0 +# 56| 1: [VarAccess] p2 +# 56| 2: [VarAccess] p3 +# 56| 3: [VarAccess] p4 +# 60| 5: [Method] user +# 60| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 60| 0: [Parameter] t +# 60| 0: [TypeAccess] ExtendMe +# 60| 5: [BlockStmt] { ... } +# 61| 0: [ExprStmt] ; +# 61| 0: [MethodAccess] test$default(...) +# 61| -1: [TypeAccess] TestReceiverReferences +# 61| 0: [VarAccess] t +# 61| 1: [ThisAccess] this +# 61| 2: [StringLiteral] receiver refs sunk +# 1| 3: [NullLiteral] null +# 1| 4: [NullLiteral] null +# 1| 5: [IntegerLiteral] 1 +# 1| 6: [NullLiteral] null +# 62| 1: [ExprStmt] ; +# 62| 0: [MethodAccess] test$default(...) +# 62| -1: [TypeAccess] TestReceiverReferences +# 62| 0: [VarAccess] t +# 62| 1: [ThisAccess] this +# 62| 2: [StringLiteral] receiver refs sunk fp +# 62| 3: [StringLiteral] receiver refs sunk 2 +# 1| 4: [NullLiteral] null +# 1| 5: [IntegerLiteral] 3 +# 1| 6: [NullLiteral] null +# 63| 2: [ExprStmt] ; +# 63| 0: [MethodAccess] test(...) +# 63| -1: [ThisAccess] this +# 63| 0: [VarAccess] t +# 63| 1: [StringLiteral] not sunk +# 63| 2: [StringLiteral] receiver refs sunk 3 +# 63| 3: [StringLiteral] not sunk +# 68| 7: [Class] TestConstructor +# 68| 1: [Constructor] TestConstructor +#-----| 4: (Parameters) +# 68| 0: [Parameter] x +# 68| 0: [TypeAccess] String +# 68| 1: [Parameter] y +# 68| 0: [TypeAccess] String +# 68| 2: [Parameter] z +# 68| 0: [TypeAccess] String +# 68| 5: [BlockStmt] { ... } +# 68| 0: [SuperConstructorInvocationStmt] super(...) +# 68| 1: [BlockStmt] { ... } +# 71| 0: [ExprStmt] ; +# 71| 0: [MethodAccess] sink(...) +# 71| -1: [TypeAccess] TestKt +# 71| 0: [VarAccess] y +# 68| 2: [Constructor] TestConstructor +#-----| 4: (Parameters) +# 68| 0: [Parameter] p0 +# 68| 0: [TypeAccess] String +# 68| 1: [Parameter] p1 +# 68| 0: [TypeAccess] String +# 68| 2: [Parameter] p2 +# 68| 0: [TypeAccess] String +# 68| 3: [Parameter] p3 +# 68| 0: [TypeAccess] int +# 68| 4: [Parameter] p4 +# 68| 0: [TypeAccess] DefaultConstructorMarker +# 68| 5: [BlockStmt] { ... } +# 68| 0: [IfStmt] if (...) +# 68| 0: [EQExpr] ... == ... +# 68| 0: [AndBitwiseExpr] ... & ... +# 68| 0: [IntegerLiteral] 2 +# 68| 1: [VarAccess] p3 +# 68| 1: [IntegerLiteral] 0 +# 68| 1: [ExprStmt] ; +# 68| 0: [AssignExpr] ...=... +# 68| 0: [VarAccess] p1 +# 68| 1: [VarAccess] p0 +# 68| 1: [IfStmt] if (...) +# 68| 0: [EQExpr] ... == ... +# 68| 0: [AndBitwiseExpr] ... & ... +# 68| 0: [IntegerLiteral] 4 +# 68| 1: [VarAccess] p3 +# 68| 1: [IntegerLiteral] 0 +# 68| 1: [ExprStmt] ; +# 68| 0: [AssignExpr] ...=... +# 68| 0: [VarAccess] p2 +# 68| 1: [StringLiteral] hello world +# 68| 2: [ThisConstructorInvocationStmt] this(...) +# 68| 0: [VarAccess] p0 +# 68| 1: [VarAccess] p1 +# 68| 2: [VarAccess] p2 +# 74| 3: [Method] user +# 74| 3: [TypeAccess] Unit +# 74| 5: [BlockStmt] { ... } +# 75| 0: [ExprStmt] ; +# 75| 0: [ImplicitCoercionToUnitExpr] +# 75| 0: [TypeAccess] Unit +# 75| 1: [ClassInstanceExpr] new TestConstructor(...) +# 75| -3: [TypeAccess] TestConstructor +# 75| 0: [StringLiteral] constructor sunk +# 1| 1: [NullLiteral] null +# 1| 2: [NullLiteral] null +# 1| 3: [IntegerLiteral] 1 +# 1| 4: [NullLiteral] null +# 76| 1: [ExprStmt] ; +# 76| 0: [ImplicitCoercionToUnitExpr] +# 76| 0: [TypeAccess] Unit +# 76| 1: [ClassInstanceExpr] new TestConstructor(...) +# 76| -3: [TypeAccess] TestConstructor +# 76| 0: [StringLiteral] constructor sunk fp +# 76| 1: [StringLiteral] constructor sunk 2 +# 1| 2: [NullLiteral] null +# 1| 3: [IntegerLiteral] 3 +# 1| 4: [NullLiteral] null +# 77| 2: [ExprStmt] ; +# 77| 0: [ImplicitCoercionToUnitExpr] +# 77| 0: [TypeAccess] Unit +# 77| 1: [ClassInstanceExpr] new TestConstructor(...) +# 77| -3: [TypeAccess] TestConstructor +# 77| 0: [StringLiteral] not sunk +# 77| 1: [StringLiteral] constructor sunk 3 +# 77| 2: [StringLiteral] not sunk +# 82| 8: [Class] TestLocal +# 82| 1: [Constructor] TestLocal +# 82| 5: [BlockStmt] { ... } +# 82| 0: [SuperConstructorInvocationStmt] super(...) +# 82| 1: [BlockStmt] { ... } +# 84| 2: [Method] enclosing +# 84| 3: [TypeAccess] Unit +# 84| 5: [BlockStmt] { ... } +# 86| 0: [LocalTypeDeclStmt] class ... +# 86| 0: [LocalClass] +# 86| 1: [Constructor] +# 86| 5: [BlockStmt] { ... } +# 86| 0: [SuperConstructorInvocationStmt] super(...) +# 86| 2: [Method] f +# 86| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 86| 0: [Parameter] x +# 86| 0: [TypeAccess] String +# 86| 1: [Parameter] y +# 86| 0: [TypeAccess] String +# 86| 2: [Parameter] z +# 86| 0: [TypeAccess] String +# 86| 5: [BlockStmt] { ... } +# 87| 0: [ExprStmt] ; +# 87| 0: [MethodAccess] sink(...) +# 87| -1: [TypeAccess] TestKt +# 87| 0: [VarAccess] y +# 86| 3: [Method] f$default +# 86| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 86| 0: [Parameter] p0 +# 86| 0: [TypeAccess] String +# 86| 1: [Parameter] p1 +# 86| 0: [TypeAccess] String +# 86| 2: [Parameter] p2 +# 86| 0: [TypeAccess] String +# 86| 3: [Parameter] p3 +# 86| 0: [TypeAccess] int +# 86| 4: [Parameter] p4 +# 86| 0: [TypeAccess] Object +# 86| 5: [BlockStmt] { ... } +# 86| 0: [IfStmt] if (...) +# 86| 0: [EQExpr] ... == ... +# 86| 0: [AndBitwiseExpr] ... & ... +# 86| 0: [IntegerLiteral] 2 +# 86| 1: [VarAccess] p3 +# 86| 1: [IntegerLiteral] 0 +# 86| 1: [ExprStmt] ; +# 86| 0: [AssignExpr] ...=... +# 86| 0: [VarAccess] p1 +# 86| 1: [VarAccess] p0 +# 86| 1: [IfStmt] if (...) +# 86| 0: [EQExpr] ... == ... +# 86| 0: [AndBitwiseExpr] ... & ... +# 86| 0: [IntegerLiteral] 4 +# 86| 1: [VarAccess] p3 +# 86| 1: [IntegerLiteral] 0 +# 86| 1: [ExprStmt] ; +# 86| 0: [AssignExpr] ...=... +# 86| 0: [VarAccess] p2 +# 86| 1: [StringLiteral] hello world +# 86| 2: [ReturnStmt] return ... +# 86| 0: [MethodAccess] f(...) +# 86| -1: [ClassInstanceExpr] new (...) +# 86| -3: [TypeAccess] Object +# 86| 0: [VarAccess] p0 +# 86| 1: [VarAccess] p1 +# 86| 2: [VarAccess] p2 +# 90| 1: [LocalTypeDeclStmt] class ... +# 90| 0: [LocalClass] +# 90| 1: [Constructor] +# 90| 5: [BlockStmt] { ... } +# 90| 0: [SuperConstructorInvocationStmt] super(...) +# 90| 2: [Method] user +# 90| 3: [TypeAccess] Unit +# 90| 5: [BlockStmt] { ... } +# 91| 0: [ExprStmt] ; +# 91| 0: [MethodAccess] f$default(...) +# 91| -1: [TypeAccess] +# 91| 0: [StringLiteral] local sunk +# 1| 1: [NullLiteral] null +# 1| 2: [NullLiteral] null +# 1| 3: [IntegerLiteral] 1 +# 1| 4: [NullLiteral] null +# 92| 1: [ExprStmt] ; +# 92| 0: [MethodAccess] f$default(...) +# 92| -1: [TypeAccess] +# 92| 0: [StringLiteral] local sunk fp +# 92| 1: [StringLiteral] local sunk 2 +# 1| 2: [NullLiteral] null +# 1| 3: [IntegerLiteral] 3 +# 1| 4: [NullLiteral] null +# 93| 2: [ExprStmt] ; +# 93| 0: [MethodAccess] f(...) +# 93| -1: [ClassInstanceExpr] new (...) +# 93| -3: [TypeAccess] Object +# 93| 0: [StringLiteral] not sunk +# 93| 1: [StringLiteral] local sunk 3 +# 93| 2: [StringLiteral] not sunk +# 100| 9: [Class] TestLocalClass +# 100| 1: [Constructor] TestLocalClass +# 100| 5: [BlockStmt] { ... } +# 100| 0: [SuperConstructorInvocationStmt] super(...) +# 100| 1: [BlockStmt] { ... } +# 102| 2: [Method] enclosingFunction +# 102| 3: [TypeAccess] Unit +# 102| 5: [BlockStmt] { ... } +# 104| 0: [LocalTypeDeclStmt] class ... +# 104| 0: [LocalClass] EnclosingLocalClass +# 104| 1: [Constructor] EnclosingLocalClass +# 104| 5: [BlockStmt] { ... } +# 104| 0: [SuperConstructorInvocationStmt] super(...) +# 104| 1: [BlockStmt] { ... } +# 106| 2: [Method] f +# 106| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 106| 0: [Parameter] x +# 106| 0: [TypeAccess] String +# 106| 1: [Parameter] y +# 106| 0: [TypeAccess] String +# 106| 2: [Parameter] z +# 106| 0: [TypeAccess] String +# 106| 5: [BlockStmt] { ... } +# 107| 0: [ExprStmt] ; +# 107| 0: [MethodAccess] sink(...) +# 107| -1: [TypeAccess] TestKt +# 107| 0: [VarAccess] y +# 106| 3: [Method] f$default +# 106| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 106| 0: [Parameter] p0 +# 106| 0: [TypeAccess] EnclosingLocalClass +# 106| 1: [Parameter] p1 +# 106| 0: [TypeAccess] String +# 106| 2: [Parameter] p2 +# 106| 0: [TypeAccess] String +# 106| 3: [Parameter] p3 +# 106| 0: [TypeAccess] String +# 106| 4: [Parameter] p4 +# 106| 0: [TypeAccess] int +# 106| 5: [Parameter] p5 +# 106| 0: [TypeAccess] Object +# 106| 5: [BlockStmt] { ... } +# 106| 0: [IfStmt] if (...) +# 106| 0: [EQExpr] ... == ... +# 106| 0: [AndBitwiseExpr] ... & ... +# 106| 0: [IntegerLiteral] 2 +# 106| 1: [VarAccess] p4 +# 106| 1: [IntegerLiteral] 0 +# 106| 1: [ExprStmt] ; +# 106| 0: [AssignExpr] ...=... +# 106| 0: [VarAccess] p2 +# 106| 1: [VarAccess] p1 +# 106| 1: [IfStmt] if (...) +# 106| 0: [EQExpr] ... == ... +# 106| 0: [AndBitwiseExpr] ... & ... +# 106| 0: [IntegerLiteral] 4 +# 106| 1: [VarAccess] p4 +# 106| 1: [IntegerLiteral] 0 +# 106| 1: [ExprStmt] ; +# 106| 0: [AssignExpr] ...=... +# 106| 0: [VarAccess] p3 +# 106| 1: [StringLiteral] hello world +# 106| 2: [ReturnStmt] return ... +# 106| 0: [MethodAccess] f(...) +# 106| -1: [VarAccess] p0 +# 106| 0: [VarAccess] p1 +# 106| 1: [VarAccess] p2 +# 106| 2: [VarAccess] p3 +# 110| 4: [Method] user +# 110| 3: [TypeAccess] Unit +# 110| 5: [BlockStmt] { ... } +# 111| 0: [ExprStmt] ; +# 111| 0: [MethodAccess] f$default(...) +# 111| -1: [TypeAccess] EnclosingLocalClass +# 111| 0: [ThisAccess] this +# 111| 1: [StringLiteral] local sunk +# 1| 2: [NullLiteral] null +# 1| 3: [NullLiteral] null +# 1| 4: [IntegerLiteral] 1 +# 1| 5: [NullLiteral] null +# 112| 1: [ExprStmt] ; +# 112| 0: [MethodAccess] f$default(...) +# 112| -1: [TypeAccess] EnclosingLocalClass +# 112| 0: [ThisAccess] this +# 112| 1: [StringLiteral] local sunk fp +# 112| 2: [StringLiteral] local sunk 2 +# 1| 3: [NullLiteral] null +# 1| 4: [IntegerLiteral] 3 +# 1| 5: [NullLiteral] null +# 113| 2: [ExprStmt] ; +# 113| 0: [MethodAccess] f(...) +# 113| -1: [ThisAccess] this +# 113| 0: [StringLiteral] not sunk +# 113| 1: [StringLiteral] local sunk 3 +# 113| 2: [StringLiteral] not sunk +# 122| 10: [Class,GenericType,ParameterizedType] TestGeneric +#-----| -2: (Generic Parameters) +# 122| 0: [TypeVariable] T +# 122| 1: [Constructor] TestGeneric +# 122| 5: [BlockStmt] { ... } +# 122| 0: [SuperConstructorInvocationStmt] super(...) +# 122| 1: [BlockStmt] { ... } +# 124| 2: [Method] f +# 124| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 124| 0: [Parameter] x +# 124| 0: [TypeAccess] T +# 124| 1: [Parameter] y +# 124| 0: [TypeAccess] T +# 124| 2: [Parameter] z +# 124| 0: [TypeAccess] T +# 124| 5: [BlockStmt] { ... } +# 125| 0: [ExprStmt] ; +# 125| 0: [MethodAccess] sink(...) +# 125| -1: [TypeAccess] TestKt +# 125| 0: [VarAccess] y +# 124| 3: [Method] f$default +# 124| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 124| 0: [Parameter] p0 +# 124| 0: [TypeAccess] TestGeneric<> +# 124| 1: [Parameter] p1 +# 124| 0: [TypeAccess] Object +# 124| 2: [Parameter] p2 +# 124| 0: [TypeAccess] Object +# 124| 3: [Parameter] p3 +# 124| 0: [TypeAccess] Object +# 124| 4: [Parameter] p4 +# 124| 0: [TypeAccess] int +# 124| 5: [Parameter] p5 +# 124| 0: [TypeAccess] Object +# 124| 5: [BlockStmt] { ... } +# 124| 0: [IfStmt] if (...) +# 124| 0: [EQExpr] ... == ... +# 124| 0: [AndBitwiseExpr] ... & ... +# 124| 0: [IntegerLiteral] 2 +# 124| 1: [VarAccess] p4 +# 124| 1: [IntegerLiteral] 0 +# 124| 1: [ExprStmt] ; +# 124| 0: [AssignExpr] ...=... +# 124| 0: [VarAccess] p2 +# 124| 1: [VarAccess] p1 +# 124| 1: [IfStmt] if (...) +# 124| 0: [EQExpr] ... == ... +# 124| 0: [AndBitwiseExpr] ... & ... +# 124| 0: [IntegerLiteral] 4 +# 124| 1: [VarAccess] p4 +# 124| 1: [IntegerLiteral] 0 +# 124| 1: [ExprStmt] ; +# 124| 0: [AssignExpr] ...=... +# 124| 0: [VarAccess] p3 +# 124| 1: [NullLiteral] null +# 124| 2: [ReturnStmt] return ... +# 124| 0: [MethodAccess] f(...) +# 124| -1: [VarAccess] p0 +# 124| 0: [VarAccess] p1 +# 124| 1: [VarAccess] p2 +# 124| 2: [VarAccess] p3 +# 128| 4: [Method] user +# 128| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 128| 0: [Parameter] tgs +# 128| 0: [TypeAccess] TestGeneric +# 128| 0: [TypeAccess] String +# 128| 1: [Parameter] tcs +# 128| 0: [TypeAccess] TestGeneric +# 128| 0: [TypeAccess] CharSequence +# 128| 5: [BlockStmt] { ... } +# 129| 0: [ExprStmt] ; +# 129| 0: [MethodAccess] f$default(...) +# 129| -1: [TypeAccess] TestGeneric<> +# 129| 0: [VarAccess] tgs +# 129| 1: [StringLiteral] generic sunk +# 1| 2: [NullLiteral] null +# 1| 3: [NullLiteral] null +# 1| 4: [IntegerLiteral] 1 +# 1| 5: [NullLiteral] null +# 130| 1: [ExprStmt] ; +# 130| 0: [MethodAccess] f$default(...) +# 130| -1: [TypeAccess] TestGeneric<> +# 130| 0: [VarAccess] tcs +# 130| 1: [StringLiteral] generic sunk fp +# 130| 2: [StringLiteral] generic sunk 2 +# 1| 3: [NullLiteral] null +# 1| 4: [IntegerLiteral] 3 +# 1| 5: [NullLiteral] null +# 131| 2: [ExprStmt] ; +# 131| 0: [MethodAccess] f(...) +# 131| -1: [VarAccess] tgs +# 131| 0: [StringLiteral] not sunk +# 131| 1: [StringLiteral] generic sunk 3 +# 131| 2: [StringLiteral] not sunk +# 132| 3: [ExprStmt] ; +# 132| 0: [MethodAccess] f(...) +# 132| -1: [VarAccess] tcs +# 132| 0: [StringLiteral] not sunk +# 132| 1: [StringLiteral] generic sunk 3 +# 132| 2: [StringLiteral] not sunk +# 135| 5: [Method] testReturn +# 135| 3: [TypeAccess] T +#-----| 4: (Parameters) +# 135| 0: [Parameter] t1 +# 135| 0: [TypeAccess] T +# 135| 1: [Parameter] t2 +# 135| 0: [TypeAccess] T +# 135| 5: [BlockStmt] { ... } +# 135| 0: [ReturnStmt] return ... +# 135| 0: [VarAccess] t1 +# 135| 6: [Method] testReturn$default +# 135| 3: [TypeAccess] Object +#-----| 4: (Parameters) +# 135| 0: [Parameter] p0 +# 135| 0: [TypeAccess] TestGeneric<> +# 135| 1: [Parameter] p1 +# 135| 0: [TypeAccess] Object +# 135| 2: [Parameter] p2 +# 135| 0: [TypeAccess] Object +# 135| 3: [Parameter] p3 +# 135| 0: [TypeAccess] int +# 135| 4: [Parameter] p4 +# 135| 0: [TypeAccess] Object +# 135| 5: [BlockStmt] { ... } +# 135| 0: [IfStmt] if (...) +# 135| 0: [EQExpr] ... == ... +# 135| 0: [AndBitwiseExpr] ... & ... +# 135| 0: [IntegerLiteral] 2 +# 135| 1: [VarAccess] p3 +# 135| 1: [IntegerLiteral] 0 +# 135| 1: [ExprStmt] ; +# 135| 0: [AssignExpr] ...=... +# 135| 0: [VarAccess] p2 +# 135| 1: [NullLiteral] null +# 135| 1: [ReturnStmt] return ... +# 135| 0: [MethodAccess] testReturn(...) +# 135| -1: [VarAccess] p0 +# 135| 0: [VarAccess] p1 +# 135| 1: [VarAccess] p2 +# 137| 7: [Method] testReturnUser +# 137| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 137| 0: [Parameter] tgs +# 137| 0: [TypeAccess] TestGeneric +# 137| 0: [TypeAccess] String +# 137| 5: [BlockStmt] { ... } +# 138| 0: [ExprStmt] ; +# 138| 0: [MethodAccess] sink(...) +# 138| -1: [TypeAccess] TestKt +# 138| 0: [MethodAccess] testReturn$default(...) +# 138| -1: [TypeAccess] TestGeneric<> +# 138| 0: [VarAccess] tgs +# 138| 1: [StringLiteral] sunk return value +# 1| 2: [NullLiteral] null +# 1| 3: [IntegerLiteral] 1 +# 1| 4: [NullLiteral] null +# 143| 12: [Class,GenericType,ParameterizedType] TestGenericFunction +#-----| -2: (Generic Parameters) +# 143| 0: [TypeVariable] T +# 143| 1: [Constructor] TestGenericFunction +# 143| 5: [BlockStmt] { ... } +# 143| 0: [SuperConstructorInvocationStmt] super(...) +# 143| 1: [BlockStmt] { ... } +# 145| 2: [Method] f +#-----| 2: (Generic Parameters) +# 145| 0: [TypeVariable] S +# 145| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 145| 0: [Parameter] x +# 145| 0: [TypeAccess] S +# 145| 1: [Parameter] y +# 145| 0: [TypeAccess] T +# 145| 2: [Parameter] def1 +# 145| 0: [TypeAccess] T +# 145| 3: [Parameter] def2 +# 145| 0: [TypeAccess] List +# 145| 0: [WildcardTypeAccess] ? ... +# 145| 0: [TypeAccess] T +# 145| 4: [Parameter] def3 +# 145| 0: [TypeAccess] S +# 145| 5: [Parameter] def4 +# 145| 0: [TypeAccess] List +# 145| 0: [WildcardTypeAccess] ? ... +# 145| 0: [TypeAccess] S +# 145| 5: [BlockStmt] { ... } +# 146| 0: [ExprStmt] ; +# 146| 0: [MethodAccess] sink(...) +# 146| -1: [TypeAccess] TestKt +# 146| 0: [VarAccess] y +# 145| 3: [Method] f$default +# 145| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 145| 0: [Parameter] p0 +# 145| 0: [TypeAccess] TestGenericFunction<> +# 145| 1: [Parameter] p1 +# 145| 0: [TypeAccess] Object +# 145| 2: [Parameter] p2 +# 145| 0: [TypeAccess] Object +# 145| 3: [Parameter] p3 +# 145| 0: [TypeAccess] Object +# 145| 4: [Parameter] p4 +# 145| 0: [TypeAccess] List<> +# 145| 5: [Parameter] p5 +# 145| 0: [TypeAccess] Object +# 145| 6: [Parameter] p6 +# 145| 0: [TypeAccess] List<> +# 145| 7: [Parameter] p7 +# 145| 0: [TypeAccess] int +# 145| 8: [Parameter] p8 +# 145| 0: [TypeAccess] Object +# 145| 5: [BlockStmt] { ... } +# 145| 0: [IfStmt] if (...) +# 145| 0: [EQExpr] ... == ... +# 145| 0: [AndBitwiseExpr] ... & ... +# 145| 0: [IntegerLiteral] 2 +# 145| 1: [VarAccess] p7 +# 145| 1: [IntegerLiteral] 0 +# 145| 1: [ExprStmt] ; +# 145| 0: [AssignExpr] ...=... +# 145| 0: [VarAccess] p2 +# 145| 1: [VarAccess] p1 +# 145| 1: [IfStmt] if (...) +# 145| 0: [EQExpr] ... == ... +# 145| 0: [AndBitwiseExpr] ... & ... +# 145| 0: [IntegerLiteral] 4 +# 145| 1: [VarAccess] p7 +# 145| 1: [IntegerLiteral] 0 +# 145| 1: [ExprStmt] ; +# 145| 0: [AssignExpr] ...=... +# 145| 0: [VarAccess] p3 +# 145| 1: [NullLiteral] null +# 145| 2: [IfStmt] if (...) +# 145| 0: [EQExpr] ... == ... +# 145| 0: [AndBitwiseExpr] ... & ... +# 145| 0: [IntegerLiteral] 8 +# 145| 1: [VarAccess] p7 +# 145| 1: [IntegerLiteral] 0 +# 145| 1: [ExprStmt] ; +# 145| 0: [AssignExpr] ...=... +# 145| 0: [VarAccess] p4 +# 145| 1: [MethodAccess] listOf(...) +# 145| -2: [TypeAccess] Object +# 145| -1: [TypeAccess] CollectionsKt +# 145| 0: [VarAccess] p2 +# 145| 3: [IfStmt] if (...) +# 145| 0: [EQExpr] ... == ... +# 145| 0: [AndBitwiseExpr] ... & ... +# 145| 0: [IntegerLiteral] 16 +# 145| 1: [VarAccess] p7 +# 145| 1: [IntegerLiteral] 0 +# 145| 1: [ExprStmt] ; +# 145| 0: [AssignExpr] ...=... +# 145| 0: [VarAccess] p5 +# 145| 1: [NullLiteral] null +# 145| 4: [IfStmt] if (...) +# 145| 0: [EQExpr] ... == ... +# 145| 0: [AndBitwiseExpr] ... & ... +# 145| 0: [IntegerLiteral] 32 +# 145| 1: [VarAccess] p7 +# 145| 1: [IntegerLiteral] 0 +# 145| 1: [ExprStmt] ; +# 145| 0: [AssignExpr] ...=... +# 145| 0: [VarAccess] p6 +# 145| 1: [MethodAccess] listOf(...) +# 145| -2: [TypeAccess] Object +# 145| -1: [TypeAccess] CollectionsKt +# 145| 0: [VarAccess] p1 +# 145| 5: [ReturnStmt] return ... +# 145| 0: [MethodAccess] f(...) +# 145| -1: [VarAccess] p0 +# 145| 0: [VarAccess] p1 +# 145| 1: [VarAccess] p2 +# 145| 2: [VarAccess] p3 +# 145| 3: [VarAccess] p4 +# 145| 4: [VarAccess] p5 +# 145| 5: [VarAccess] p6 +# 149| 4: [Method] user +# 149| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 149| 0: [Parameter] inst +# 149| 0: [TypeAccess] TestGenericFunction +# 149| 0: [TypeAccess] String +# 149| 5: [BlockStmt] { ... } +# 150| 0: [ExprStmt] ; +# 150| 0: [MethodAccess] f$default(...) +# 150| -1: [TypeAccess] TestGenericFunction<> +# 150| 0: [VarAccess] inst +# 150| 1: [StringLiteral] generic function sunk +# 1| 2: [NullLiteral] null +# 1| 3: [NullLiteral] null +# 1| 4: [NullLiteral] null +# 1| 5: [NullLiteral] null +# 1| 6: [NullLiteral] null +# 1| 7: [IntegerLiteral] 1 +# 1| 8: [NullLiteral] null +# 151| 1: [ExprStmt] ; +# 151| 0: [MethodAccess] f$default(...) +# 151| -1: [TypeAccess] TestGenericFunction<> +# 151| 0: [VarAccess] inst +# 151| 1: [StringLiteral] generic function sunk fp +# 151| 2: [StringLiteral] generic function sunk 2 +# 1| 3: [NullLiteral] null +# 1| 4: [NullLiteral] null +# 1| 5: [NullLiteral] null +# 1| 6: [NullLiteral] null +# 1| 7: [IntegerLiteral] 3 +# 1| 8: [NullLiteral] null +# 156| 14: [Class] VisibilityTests +# 156| 1: [Constructor] VisibilityTests +# 156| 5: [BlockStmt] { ... } +# 156| 0: [SuperConstructorInvocationStmt] super(...) +# 156| 1: [BlockStmt] { ... } +# 158| 2: [Method] f +# 158| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 158| 0: [Parameter] x +# 158| 0: [TypeAccess] int +# 158| 1: [Parameter] y +# 158| 0: [TypeAccess] int +# 158| 5: [BlockStmt] { ... } +# 158| 0: [ReturnStmt] return ... +# 158| 0: [AddExpr] ... + ... +# 158| 0: [VarAccess] x +# 158| 1: [VarAccess] y +# 158| 3: [Method] f$default +# 158| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 158| 0: [Parameter] p0 +# 158| 0: [TypeAccess] VisibilityTests +# 158| 1: [Parameter] p1 +# 158| 0: [TypeAccess] int +# 158| 2: [Parameter] p2 +# 158| 0: [TypeAccess] int +# 158| 3: [Parameter] p3 +# 158| 0: [TypeAccess] int +# 158| 4: [Parameter] p4 +# 158| 0: [TypeAccess] Object +# 158| 5: [BlockStmt] { ... } +# 158| 0: [IfStmt] if (...) +# 158| 0: [EQExpr] ... == ... +# 158| 0: [AndBitwiseExpr] ... & ... +# 158| 0: [IntegerLiteral] 2 +# 158| 1: [VarAccess] p3 +# 158| 1: [IntegerLiteral] 0 +# 158| 1: [ExprStmt] ; +# 158| 0: [AssignExpr] ...=... +# 158| 0: [VarAccess] p2 +# 158| 1: [IntegerLiteral] 0 +# 158| 1: [ReturnStmt] return ... +# 158| 0: [MethodAccess] f(...) +# 158| -1: [VarAccess] p0 +# 158| 0: [VarAccess] p1 +# 158| 1: [VarAccess] p2 +# 159| 4: [Method] g$main +# 159| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 159| 0: [Parameter] x +# 159| 0: [TypeAccess] int +# 159| 1: [Parameter] y +# 159| 0: [TypeAccess] int +# 159| 5: [BlockStmt] { ... } +# 159| 0: [ReturnStmt] return ... +# 159| 0: [AddExpr] ... + ... +# 159| 0: [VarAccess] x +# 159| 1: [VarAccess] y +# 159| 5: [Method] g$main$default +# 159| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 159| 0: [Parameter] p0 +# 159| 0: [TypeAccess] VisibilityTests +# 159| 1: [Parameter] p1 +# 159| 0: [TypeAccess] int +# 159| 2: [Parameter] p2 +# 159| 0: [TypeAccess] int +# 159| 3: [Parameter] p3 +# 159| 0: [TypeAccess] int +# 159| 4: [Parameter] p4 +# 159| 0: [TypeAccess] Object +# 159| 5: [BlockStmt] { ... } +# 159| 0: [IfStmt] if (...) +# 159| 0: [EQExpr] ... == ... +# 159| 0: [AndBitwiseExpr] ... & ... +# 159| 0: [IntegerLiteral] 2 +# 159| 1: [VarAccess] p3 +# 159| 1: [IntegerLiteral] 0 +# 159| 1: [ExprStmt] ; +# 159| 0: [AssignExpr] ...=... +# 159| 0: [VarAccess] p2 +# 159| 1: [IntegerLiteral] 0 +# 159| 1: [ReturnStmt] return ... +# 159| 0: [MethodAccess] g$main(...) +# 159| -1: [VarAccess] p0 +# 159| 0: [VarAccess] p1 +# 159| 1: [VarAccess] p2 +# 160| 6: [Method] h +# 160| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 160| 0: [Parameter] x +# 160| 0: [TypeAccess] int +# 160| 1: [Parameter] y +# 160| 0: [TypeAccess] int +# 160| 5: [BlockStmt] { ... } +# 160| 0: [ReturnStmt] return ... +# 160| 0: [AddExpr] ... + ... +# 160| 0: [VarAccess] x +# 160| 1: [VarAccess] y +# 160| 7: [Method] h$default +# 160| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 160| 0: [Parameter] p0 +# 160| 0: [TypeAccess] VisibilityTests +# 160| 1: [Parameter] p1 +# 160| 0: [TypeAccess] int +# 160| 2: [Parameter] p2 +# 160| 0: [TypeAccess] int +# 160| 3: [Parameter] p3 +# 160| 0: [TypeAccess] int +# 160| 4: [Parameter] p4 +# 160| 0: [TypeAccess] Object +# 160| 5: [BlockStmt] { ... } +# 160| 0: [IfStmt] if (...) +# 160| 0: [EQExpr] ... == ... +# 160| 0: [AndBitwiseExpr] ... & ... +# 160| 0: [IntegerLiteral] 2 +# 160| 1: [VarAccess] p3 +# 160| 1: [IntegerLiteral] 0 +# 160| 1: [ExprStmt] ; +# 160| 0: [AssignExpr] ...=... +# 160| 0: [VarAccess] p2 +# 160| 1: [IntegerLiteral] 0 +# 160| 1: [ReturnStmt] return ... +# 160| 0: [MethodAccess] h(...) +# 160| -1: [VarAccess] p0 +# 160| 0: [VarAccess] p1 +# 160| 1: [VarAccess] p2 +# 161| 8: [Method] i +# 161| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 161| 0: [Parameter] x +# 161| 0: [TypeAccess] int +# 161| 1: [Parameter] y +# 161| 0: [TypeAccess] int +# 161| 5: [BlockStmt] { ... } +# 161| 0: [ReturnStmt] return ... +# 161| 0: [AddExpr] ... + ... +# 161| 0: [VarAccess] x +# 161| 1: [VarAccess] y +# 161| 9: [Method] i$default +# 161| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 161| 0: [Parameter] p0 +# 161| 0: [TypeAccess] VisibilityTests +# 161| 1: [Parameter] p1 +# 161| 0: [TypeAccess] int +# 161| 2: [Parameter] p2 +# 161| 0: [TypeAccess] int +# 161| 3: [Parameter] p3 +# 161| 0: [TypeAccess] int +# 161| 4: [Parameter] p4 +# 161| 0: [TypeAccess] Object +# 161| 5: [BlockStmt] { ... } +# 161| 0: [IfStmt] if (...) +# 161| 0: [EQExpr] ... == ... +# 161| 0: [AndBitwiseExpr] ... & ... +# 161| 0: [IntegerLiteral] 2 +# 161| 1: [VarAccess] p3 +# 161| 1: [IntegerLiteral] 0 +# 161| 1: [ExprStmt] ; +# 161| 0: [AssignExpr] ...=... +# 161| 0: [VarAccess] p2 +# 161| 1: [IntegerLiteral] 0 +# 161| 1: [ReturnStmt] return ... +# 161| 0: [MethodAccess] i(...) +# 161| -1: [VarAccess] p0 +# 161| 0: [VarAccess] p1 +# 161| 1: [VarAccess] p2 +# 165| 15: [Class,GenericType,ParameterizedType] TestGenericUsedWithinDefaultValue +#-----| -2: (Generic Parameters) +# 165| 0: [TypeVariable] T +# 165| 1: [Constructor] TestGenericUsedWithinDefaultValue +# 165| 5: [BlockStmt] { ... } +# 165| 0: [SuperConstructorInvocationStmt] super(...) +# 165| 1: [BlockStmt] { ... } +# 171| 2: [Method] f +# 171| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 171| 0: [Parameter] x +# 171| 0: [TypeAccess] int +# 171| 1: [Parameter] y +# 171| 0: [TypeAccess] String +# 171| 5: [BlockStmt] { ... } +# 171| 3: [Method] f$default +# 171| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 171| 0: [Parameter] p0 +# 171| 0: [TypeAccess] TestGenericUsedWithinDefaultValue<> +# 171| 1: [Parameter] p1 +# 171| 0: [TypeAccess] int +# 171| 2: [Parameter] p2 +# 171| 0: [TypeAccess] String +# 171| 3: [Parameter] p3 +# 171| 0: [TypeAccess] int +# 171| 4: [Parameter] p4 +# 171| 0: [TypeAccess] Object +# 171| 5: [BlockStmt] { ... } +# 171| 0: [IfStmt] if (...) +# 171| 0: [EQExpr] ... == ... +# 171| 0: [AndBitwiseExpr] ... & ... +# 171| 0: [IntegerLiteral] 2 +# 171| 1: [VarAccess] p3 +# 171| 1: [IntegerLiteral] 0 +# 171| 1: [ExprStmt] ; +# 171| 0: [AssignExpr] ...=... +# 171| 0: [VarAccess] p2 +# 171| 1: [MethodAccess] ident(...) +# 171| -1: [ClassInstanceExpr] new TestGenericUsedWithinDefaultValue(...) +# 171| -3: [TypeAccess] TestGenericUsedWithinDefaultValue +# 171| 0: [TypeAccess] String +# 171| 0: [StringLiteral] Hello world +# 171| 1: [ReturnStmt] return ... +# 171| 0: [MethodAccess] f(...) +# 171| -1: [VarAccess] p0 +# 171| 0: [VarAccess] p1 +# 171| 1: [VarAccess] p2 +# 173| 4: [Method] ident +# 173| 3: [TypeAccess] T +#-----| 4: (Parameters) +# 173| 0: [Parameter] t +# 173| 0: [TypeAccess] T +# 173| 5: [BlockStmt] { ... } +# 173| 0: [ReturnStmt] return ... +# 173| 0: [VarAccess] t diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.qlref b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.qlref new file mode 100644 index 00000000000..c7fd5faf239 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/java/PrintAst.ql \ No newline at end of file diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/erasure.expected b/java/ql/test/kotlin/library-tests/parameter-defaults/erasure.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/erasure.ql b/java/ql/test/kotlin/library-tests/parameter-defaults/erasure.ql new file mode 100644 index 00000000000..9bb2ad44c15 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/erasure.ql @@ -0,0 +1,19 @@ +import java + +class InstantiatedType extends ParameterizedType { + InstantiatedType() { typeArgs(_, _, this) } +} + +// This checks that all type parameter references are erased in the context of a $default function. +predicate containsTypeVariables(Type t) { + t instanceof TypeVariable or + containsTypeVariables(t.(InstantiatedType).getATypeArgument()) or + containsTypeVariables(t.(NestedType).getEnclosingType()) or + containsTypeVariables(t.(Wildcard).getATypeBound().getType()) +} + +from Expr e +where + e.getEnclosingCallable().getName().matches("%$default") and + containsTypeVariables(e.getType()) +select e, e.getType() diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/flowTest.expected b/java/ql/test/kotlin/library-tests/parameter-defaults/flowTest.expected new file mode 100644 index 00000000000..37b80612273 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/flowTest.expected @@ -0,0 +1,2 @@ +shouldBeSunkButIsnt +shouldntBeSunkButIs diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/flowTest.ql b/java/ql/test/kotlin/library-tests/parameter-defaults/flowTest.ql new file mode 100644 index 00000000000..28151ecdc85 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/flowTest.ql @@ -0,0 +1,34 @@ +import java +import semmle.code.java.dataflow.DataFlow + +class ShouldNotBeSunk extends StringLiteral { + ShouldNotBeSunk() { this.getValue().matches("%not sunk%") } +} + +class ShouldBeSunk extends StringLiteral { + ShouldBeSunk() { + this.getValue().matches("%sunk%") and + not this instanceof ShouldNotBeSunk + } +} + +class Config extends DataFlow::Configuration { + Config() { this = "Config" } + + override predicate isSource(DataFlow::Node n) { + n.asExpr() instanceof ShouldBeSunk or + n.asExpr() instanceof ShouldNotBeSunk + } + + override predicate isSink(DataFlow::Node n) { + n.asExpr().(Argument).getCall().getCallee().getName() = "sink" + } +} + +predicate isSunk(StringLiteral sl) { + exists(Config c, DataFlow::Node source | c.hasFlow(source, _) and sl = source.asExpr()) +} + +query predicate shouldBeSunkButIsnt(ShouldBeSunk src) { not isSunk(src) } + +query predicate shouldntBeSunkButIs(ShouldNotBeSunk src) { isSunk(src) } diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt b/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt new file mode 100644 index 00000000000..25a29fb468f --- /dev/null +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt @@ -0,0 +1,175 @@ +fun sink(a: Any?) { } + +class TestMember { + + fun f(x: String, y: String = x, z: String = "hello world") { + sink(y) + } + + fun user() { + f("member sunk") + f("member sunk fp", "member sunk 2") + f("not sunk", "member sunk 3", "not sunk") + } + +} + +class TestExtensionMember { + + fun String.f(x: String, y: String = x, z: String = "hello world") { + sink(this) + sink(y) + } + + fun user(sunk: String) { + sunk.f("extension sunk") + sunk.f("extension sunk fp", "extension sunk 2") + sunk.f("not sunk", "extension sunk 3", "not sunk") + } + +} + +object TestStaticMember { + + @JvmStatic fun f(x: String, y: String = x, z: String = "hello world") { + sink(y) + } + + fun user() { + f("static sunk") + f("static sunk fp", "static sunk 2") + f("not sunk", "static sunk 3", "not sunk") + } + +} + +class ExtendMe { + + fun f(x: String) = x + +} + +class TestReceiverReferences { + + fun g(x: String) = x + + fun ExtendMe.test(x: String, y: String = this.f(this@TestReceiverReferences.g(x)), z: String = "hello world") { + sink(y) + } + + fun user(t: ExtendMe) { + t.test("receiver refs sunk") + t.test("receiver refs sunk fp", "receiver refs sunk 2") + t.test("not sunk", "receiver refs sunk 3", "not sunk") + } + +} + +class TestConstructor(x: String, y: String = x, z: String = "hello world") { + + init { + sink(y) + } + + fun user() { + TestConstructor("constructor sunk") + TestConstructor("constructor sunk fp", "constructor sunk 2") + TestConstructor("not sunk", "constructor sunk 3", "not sunk") + } + +} + +class TestLocal { + + fun enclosing() { + + fun f(x: String, y: String = x, z: String = "hello world") { + sink(y) + } + + fun user() { + f("local sunk") + f("local sunk fp", "local sunk 2") + f("not sunk", "local sunk 3", "not sunk") + } + + } + +} + +class TestLocalClass { + + fun enclosingFunction() { + + class EnclosingLocalClass { + + fun f(x: String, y: String = x, z: String = "hello world") { + sink(y) + } + + fun user() { + f("local sunk") + f("local sunk fp", "local sunk 2") + f("not sunk", "local sunk 3", "not sunk") + } + + } + + } + +} + +class TestGeneric { + + fun f(x: T, y: T = x, z: T? = null) { + sink(y) + } + + fun user(tgs: TestGeneric, tcs: TestGeneric) { + tgs.f("generic sunk") + tcs.f("generic sunk fp", "generic sunk 2") + tgs.f("not sunk", "generic sunk 3", "not sunk") + tcs.f("not sunk", "generic sunk 3", "not sunk") + } + + fun testReturn(t1: T, t2: T? = null) = t1 + + fun testReturnUser(tgs: TestGeneric) { + sink(tgs.testReturn("sunk return value")) + } + +} + +class TestGenericFunction { + + fun f(x: S, y: T = x, def1: T? = null, def2: List = listOf(y), def3: S? = null, def4: List? = listOf(x)) { + sink(y) + } + + fun user(inst: TestGenericFunction) { + inst.f("generic function sunk") + inst.f("generic function sunk fp", "generic function sunk 2") + } + +} + +class VisibilityTests { + + fun f(x: Int, y: Int = 0) = x + y + internal fun g(x: Int, y: Int = 0) = x + y + protected fun h(x: Int, y: Int = 0) = x + y + private fun i(x: Int, y: Int = 0) = x + y + +} + +class TestGenericUsedWithinDefaultValue { + + // This tests parameter erasure works properly: we should notice that here the type variable T + // isn't used in the specialisation TestGenericUsedWithinDefaultValue, but it can be + // cited in contexts like "the signature of the source declaration of 'TestGenericUsedWithinDefaultValue.f(String)' is 'f(T)'", + // not 'f(Object)' as we might mistakenly conclude if we're inappropriately erasing 'T'. + fun f(x: Int, y: String = TestGenericUsedWithinDefaultValue().ident("Hello world")) { } + + fun ident(t: T) = t + +} diff --git a/java/ql/test/kotlin/library-tests/reflection/reflection.expected b/java/ql/test/kotlin/library-tests/reflection/reflection.expected index 12bbfb4db98..523ebd93d44 100644 --- a/java/ql/test/kotlin/library-tests/reflection/reflection.expected +++ b/java/ql/test/kotlin/library-tests/reflection/reflection.expected @@ -233,6 +233,7 @@ compGenerated | file:///Class2.class:0:0:0:0 | getValue | 3 | | file:///Class2.class:0:0:0:0 | getValue | 3 | | file:///KTypeProjection.class:0:0:0:0 | contravariant | 8 | +| file:///KTypeProjection.class:0:0:0:0 | copy$default | 10 | | file:///KTypeProjection.class:0:0:0:0 | covariant | 8 | | file:///KTypeProjection.class:0:0:0:0 | invariant | 8 | | reflection.kt:33:9:33:23 | getP0 | 3 | diff --git a/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.expected b/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.qlref b/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.qlref new file mode 100644 index 00000000000..6452bb942d2 --- /dev/null +++ b/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposeRepresentation.qlref @@ -0,0 +1 @@ +Violations of Best Practice/Implementation Hiding/ExposeRepresentation.ql diff --git a/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposesRep.kt b/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposesRep.kt new file mode 100644 index 00000000000..04d8f8f588d --- /dev/null +++ b/java/ql/test/kotlin/query-tests/ExposeRepresentation/ExposesRep.kt @@ -0,0 +1,3 @@ +class ExposesRep { + val strings: Array = arrayOfNulls(1) +} diff --git a/java/ql/test/kotlin/query-tests/ExposeRepresentation/User.kt b/java/ql/test/kotlin/query-tests/ExposeRepresentation/User.kt new file mode 100644 index 00000000000..aac812be0d0 --- /dev/null +++ b/java/ql/test/kotlin/query-tests/ExposeRepresentation/User.kt @@ -0,0 +1,5 @@ +class User { + fun test1(er: ExposesRep) { + er.strings[0] = "Hello world" + } +} diff --git a/java/ql/test/kotlin/query-tests/MissingInstanceofInEquals/Test.kt b/java/ql/test/kotlin/query-tests/MissingInstanceofInEquals/Test.kt index 7e8fa2619e2..f6252b5d3f2 100644 --- a/java/ql/test/kotlin/query-tests/MissingInstanceofInEquals/Test.kt +++ b/java/ql/test/kotlin/query-tests/MissingInstanceofInEquals/Test.kt @@ -5,3 +5,9 @@ data class E(val x: Int) { return (other as? E)?.x == this.x } } + +data class F(val x: Int) { + override fun equals(other: Any?): Boolean { + return other != null && other::class == this::class + } +} diff --git a/java/ql/test/library-tests/frameworks/android/intent/AndroidManifest.xml b/java/ql/test/library-tests/frameworks/android/intent/AndroidManifest.xml index 0be6a0ae8f8..0b7cc21200b 100644 --- a/java/ql/test/library-tests/frameworks/android/intent/AndroidManifest.xml +++ b/java/ql/test/library-tests/frameworks/android/intent/AndroidManifest.xml @@ -18,5 +18,30 @@ android:exported="false"> + + + + + + + + + + + + + + + diff --git a/java/ql/test/library-tests/frameworks/android/intent/TestStartActivityToGetIntent.java b/java/ql/test/library-tests/frameworks/android/intent/TestStartActivityToGetIntent.java index 3d497aac93d..35884a23a58 100644 --- a/java/ql/test/library-tests/frameworks/android/intent/TestStartActivityToGetIntent.java +++ b/java/ql/test/library-tests/frameworks/android/intent/TestStartActivityToGetIntent.java @@ -4,22 +4,90 @@ import android.content.Intent; public class TestStartActivityToGetIntent { - static Object source() { + static Object source(String kind) { return null; } static void sink(Object sink) {} - public void test(Context ctx) { - Intent intent = new Intent(null, SomeActivity.class); - intent.putExtra("data", (String) source()); - ctx.startActivity(intent); + public void test(Context ctx, Activity act) { + + // test all methods that start an activity + { + Intent intent = new Intent(null, SomeActivity.class); + intent.putExtra("data", (String) source("ctx-start")); + ctx.startActivity(intent); + } + { + Intent intent = new Intent(null, SomeActivity.class); + intent.putExtra("data", (String) source("ctx-start-acts")); + Intent[] intents = new Intent[] {intent}; + ctx.startActivities(intents); + } + { + Intent intent = new Intent(null, SomeActivity.class); + intent.putExtra("data", (String) source("act-start")); + act.startActivity(intent); + } + { + Intent intent = new Intent(null, SomeActivity.class); + intent.putExtra("data", (String) source("act-start-acts")); + Intent[] intents = new Intent[] {intent}; + act.startActivities(intents); + } + { + Intent intent = new Intent(null, SomeActivity.class); + intent.putExtra("data", (String) source("start-for-result")); + act.startActivityForResult(intent, 0); + } + { + Intent intent = new Intent(null, SomeActivity.class); + intent.putExtra("data", (String) source("start-if-needed")); + act.startActivityIfNeeded(intent, 0); + } + { + Intent intent = new Intent(null, SomeActivity.class); + intent.putExtra("data", (String) source("start-matching")); + act.startNextMatchingActivity(intent); + } + { + Intent intent = new Intent(null, SomeActivity.class); + intent.putExtra("data", (String) source("start-from-child")); + act.startActivityFromChild(null, intent, 0); + } + { + Intent intent = new Intent(null, SomeActivity.class); + intent.putExtra("data", (String) source("start-from-frag")); + act.startActivityFromFragment(null, intent, 0); + } + + // test 4-arg Intent constructor + { + Intent intent = new Intent(null, null, null, SomeActivity.class); + intent.putExtra("data", (String) source("4-arg")); + ctx.startActivity(intent); + } + + // safe test + { + Intent intent = new Intent(null, SafeActivity.class); + intent.putExtra("data", "safe"); + ctx.startActivity(intent); + } } static class SomeActivity extends Activity { public void test() { - sink(getIntent().getStringExtra("data")); // $ hasValueFlow + sink(getIntent().getStringExtra("data")); // $ hasValueFlow=ctx-start hasValueFlow=act-start hasValueFlow=start-for-result hasValueFlow=start-if-needed hasValueFlow=start-matching hasValueFlow=start-from-child hasValueFlow=start-from-frag hasValueFlow=4-arg MISSING: hasValueFlow=ctx-start-acts hasValueFlow=act-start-acts + } + + } + + static class SafeActivity extends Activity { + + public void test() { + sink(getIntent().getStringExtra("data")); // Safe } } } diff --git a/java/ql/test/library-tests/frameworks/android/intent/TestStartBroadcastReceiverToIntent.java b/java/ql/test/library-tests/frameworks/android/intent/TestStartBroadcastReceiverToIntent.java new file mode 100644 index 00000000000..f317b3ed2e8 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/intent/TestStartBroadcastReceiverToIntent.java @@ -0,0 +1,93 @@ +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +public class TestStartBroadcastReceiverToIntent { + + static Object source(String kind) { + return null; + } + + static void sink(Object sink) {} + + public void test(Context ctx) { + + // test all methods that send a broadcast + { + Intent intent = new Intent(null, SomeBroadcastReceiver.class); + intent.putExtra("data", (String) source("send")); + ctx.sendBroadcast(intent); + } + { + Intent intent = new Intent(null, SomeBroadcastReceiver.class); + intent.putExtra("data", (String) source("send-as-user")); + ctx.sendBroadcastAsUser(intent, null); + } + { + Intent intent = new Intent(null, SomeBroadcastReceiver.class); + intent.putExtra("data", (String) source("send-with-perm")); + ctx.sendBroadcastWithMultiplePermissions(intent, null); + } + { + Intent intent = new Intent(null, SomeBroadcastReceiver.class); + intent.putExtra("data", (String) source("send-ordered")); + ctx.sendOrderedBroadcast(intent, null); + } + { + Intent intent = new Intent(null, SomeBroadcastReceiver.class); + intent.putExtra("data", (String) source("send-ordered-as-user")); + ctx.sendOrderedBroadcastAsUser(intent, null, null, null, null, 0, null, null); + } + { + Intent intent = new Intent(null, SomeBroadcastReceiver.class); + intent.putExtra("data", (String) source("send-sticky")); + ctx.sendStickyBroadcast(intent); + } + { + Intent intent = new Intent(null, SomeBroadcastReceiver.class); + intent.putExtra("data", (String) source("send-sticky-as-user")); + ctx.sendStickyBroadcastAsUser(intent, null); + } + { + Intent intent = new Intent(null, SomeBroadcastReceiver.class); + intent.putExtra("data", (String) source("send-sticky-ordered")); + ctx.sendStickyOrderedBroadcast(intent, null, null, 0, null, null); + } + { + Intent intent = new Intent(null, SomeBroadcastReceiver.class); + intent.putExtra("data", (String) source("send-sticky-ordered-as-user")); + ctx.sendStickyOrderedBroadcastAsUser(intent, null, null, null, 0, null, null); + } + + // test 4-arg Intent constructor + { + Intent intent = new Intent(null, null, null, SomeBroadcastReceiver.class); + intent.putExtra("data", (String) source("4-arg")); + ctx.sendBroadcast(intent); + } + + // safe test + { + Intent intent = new Intent(null, SafeBroadcastReceiver.class); + intent.putExtra("data", "safe"); + ctx.sendBroadcast(intent); + } + } + + static class SomeBroadcastReceiver extends BroadcastReceiver { + + // test method that receives an Intent as a parameter + @Override + public void onReceive(Context context, Intent intent) { + sink(intent.getStringExtra("data")); // $ hasValueFlow=send hasValueFlow=send-as-user hasValueFlow=send-with-perm hasValueFlow=send-ordered hasValueFlow=send-ordered-as-user hasValueFlow=send-sticky hasValueFlow=send-sticky-as-user hasValueFlow=send-sticky-ordered hasValueFlow=send-sticky-ordered-as-user hasValueFlow=4-arg + } + } + + static class SafeBroadcastReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + sink(intent.getStringExtra("data")); // Safe + } + } +} diff --git a/java/ql/test/library-tests/frameworks/android/intent/TestStartServiceToIntent.java b/java/ql/test/library-tests/frameworks/android/intent/TestStartServiceToIntent.java new file mode 100644 index 00000000000..98404eed1b7 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/android/intent/TestStartServiceToIntent.java @@ -0,0 +1,130 @@ +import android.app.Service; +import android.os.IBinder; +import android.content.Context; +import android.content.Intent; + +public class TestStartServiceToIntent { + + static Object source(String kind) { + return null; + } + + static void sink(Object sink) {} + + public void test(Context ctx) { + + // test all methods that start a service + { + Intent intent = new Intent(null, SomeService.class); + intent.putExtra("data", (String) source("bind")); + ctx.bindService(intent, null, 0); + } + { + Intent intent = new Intent(null, SomeService.class); + intent.putExtra("data", (String) source("bind-as-user")); + ctx.bindServiceAsUser(intent, null, 0, null); + } + { + Intent intent = new Intent(null, SomeService.class); + intent.putExtra("data", (String) source("bind-isolated")); + ctx.bindIsolatedService(intent, 0, null, null, null); + } + { + Intent intent = new Intent(null, SomeService.class); + intent.putExtra("data", (String) source("start")); + ctx.startService(intent); + } + { + Intent intent = new Intent(null, SomeService.class); + intent.putExtra("data", (String) source("start-foreground")); + ctx.startForegroundService(intent); + } + + // test 4-arg Intent constructor + { + Intent intent = new Intent(null, null, null, SomeService.class); + intent.putExtra("data", (String) source("4-arg")); + ctx.startService(intent); + } + + // safe test + { + Intent intent = new Intent(null, SafeService.class); + intent.putExtra("data", "safe"); + ctx.startService(intent); + } + } + + static class SomeService extends Service { + + // test methods that receive an Intent as a parameter + @Override + public void onStart(Intent intent, int startId) { + sink(intent.getStringExtra("data")); // $ hasValueFlow=bind hasValueFlow=bind-as-user hasValueFlow=bind-isolated hasValueFlow=start hasValueFlow=start-foreground hasValueFlow=4-arg + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + sink(intent.getStringExtra("data")); // $ hasValueFlow=bind hasValueFlow=bind-as-user hasValueFlow=bind-isolated hasValueFlow=start hasValueFlow=start-foreground hasValueFlow=4-arg + return -1; + } + + @Override + public IBinder onBind(Intent intent) { + sink(intent.getStringExtra("data")); // $ hasValueFlow=bind hasValueFlow=bind-as-user hasValueFlow=bind-isolated hasValueFlow=start hasValueFlow=start-foreground hasValueFlow=4-arg + return null; + } + + @Override + public boolean onUnbind(Intent intent) { + sink(intent.getStringExtra("data")); // $ hasValueFlow=bind hasValueFlow=bind-as-user hasValueFlow=bind-isolated hasValueFlow=start hasValueFlow=start-foreground hasValueFlow=4-arg + return false; + } + + @Override + public void onRebind(Intent intent) { + sink(intent.getStringExtra("data")); // $ hasValueFlow=bind hasValueFlow=bind-as-user hasValueFlow=bind-isolated hasValueFlow=start hasValueFlow=start-foreground hasValueFlow=4-arg + } + + @Override + public void onTaskRemoved(Intent intent) { + sink(intent.getStringExtra("data")); // $ hasValueFlow=bind hasValueFlow=bind-as-user hasValueFlow=bind-isolated hasValueFlow=start hasValueFlow=start-foreground hasValueFlow=4-arg + } + } + + static class SafeService extends Service { + + @Override + public void onStart(Intent intent, int startId) { + sink(intent.getStringExtra("data")); // Safe + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + sink(intent.getStringExtra("data")); // Safe + return -1; + } + + @Override + public IBinder onBind(Intent intent) { + sink(intent.getStringExtra("data")); // Safe + return null; + } + + @Override + public boolean onUnbind(Intent intent) { + sink(intent.getStringExtra("data")); // Safe + return false; + } + + @Override + public void onRebind(Intent intent) { + sink(intent.getStringExtra("data")); // Safe + } + + @Override + public void onTaskRemoved(Intent intent) { + sink(intent.getStringExtra("data")); // Safe + } + } +} diff --git a/javascript/ql/lib/CHANGELOG.md b/javascript/ql/lib/CHANGELOG.md index d85a14dca02..de3424c2f4d 100644 --- a/javascript/ql/lib/CHANGELOG.md +++ b/javascript/ql/lib/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.3.1 + +### Minor Analysis Improvements + +- Several of the SQL and NoSQL library models have improved, leading to more results for the `js/sql-injection` query, + and in some cases the `js/missing-rate-limiting` query. + ## 0.3.0 ### Breaking Changes diff --git a/javascript/ql/lib/change-notes/2022-09-06-type-defs-squashed.md b/javascript/ql/lib/change-notes/released/0.3.1.md similarity index 80% rename from javascript/ql/lib/change-notes/2022-09-06-type-defs-squashed.md rename to javascript/ql/lib/change-notes/released/0.3.1.md index 9e628b394dc..81c8ef9fcff 100644 --- a/javascript/ql/lib/change-notes/2022-09-06-type-defs-squashed.md +++ b/javascript/ql/lib/change-notes/released/0.3.1.md @@ -1,6 +1,6 @@ ---- -category: minorAnalysis ---- +## 0.3.1 + +### Minor Analysis Improvements - Several of the SQL and NoSQL library models have improved, leading to more results for the `js/sql-injection` query, and in some cases the `js/missing-rate-limiting` query. diff --git a/javascript/ql/lib/codeql-pack.release.yml b/javascript/ql/lib/codeql-pack.release.yml index 95f6e3a0ba6..bb106b1cb63 100644 --- a/javascript/ql/lib/codeql-pack.release.yml +++ b/javascript/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.0 +lastReleaseVersion: 0.3.1 diff --git a/javascript/ql/lib/qlpack.yml b/javascript/ql/lib/qlpack.yml index 0cf4b33407a..d5442a13f13 100644 --- a/javascript/ql/lib/qlpack.yml +++ b/javascript/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-all -version: 0.3.1-dev +version: 0.3.2-dev groups: javascript dbscheme: semmlecode.javascript.dbscheme extractor: javascript diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll index 5147bcf7f2a..2e7a9dd4f34 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll @@ -711,13 +711,31 @@ module TaintTracking { } } + /** + * Gets a local source of any part of the input to the given stringification `call`. + */ + pragma[nomagic] + private DataFlow::Node getAJsonLocalInput(JsonStringifyCall call) { + result = call.getInput() + or + exists(DataFlow::SourceNode source | + source = pragma[only_bind_out](getAJsonLocalInput(call)).getALocalSource() + | + result = source.getAPropertyWrite().getRhs() + or + result = source.(DataFlow::ObjectLiteralNode).getASpreadProperty() + or + result = source.(DataFlow::ArrayCreationNode).getASpreadArgument() + ) + } + /** * A taint propagating data flow edge arising from JSON unparsing. */ private class JsonStringifyTaintStep extends SharedTaintStep { override predicate serializeStep(DataFlow::Node pred, DataFlow::Node succ) { exists(JsonStringifyCall call | - pred = call.getArgument(0) and + pred = getAJsonLocalInput(call) and succ = call ) } diff --git a/javascript/ql/src/CHANGELOG.md b/javascript/ql/src/CHANGELOG.md index a5e41a1e50a..b166176b56f 100644 --- a/javascript/ql/src/CHANGELOG.md +++ b/javascript/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.1 + +No user-facing changes. + ## 0.4.0 ### Minor Analysis Improvements diff --git a/javascript/ql/src/change-notes/2022-10-04-json-stringify-improvement.md b/javascript/ql/src/change-notes/2022-10-04-json-stringify-improvement.md new file mode 100644 index 00000000000..0480c231a16 --- /dev/null +++ b/javascript/ql/src/change-notes/2022-10-04-json-stringify-improvement.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Improved taint tracking through `JSON.stringify` in cases where a tainted value is stored somewhere in the input object. diff --git a/javascript/ql/src/change-notes/released/0.4.1.md b/javascript/ql/src/change-notes/released/0.4.1.md new file mode 100644 index 00000000000..0d865d0571e --- /dev/null +++ b/javascript/ql/src/change-notes/released/0.4.1.md @@ -0,0 +1,3 @@ +## 0.4.1 + +No user-facing changes. diff --git a/javascript/ql/src/codeql-pack.release.yml b/javascript/ql/src/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/javascript/ql/src/codeql-pack.release.yml +++ b/javascript/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/javascript/ql/src/qlpack.yml b/javascript/ql/src/qlpack.yml index 44ac00e5caf..c3157ce5043 100644 --- a/javascript/ql/src/qlpack.yml +++ b/javascript/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-queries -version: 0.4.1-dev +version: 0.4.2-dev groups: - javascript - queries 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 3effc99fcb3..4582ba675a4 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,22 @@ nodes | jquery.js:34:5:34:25 | '' + ... '' | | jquery.js:34:5:34:25 | '' + ... '' | | jquery.js:34:13:34:16 | hash | +| 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") | +| json-stringify.jsx:5:18:5:36 | req.param("locale") | +| json-stringify.jsx:5:18:5:36 | req.param("locale") | +| json-stringify.jsx:11:16:11:58 | `https: ... ocale}` | +| json-stringify.jsx:11:51:11:56 | locale | +| json-stringify.jsx:19:16:19:63 | `https: ... ocale}` | +| json-stringify.jsx:19:56:19:61 | locale | +| json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | +| json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | +| json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | +| json-stringify.jsx:31:55:31:60 | locale | +| json-stringify.jsx:31:55:31:60 | locale | +| json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | +| json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | | jwt-server.js:7:9:7:35 | taint | | jwt-server.js:7:9:7:35 | taint | | jwt-server.js:7:17:7:35 | req.param("wobble") | @@ -1509,6 +1525,24 @@ 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 | '' + ... '' | +| 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 | +| json-stringify.jsx:5:9:5:36 | locale | json-stringify.jsx:31:55:31:60 | locale | +| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:5:9:5:36 | locale | +| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:5:9:5:36 | locale | +| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:5:9:5:36 | locale | +| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:5:9:5:36 | locale | +| json-stringify.jsx:11:16:11:58 | `https: ... ocale}` | json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | +| json-stringify.jsx:11:16:11:58 | `https: ... ocale}` | json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | +| json-stringify.jsx:11:51:11:56 | locale | json-stringify.jsx:11:16:11:58 | `https: ... ocale}` | +| json-stringify.jsx:19:16:19:63 | `https: ... ocale}` | json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | +| json-stringify.jsx:19:16:19:63 | `https: ... ocale}` | json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | +| json-stringify.jsx:19:56:19:61 | locale | json-stringify.jsx:19:16:19:63 | `https: ... ocale}` | +| json-stringify.jsx:31:55:31:60 | locale | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | +| json-stringify.jsx:31:55:31:60 | locale | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | +| json-stringify.jsx:31:55:31:60 | locale | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | +| json-stringify.jsx:31:55:31:60 | locale | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | | jwt-server.js:7:9:7:35 | taint | jwt-server.js:9:16:9:20 | taint | | jwt-server.js:7:9:7:35 | taint | jwt-server.js:9:16:9:20 | taint | | jwt-server.js:7:17:7:35 | req.param("wobble") | jwt-server.js:7:9:7:35 | taint | @@ -2241,6 +2275,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 | +| 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 | | nodemailer.js:13:11:13:69 | `Hi, yo ... sage}.` | nodemailer.js:13:50:13:66 | req.query.message | nodemailer.js:13:11:13:69 | `Hi, yo ... sage}.` | HTML injection vulnerability due to $@. | nodemailer.js:13:50:13:66 | req.query.message | user-provided value | | optionalSanitizer.js:6:18:6:23 | target | optionalSanitizer.js:2:16:2:39 | documen ... .search | optionalSanitizer.js:6:18:6:23 | target | Cross-site scripting vulnerability due to $@. | optionalSanitizer.js:2:16:2:39 | documen ... .search | 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 fa65ccbe3df..5c5232b11d2 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,22 @@ nodes | jquery.js:34:5:34:25 | '' + ... '' | | jquery.js:34:5:34:25 | '' + ... '' | | jquery.js:34:13:34:16 | hash | +| 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") | +| json-stringify.jsx:5:18:5:36 | req.param("locale") | +| json-stringify.jsx:5:18:5:36 | req.param("locale") | +| json-stringify.jsx:11:16:11:58 | `https: ... ocale}` | +| json-stringify.jsx:11:51:11:56 | locale | +| json-stringify.jsx:19:16:19:63 | `https: ... ocale}` | +| json-stringify.jsx:19:56:19:61 | locale | +| json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | +| json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | +| json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | +| json-stringify.jsx:31:55:31:60 | locale | +| json-stringify.jsx:31:55:31:60 | locale | +| json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | +| json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | | jwt-server.js:7:9:7:35 | taint | | jwt-server.js:7:9:7:35 | taint | | jwt-server.js:7:17:7:35 | req.param("wobble") | @@ -1559,6 +1575,24 @@ 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 | '' + ... '' | +| 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 | +| json-stringify.jsx:5:9:5:36 | locale | json-stringify.jsx:31:55:31:60 | locale | +| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:5:9:5:36 | locale | +| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:5:9:5:36 | locale | +| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:5:9:5:36 | locale | +| json-stringify.jsx:5:18:5:36 | req.param("locale") | json-stringify.jsx:5:9:5:36 | locale | +| json-stringify.jsx:11:16:11:58 | `https: ... ocale}` | json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | +| json-stringify.jsx:11:16:11:58 | `https: ... ocale}` | json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | +| json-stringify.jsx:11:51:11:56 | locale | json-stringify.jsx:11:16:11:58 | `https: ... ocale}` | +| json-stringify.jsx:19:16:19:63 | `https: ... ocale}` | json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | +| json-stringify.jsx:19:16:19:63 | `https: ... ocale}` | json-stringify.jsx:35:40:35:61 | JSON.st ... jsonLD) | +| json-stringify.jsx:19:56:19:61 | locale | json-stringify.jsx:19:16:19:63 | `https: ... ocale}` | +| json-stringify.jsx:31:55:31:60 | locale | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | +| json-stringify.jsx:31:55:31:60 | locale | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | +| json-stringify.jsx:31:55:31:60 | locale | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | +| json-stringify.jsx:31:55:31:60 | locale | json-stringify.jsx:31:40:31:61 | JSON.st ... locale) | | jwt-server.js:7:9:7:35 | taint | jwt-server.js:9:16:9:20 | taint | | jwt-server.js:7:9:7:35 | taint | jwt-server.js:9:16:9:20 | taint | | jwt-server.js:7:17:7:35 | req.param("wobble") | jwt-server.js:7:9:7:35 | taint | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/json-stringify.jsx b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/json-stringify.jsx new file mode 100644 index 00000000000..85ad5cef8d4 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/json-stringify.jsx @@ -0,0 +1,42 @@ +var express = require("express"); +var app = express(); + +app.get("/some/path", function (req, res) { + const locale = req.param("locale"); + const breadcrumbList = [ + { + "@type": "ListItem", + position: 1, + item: { + "@id": `https://example.com/some?locale=${locale}`, + name: "Some", + }, + }, + { + "@type": "ListItem", + position: 2, + item: { + "@id": `https://example.com/some/path?locale=${locale}`, + name: "Path", + }, + }, + ]; + const jsonLD = { + "@context": "https://schema.org", + "@type": "BreadcrumbList", + itemListElement: breadcrumbList, + }; + // OK +}); diff --git a/misc/suite-helpers/CHANGELOG.md b/misc/suite-helpers/CHANGELOG.md index 6bd73620860..c93557f5801 100644 --- a/misc/suite-helpers/CHANGELOG.md +++ b/misc/suite-helpers/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.1 + +No user-facing changes. + ## 0.3.0 No user-facing changes. diff --git a/misc/suite-helpers/change-notes/released/0.3.1.md b/misc/suite-helpers/change-notes/released/0.3.1.md new file mode 100644 index 00000000000..9fd4efd6c80 --- /dev/null +++ b/misc/suite-helpers/change-notes/released/0.3.1.md @@ -0,0 +1,3 @@ +## 0.3.1 + +No user-facing changes. diff --git a/misc/suite-helpers/codeql-pack.release.yml b/misc/suite-helpers/codeql-pack.release.yml index 95f6e3a0ba6..bb106b1cb63 100644 --- a/misc/suite-helpers/codeql-pack.release.yml +++ b/misc/suite-helpers/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.0 +lastReleaseVersion: 0.3.1 diff --git a/misc/suite-helpers/qlpack.yml b/misc/suite-helpers/qlpack.yml index aa0a2693b1d..0c38110c86a 100644 --- a/misc/suite-helpers/qlpack.yml +++ b/misc/suite-helpers/qlpack.yml @@ -1,3 +1,3 @@ name: codeql/suite-helpers -version: 0.3.1-dev +version: 0.3.2-dev groups: shared diff --git a/python/ql/lib/CHANGELOG.md b/python/ql/lib/CHANGELOG.md index 962c7b5d023..10707d9d391 100644 --- a/python/ql/lib/CHANGELOG.md +++ b/python/ql/lib/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.6.1 + +### Minor Analysis Improvements + +* Added the ability to refer to subscript operations in the API graph. It is now possible to write `response().getMember("cookies").getASubscript()` to find code like `resp.cookies["key"]` (assuming `response` returns an API node for reponse objects). +* Added modeling of creating Flask responses with `flask.jsonify`. + ## 0.6.0 ### Deprecated APIs diff --git a/python/ql/lib/change-notes/2022-09-22-flask-jsonify.md b/python/ql/lib/change-notes/2022-09-22-flask-jsonify.md deleted file mode 100644 index cac16e270f4..00000000000 --- a/python/ql/lib/change-notes/2022-09-22-flask-jsonify.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* Added modeling of creating Flask responses with `flask.jsonify`. diff --git a/python/ql/lib/change-notes/2022-09-28-api-subscript.md b/python/ql/lib/change-notes/released/0.6.1.md similarity index 69% rename from python/ql/lib/change-notes/2022-09-28-api-subscript.md rename to python/ql/lib/change-notes/released/0.6.1.md index f14b59d643b..e4ca9748e5f 100644 --- a/python/ql/lib/change-notes/2022-09-28-api-subscript.md +++ b/python/ql/lib/change-notes/released/0.6.1.md @@ -1,4 +1,6 @@ ---- -category: minorAnalysis ---- +## 0.6.1 + +### Minor Analysis Improvements + * Added the ability to refer to subscript operations in the API graph. It is now possible to write `response().getMember("cookies").getASubscript()` to find code like `resp.cookies["key"]` (assuming `response` returns an API node for reponse objects). +* Added modeling of creating Flask responses with `flask.jsonify`. diff --git a/python/ql/lib/codeql-pack.release.yml b/python/ql/lib/codeql-pack.release.yml index a3f820f884d..80fb0899f64 100644 --- a/python/ql/lib/codeql-pack.release.yml +++ b/python/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.6.0 +lastReleaseVersion: 0.6.1 diff --git a/python/ql/lib/qlpack.yml b/python/ql/lib/qlpack.yml index 6121fdace8c..aea8a2fe067 100644 --- a/python/ql/lib/qlpack.yml +++ b/python/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-all -version: 0.6.1-dev +version: 0.6.2-dev groups: python dbscheme: semmlecode.python.dbscheme extractor: python diff --git a/python/ql/lib/semmle/python/Concepts.qll b/python/ql/lib/semmle/python/Concepts.qll index b4f1c73e633..fe091f84e9c 100644 --- a/python/ql/lib/semmle/python/Concepts.qll +++ b/python/ql/lib/semmle/python/Concepts.qll @@ -344,7 +344,7 @@ module SqlConstruction { * A data-flow node that executes SQL statements. * * If the context of interest is such that merely constructing an SQL statement - * would be valuabe to report, then consider using `SqlConstruction`. + * would be valuable to report, then consider using `SqlConstruction`. * * Extend this class to refine existing API models. If you want to model new APIs, * extend `SqlExecution::Range` instead. @@ -360,7 +360,7 @@ module SqlExecution { * A data-flow node that executes SQL statements. * * If the context of interest is such that merely constructing an SQL statement - * would be valuabe to report, then consider using `SqlConstruction`. + * would be valuable to report, then consider using `SqlConstruction`. * * Extend this class to model new APIs. If you want to refine existing API models, * extend `SqlExecution` instead. @@ -465,7 +465,7 @@ module XML { * A data-flow node that executes a xpath expression. * * If the context of interest is such that merely constructing an XPath expression - * would be valuabe to report, then consider using `XPathConstruction`. + * would be valuable to report, then consider using `XPathConstruction`. * * Extend this class to refine existing API models. If you want to model new APIs, * extend `XPathExecution::Range` instead. @@ -487,7 +487,7 @@ module XML { * A data-flow node that executes a XPath expression. * * If the context of interest is such that merely constructing an XPath expression - * would be valuabe to report, then consider using `XPathConstruction`. + * would be valuable to report, then consider using `XPathConstruction`. * * Extend this class to model new APIs. If you want to refine existing API models, * extend `XPathExecution` instead. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. 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 67e93ea7f6f..c8d9d66e1b9 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/python/ql/lib/semmle/python/frameworks/Flask.qll b/python/ql/lib/semmle/python/frameworks/Flask.qll index 45e43944ac5..d264b085fc4 100644 --- a/python/ql/lib/semmle/python/frameworks/Flask.qll +++ b/python/ql/lib/semmle/python/frameworks/Flask.qll @@ -354,13 +354,7 @@ module Flask { * See https://flask.palletsprojects.com/en/1.1.x/api/#flask.Request */ private class FlaskRequestSource extends RemoteFlowSource::Range { - FlaskRequestSource() { - this = request().getAValueReachableFromSource() and - not any(Import imp).contains(this.asExpr()) and - not exists(ControlFlowNode def | this.asVar().getSourceVariable().hasDefiningNode(def) | - any(Import imp).contains(def.getNode()) - ) - } + FlaskRequestSource() { this = request().asSource() } override string getSourceType() { result = "flask.request" } } diff --git a/python/ql/lib/semmle/python/frameworks/Tornado.qll b/python/ql/lib/semmle/python/frameworks/Tornado.qll index 77c60097cb5..9cf258babe9 100644 --- a/python/ql/lib/semmle/python/frameworks/Tornado.qll +++ b/python/ql/lib/semmle/python/frameworks/Tornado.qll @@ -14,10 +14,12 @@ private import semmle.python.frameworks.Stdlib private import semmle.python.frameworks.internal.InstanceTaintStepsHelper /** + * INTERNAL: Do not use. + * * Provides models for the `tornado` PyPI package. * See https://www.tornadoweb.org/en/stable/. */ -private module Tornado { +module Tornado { /** * Provides models for the `tornado.httputil.HTTPHeaders` class * @@ -126,8 +128,7 @@ private module Tornado { abstract class InstanceSource extends DataFlow::LocalSourceNode { } /** The `self` parameter in a method on the `tornado.web.RequestHandler` class or any subclass. */ - private class SelfParam extends InstanceSource, RemoteFlowSource::Range, - DataFlow::ParameterNode { + class SelfParam extends InstanceSource, RemoteFlowSource::Range, DataFlow::ParameterNode { SelfParam() { exists(RequestHandlerClass cls | cls.getAMethod().getArg(0) = this.getParameter()) } diff --git a/python/ql/src/CHANGELOG.md b/python/ql/src/CHANGELOG.md index b26aede7b0b..aaf184f4e7c 100644 --- a/python/ql/src/CHANGELOG.md +++ b/python/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.1 + +No user-facing changes. + ## 0.5.0 ### Query Metadata Changes diff --git a/python/ql/src/change-notes/2022-09-29-flask-source-modeling.md b/python/ql/src/change-notes/2022-09-29-flask-source-modeling.md new file mode 100644 index 00000000000..59774242825 --- /dev/null +++ b/python/ql/src/change-notes/2022-09-29-flask-source-modeling.md @@ -0,0 +1,4 @@ +--- +category: fix +--- +* Fixed how `flask.request` is modeled as a RemoteFlowSource, such that we show fewer duplicated alert messages for Code Scanning alerts. The import, such as `from flask import request`, will now be shown as the first step in a path explanation. diff --git a/python/ql/src/change-notes/released/0.5.1.md b/python/ql/src/change-notes/released/0.5.1.md new file mode 100644 index 00000000000..0275d38f63c --- /dev/null +++ b/python/ql/src/change-notes/released/0.5.1.md @@ -0,0 +1,3 @@ +## 0.5.1 + +No user-facing changes. diff --git a/python/ql/src/codeql-pack.release.yml b/python/ql/src/codeql-pack.release.yml index 30e271c5361..0bf7024c337 100644 --- a/python/ql/src/codeql-pack.release.yml +++ b/python/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.0 +lastReleaseVersion: 0.5.1 diff --git a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll index 21e602e5d34..39b69b10004 100644 --- a/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll +++ b/python/ql/src/experimental/Security/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll @@ -1,73 +1,57 @@ private import python private import semmle.python.Concepts private import semmle.python.ApiGraphs -private import semmle.python.dataflow.new.RemoteFlowSources +private import semmle.python.frameworks.Flask +private import semmle.python.frameworks.Django +private import semmle.python.frameworks.Tornado /** * A data flow source of the client ip obtained according to the remote endpoint identifier specified * (`X-Forwarded-For`, `X-Real-IP`, `Proxy-Client-IP`, etc.) in the header. * * For example: `request.headers.get("X-Forwarded-For")`. + * + * A call to `request.headers.get` or `request.headers.get_all` or `request.headers.getlist`. */ -abstract class ClientSuppliedIpUsedInSecurityCheck extends DataFlow::CallCfgNode { } +abstract class ClientSuppliedIpUsedInSecurityCheck extends DataFlow::Node { } -private class FlaskClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck { +private class FlaskClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck, + DataFlow::MethodCallNode { FlaskClientSuppliedIpUsedInSecurityCheck() { - exists(RemoteFlowSource rfs, DataFlow::AttrRead get | - rfs.getSourceType() = "flask.request" and this.getFunction() = get - | - // `get` is a call to request.headers.get or request.headers.get_all or request.headers.getlist - // request.headers - get.getObject() - .(DataFlow::AttrRead) - // request - .getObject() - .getALocalSource() = rfs and - get.getAttributeName() in ["get", "get_all", "getlist"] and - get.getObject().(DataFlow::AttrRead).getAttributeName() = "headers" and - this.getArg(0).asExpr().(StrConst).getText().toLowerCase() = clientIpParameterName() - ) + this = Flask::request().getMember("headers").getMember(["get", "get_all", "getlist"]).getACall() and + this.getArg(0).asExpr().(StrConst).getText().toLowerCase() = clientIpParameterName() } } -private class DjangoClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck { +private class DjangoClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck, + DataFlow::MethodCallNode { DjangoClientSuppliedIpUsedInSecurityCheck() { - exists(RemoteFlowSource rfs, DataFlow::AttrRead get | - rfs.getSourceType() = "django.http.request.HttpRequest" and this.getFunction() = get - | - // `get` is a call to request.headers.get or request.META.get - // request.headers - get.getObject() - .(DataFlow::AttrRead) - // request - .getObject() - .getALocalSource() = rfs and - get.getAttributeName() = "get" and - get.getObject().(DataFlow::AttrRead).getAttributeName() in ["headers", "META"] and - this.getArg(0).asExpr().(StrConst).getText().toLowerCase() = clientIpParameterName() - ) + exists(DataFlow::Node req, DataFlow::AttrRead headers | + // a call to request.headers.get or request.META.get + req = PrivateDjango::DjangoImpl::DjangoHttp::Request::HttpRequest::instance() and + headers.getObject().getALocalSource() = req and + headers.getAttributeName() in ["headers", "META"] and + this.calls(headers, "get") + ) and + this.getArg(0).asExpr().(StrConst).getText().toLowerCase() = clientIpParameterName() } } -private class TornadoClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck { +private class TornadoClientSuppliedIpUsedInSecurityCheck extends ClientSuppliedIpUsedInSecurityCheck, + DataFlow::MethodCallNode { TornadoClientSuppliedIpUsedInSecurityCheck() { - exists(RemoteFlowSource rfs, DataFlow::AttrRead get | - rfs.getSourceType() = "tornado.web.RequestHandler" and this.getFunction() = get + // a call to self.request.headers.get or self.request.headers.get_list inside a tornado requesthandler + exists( + Tornado::TornadoModule::Web::RequestHandler::SelfParam selfParam, DataFlow::AttrRead headers, + DataFlow::AttrRead req | - // `get` is a call to `rfs`.request.headers.get - // `rfs`.request.headers - get.getObject() - .(DataFlow::AttrRead) - // `rfs`.request - .getObject() - .(DataFlow::AttrRead) - // `rfs` - .getObject() - .getALocalSource() = rfs and - get.getAttributeName() in ["get", "get_list"] and - get.getObject().(DataFlow::AttrRead).getAttributeName() = "headers" and - this.getArg(0).asExpr().(StrConst).getText().toLowerCase() = clientIpParameterName() - ) + req.getObject().getALocalSource() = selfParam and + req.getAttributeName() = "request" and + headers.getObject().getALocalSource() = req and + headers.getAttributeName() = "headers" and + this.calls(headers, ["get", "get_list"]) + ) and + this.getArg(0).asExpr().(StrConst).getText().toLowerCase() = clientIpParameterName() } } diff --git a/python/ql/src/meta/alerts/RemoteFlowSourcesReach.ql b/python/ql/src/meta/alerts/RemoteFlowSourcesReach.ql index b629d1b2955..02e063fd15e 100644 --- a/python/ql/src/meta/alerts/RemoteFlowSourcesReach.ql +++ b/python/ql/src/meta/alerts/RemoteFlowSourcesReach.ql @@ -25,28 +25,15 @@ class RemoteFlowSourceReach extends TaintTracking::Configuration { } override predicate isSink(DataFlow::Node node) { - not node.getLocation().getFile() instanceof IgnoredFile and - ( - node instanceof RemoteFlowSource - or - this.isAdditionalFlowStep(_, node) - ) and - // In september 2021 we changed how we do taint-propagation for method calls (mostly - // relating to modeled frameworks/libraries). We used to do `obj -> obj.meth` and - // `obj.meth -> obj.meth()` in two separate steps, and now do them in one - // `obj -> obj.meth()`. To be able to compare the overall reach between these two - // version, we don't want this query to alert us to the fact that we no longer taint - // the node in the middle (since that is just noise). - // see https://github.com/github/codeql/pull/6349 + not node.getLocation().getFile() instanceof IgnoredFile + // We could try to reduce the number of sinks in this configuration, by only + // allowing something that is on one end of a localFlowStep, readStep or storeStep, + // however, it's a brittle solution that requires us to remember to update this file + // if/when adding something new to the data-flow library. // - // We should be able to remove the following few lines of code once we don't care to - // compare with the old (before September 2021) way of doing taint-propagation for - // method calls. - not exists(DataFlow::MethodCallNode c | - node = c.getFunction() and - this.isAdditionalFlowStep(c.getObject(), node) and - this.isAdditionalFlowStep(node, c) - ) + // From testing on a few projects, trying to reduce the number of nodes, we only + // gain a reduction in the range of 40%, and while that's nice, it doesn't seem + // worth it to me for a meta query. } } diff --git a/python/ql/src/qlpack.yml b/python/ql/src/qlpack.yml index 6e3e2010677..31b6ab69f2e 100644 --- a/python/ql/src/qlpack.yml +++ b/python/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-queries -version: 0.5.1-dev +version: 0.5.2-dev groups: - python - queries diff --git a/python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.expected b/python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.expected index f787dfa43fc..77dafce4a10 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-079/ReflectedXSS.expected @@ -1,4 +1,9 @@ edges +| flask_mail.py:0:0:0:0 | ModuleVariableNode for flask_mail.request | flask_mail.py:13:22:13:28 | ControlFlowNode for request | +| flask_mail.py:0:0:0:0 | ModuleVariableNode for flask_mail.request | flask_mail.py:18:14:18:20 | ControlFlowNode for request | +| flask_mail.py:0:0:0:0 | ModuleVariableNode for flask_mail.request | flask_mail.py:31:24:31:30 | ControlFlowNode for request | +| flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | flask_mail.py:1:19:1:25 | GSSA Variable request | +| flask_mail.py:1:19:1:25 | GSSA Variable request | flask_mail.py:0:0:0:0 | ModuleVariableNode for flask_mail.request | | flask_mail.py:13:22:13:28 | ControlFlowNode for request | flask_mail.py:13:22:13:33 | ControlFlowNode for Attribute | | flask_mail.py:13:22:13:28 | ControlFlowNode for request | flask_mail.py:18:14:18:25 | ControlFlowNode for Attribute | | flask_mail.py:13:22:13:33 | ControlFlowNode for Attribute | flask_mail.py:13:22:13:41 | ControlFlowNode for Subscript | @@ -6,6 +11,11 @@ edges | flask_mail.py:18:14:18:25 | ControlFlowNode for Attribute | flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | | flask_mail.py:31:24:31:30 | ControlFlowNode for request | flask_mail.py:31:24:31:35 | ControlFlowNode for Attribute | | flask_mail.py:31:24:31:35 | ControlFlowNode for Attribute | flask_mail.py:31:24:31:43 | ControlFlowNode for Subscript | +| sendgrid_mail.py:0:0:0:0 | ModuleVariableNode for sendgrid_mail.request | sendgrid_mail.py:14:22:14:28 | ControlFlowNode for request | +| sendgrid_mail.py:0:0:0:0 | ModuleVariableNode for sendgrid_mail.request | sendgrid_mail.py:26:34:26:40 | ControlFlowNode for request | +| sendgrid_mail.py:0:0:0:0 | ModuleVariableNode for sendgrid_mail.request | sendgrid_mail.py:37:41:37:47 | ControlFlowNode for request | +| sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | sendgrid_mail.py:1:19:1:25 | GSSA Variable request | +| sendgrid_mail.py:1:19:1:25 | GSSA Variable request | sendgrid_mail.py:0:0:0:0 | ModuleVariableNode for sendgrid_mail.request | | sendgrid_mail.py:14:22:14:28 | ControlFlowNode for request | sendgrid_mail.py:14:22:14:33 | ControlFlowNode for Attribute | | sendgrid_mail.py:14:22:14:33 | ControlFlowNode for Attribute | sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | | sendgrid_mail.py:26:34:26:40 | ControlFlowNode for request | sendgrid_mail.py:26:34:26:45 | ControlFlowNode for Attribute | @@ -13,6 +23,11 @@ edges | sendgrid_mail.py:26:34:26:61 | ControlFlowNode for Subscript | sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() | | sendgrid_mail.py:37:41:37:47 | ControlFlowNode for request | sendgrid_mail.py:37:41:37:52 | ControlFlowNode for Attribute | | sendgrid_mail.py:37:41:37:52 | ControlFlowNode for Attribute | sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | +| sendgrid_via_mail_send_post_request_body_bad.py:0:0:0:0 | ModuleVariableNode for sendgrid_via_mail_send_post_request_body_bad.request | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | +| sendgrid_via_mail_send_post_request_body_bad.py:0:0:0:0 | ModuleVariableNode for sendgrid_via_mail_send_post_request_body_bad.request | sendgrid_via_mail_send_post_request_body_bad.py:27:50:27:56 | ControlFlowNode for request | +| sendgrid_via_mail_send_post_request_body_bad.py:0:0:0:0 | ModuleVariableNode for sendgrid_via_mail_send_post_request_body_bad.request | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:56 | ControlFlowNode for request | +| sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | GSSA Variable request | +| sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | GSSA Variable request | sendgrid_via_mail_send_post_request_body_bad.py:0:0:0:0 | ModuleVariableNode for sendgrid_via_mail_send_post_request_body_bad.request | | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:62 | ControlFlowNode for Attribute | | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:27:50:27:61 | ControlFlowNode for Attribute | | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:61 | ControlFlowNode for Attribute | @@ -25,9 +40,15 @@ edges | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:56 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:61 | ControlFlowNode for Attribute | | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:61 | ControlFlowNode for Attribute | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:78 | ControlFlowNode for Subscript | | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:78 | ControlFlowNode for Subscript | sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | +| smtplib_bad_subparts.py:0:0:0:0 | ModuleVariableNode for smtplib_bad_subparts.request | smtplib_bad_subparts.py:17:12:17:18 | ControlFlowNode for request | +| smtplib_bad_subparts.py:2:26:2:32 | ControlFlowNode for ImportMember | smtplib_bad_subparts.py:2:26:2:32 | GSSA Variable request | +| smtplib_bad_subparts.py:2:26:2:32 | GSSA Variable request | smtplib_bad_subparts.py:0:0:0:0 | ModuleVariableNode for smtplib_bad_subparts.request | | smtplib_bad_subparts.py:17:12:17:18 | ControlFlowNode for request | smtplib_bad_subparts.py:17:12:17:23 | ControlFlowNode for Attribute | | smtplib_bad_subparts.py:17:12:17:23 | ControlFlowNode for Attribute | smtplib_bad_subparts.py:17:12:17:33 | ControlFlowNode for Subscript | | smtplib_bad_subparts.py:17:12:17:33 | ControlFlowNode for Subscript | smtplib_bad_subparts.py:24:22:24:25 | ControlFlowNode for html | +| smtplib_bad_via_attach.py:0:0:0:0 | ModuleVariableNode for smtplib_bad_via_attach.request | smtplib_bad_via_attach.py:20:12:20:18 | ControlFlowNode for request | +| smtplib_bad_via_attach.py:2:26:2:32 | ControlFlowNode for ImportMember | smtplib_bad_via_attach.py:2:26:2:32 | GSSA Variable request | +| smtplib_bad_via_attach.py:2:26:2:32 | GSSA Variable request | smtplib_bad_via_attach.py:0:0:0:0 | ModuleVariableNode for smtplib_bad_via_attach.request | | smtplib_bad_via_attach.py:20:12:20:18 | ControlFlowNode for request | smtplib_bad_via_attach.py:20:12:20:23 | ControlFlowNode for Attribute | | smtplib_bad_via_attach.py:20:12:20:23 | ControlFlowNode for Attribute | smtplib_bad_via_attach.py:20:12:20:31 | ControlFlowNode for Subscript | | smtplib_bad_via_attach.py:20:12:20:31 | ControlFlowNode for Subscript | smtplib_bad_via_attach.py:27:22:27:25 | ControlFlowNode for html | @@ -35,6 +56,9 @@ nodes | django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| flask_mail.py:0:0:0:0 | ModuleVariableNode for flask_mail.request | semmle.label | ModuleVariableNode for flask_mail.request | +| flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| flask_mail.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | flask_mail.py:13:22:13:28 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_mail.py:13:22:13:33 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_mail.py:13:22:13:41 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -44,6 +68,9 @@ nodes | flask_mail.py:31:24:31:30 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_mail.py:31:24:31:35 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_mail.py:31:24:31:43 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| sendgrid_mail.py:0:0:0:0 | ModuleVariableNode for sendgrid_mail.request | semmle.label | ModuleVariableNode for sendgrid_mail.request | +| sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| sendgrid_mail.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | sendgrid_mail.py:14:22:14:28 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | sendgrid_mail.py:14:22:14:33 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -54,6 +81,9 @@ nodes | sendgrid_mail.py:37:41:37:47 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | sendgrid_mail.py:37:41:37:52 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| sendgrid_via_mail_send_post_request_body_bad.py:0:0:0:0 | ModuleVariableNode for sendgrid_via_mail_send_post_request_body_bad.request | semmle.label | ModuleVariableNode for sendgrid_via_mail_send_post_request_body_bad.request | +| sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | GSSA Variable request | semmle.label | GSSA Variable request | | sendgrid_via_mail_send_post_request_body_bad.py:16:26:16:79 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:62 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -66,10 +96,16 @@ nodes | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:56 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:61 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:78 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | +| smtplib_bad_subparts.py:0:0:0:0 | ModuleVariableNode for smtplib_bad_subparts.request | semmle.label | ModuleVariableNode for smtplib_bad_subparts.request | +| smtplib_bad_subparts.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| smtplib_bad_subparts.py:2:26:2:32 | GSSA Variable request | semmle.label | GSSA Variable request | | smtplib_bad_subparts.py:17:12:17:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | smtplib_bad_subparts.py:17:12:17:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | smtplib_bad_subparts.py:17:12:17:33 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | smtplib_bad_subparts.py:24:22:24:25 | ControlFlowNode for html | semmle.label | ControlFlowNode for html | +| smtplib_bad_via_attach.py:0:0:0:0 | ModuleVariableNode for smtplib_bad_via_attach.request | semmle.label | ModuleVariableNode for smtplib_bad_via_attach.request | +| smtplib_bad_via_attach.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| smtplib_bad_via_attach.py:2:26:2:32 | GSSA Variable request | semmle.label | GSSA Variable request | | smtplib_bad_via_attach.py:20:12:20:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | smtplib_bad_via_attach.py:20:12:20:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | smtplib_bad_via_attach.py:20:12:20:31 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -79,18 +115,14 @@ subpaths | django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | django_mail.py:14:48:14:82 | ControlFlowNode for Attribute() | a user-provided value | | django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | django_mail.py:23:30:23:64 | ControlFlowNode for Attribute() | a user-provided value | | django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | django_mail.py:25:32:25:66 | ControlFlowNode for Attribute() | a user-provided value | -| flask_mail.py:13:22:13:41 | ControlFlowNode for Subscript | flask_mail.py:13:22:13:28 | ControlFlowNode for request | flask_mail.py:13:22:13:41 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:13:22:13:28 | ControlFlowNode for request | a user-provided value | -| flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | flask_mail.py:13:22:13:28 | ControlFlowNode for request | flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:13:22:13:28 | ControlFlowNode for request | a user-provided value | -| flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | flask_mail.py:18:14:18:20 | ControlFlowNode for request | flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:18:14:18:20 | ControlFlowNode for request | a user-provided value | -| flask_mail.py:31:24:31:43 | ControlFlowNode for Subscript | flask_mail.py:31:24:31:30 | ControlFlowNode for request | flask_mail.py:31:24:31:43 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:31:24:31:30 | ControlFlowNode for request | a user-provided value | -| sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | sendgrid_mail.py:14:22:14:28 | ControlFlowNode for request | sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:14:22:14:28 | ControlFlowNode for request | a user-provided value | -| sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() | sendgrid_mail.py:26:34:26:40 | ControlFlowNode for request | sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:26:34:26:40 | ControlFlowNode for request | a user-provided value | -| sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | sendgrid_mail.py:37:41:37:47 | ControlFlowNode for request | sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:37:41:37:47 | ControlFlowNode for request | a user-provided value | -| sendgrid_via_mail_send_post_request_body_bad.py:16:26:16:79 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:16:26:16:79 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | a user-provided value | -| sendgrid_via_mail_send_post_request_body_bad.py:27:25:27:77 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:27:25:27:77 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | a user-provided value | -| sendgrid_via_mail_send_post_request_body_bad.py:27:25:27:77 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:27:50:27:56 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:27:25:27:77 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:27:50:27:56 | ControlFlowNode for request | a user-provided value | -| sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:16:51:16:57 | ControlFlowNode for request | a user-provided value | -| sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:27:50:27:56 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:27:50:27:56 | ControlFlowNode for request | a user-provided value | -| sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:56 | ControlFlowNode for request | sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:41:50:41:56 | ControlFlowNode for request | a user-provided value | -| smtplib_bad_subparts.py:24:22:24:25 | ControlFlowNode for html | smtplib_bad_subparts.py:17:12:17:18 | ControlFlowNode for request | smtplib_bad_subparts.py:24:22:24:25 | ControlFlowNode for html | Cross-site scripting vulnerability due to $@. | smtplib_bad_subparts.py:17:12:17:18 | ControlFlowNode for request | a user-provided value | -| smtplib_bad_via_attach.py:27:22:27:25 | ControlFlowNode for html | smtplib_bad_via_attach.py:20:12:20:18 | ControlFlowNode for request | smtplib_bad_via_attach.py:27:22:27:25 | ControlFlowNode for html | Cross-site scripting vulnerability due to $@. | smtplib_bad_via_attach.py:20:12:20:18 | ControlFlowNode for request | a user-provided value | +| flask_mail.py:13:22:13:41 | ControlFlowNode for Subscript | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | flask_mail.py:13:22:13:41 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | flask_mail.py:18:14:18:33 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| flask_mail.py:31:24:31:43 | ControlFlowNode for Subscript | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | flask_mail.py:31:24:31:43 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | flask_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | sendgrid_mail.py:14:22:14:49 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | sendgrid_mail.py:26:22:26:62 | ControlFlowNode for HtmlContent() | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | sendgrid_mail.py:37:41:37:68 | ControlFlowNode for Subscript | Cross-site scripting vulnerability due to $@. | sendgrid_mail.py:1:19:1:25 | ControlFlowNode for ImportMember | a user-provided value | +| sendgrid_via_mail_send_post_request_body_bad.py:16:26:16:79 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | sendgrid_via_mail_send_post_request_body_bad.py:16:26:16:79 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | a user-provided value | +| sendgrid_via_mail_send_post_request_body_bad.py:27:25:27:77 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | sendgrid_via_mail_send_post_request_body_bad.py:27:25:27:77 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | a user-provided value | +| sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | sendgrid_via_mail_send_post_request_body_bad.py:41:25:41:79 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | sendgrid_via_mail_send_post_request_body_bad.py:3:19:3:25 | ControlFlowNode for ImportMember | a user-provided value | +| smtplib_bad_subparts.py:24:22:24:25 | ControlFlowNode for html | smtplib_bad_subparts.py:2:26:2:32 | ControlFlowNode for ImportMember | smtplib_bad_subparts.py:24:22:24:25 | ControlFlowNode for html | Cross-site scripting vulnerability due to $@. | smtplib_bad_subparts.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value | +| smtplib_bad_via_attach.py:27:22:27:25 | ControlFlowNode for html | smtplib_bad_via_attach.py:2:26:2:32 | ControlFlowNode for ImportMember | smtplib_bad_via_attach.py:27:22:27:25 | ControlFlowNode for html | Cross-site scripting vulnerability due to $@. | smtplib_bad_via_attach.py:2:26:2:32 | ControlFlowNode for ImportMember | a user-provided value | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected index f2838178c0d..af98a815fe8 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected @@ -1,6 +1,12 @@ edges | django_bad.py:5:18:5:58 | ControlFlowNode for Attribute() | django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | | django_bad.py:12:18:12:58 | ControlFlowNode for Attribute() | django_bad.py:14:30:14:39 | ControlFlowNode for rfs_header | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | flask_bad.py:9:18:9:24 | ControlFlowNode for request | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | flask_bad.py:19:18:19:24 | ControlFlowNode for request | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | flask_bad.py:27:18:27:24 | ControlFlowNode for request | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | flask_bad.py:35:18:35:24 | ControlFlowNode for request | +| flask_bad.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_bad.py:1:29:1:35 | GSSA Variable request | +| flask_bad.py:1:29:1:35 | GSSA Variable request | flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | | flask_bad.py:9:18:9:24 | ControlFlowNode for request | flask_bad.py:9:18:9:29 | ControlFlowNode for Attribute | | flask_bad.py:9:18:9:29 | ControlFlowNode for Attribute | flask_bad.py:9:18:9:43 | ControlFlowNode for Subscript | | flask_bad.py:9:18:9:43 | ControlFlowNode for Subscript | flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | @@ -18,6 +24,9 @@ nodes | django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header | | django_bad.py:12:18:12:58 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | django_bad.py:14:30:14:39 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | semmle.label | ModuleVariableNode for flask_bad.request | +| flask_bad.py:1:29:1:35 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| flask_bad.py:1:29:1:35 | GSSA Variable request | semmle.label | GSSA Variable request | | flask_bad.py:9:18:9:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_bad.py:9:18:9:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_bad.py:9:18:9:43 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -38,7 +47,7 @@ subpaths #select | django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | django_bad.py:5:18:5:58 | ControlFlowNode for Attribute() | django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | django_bad.py:5:18:5:58 | ControlFlowNode for Attribute() | user-provided value | | django_bad.py:14:30:14:39 | ControlFlowNode for rfs_header | django_bad.py:12:18:12:58 | ControlFlowNode for Attribute() | django_bad.py:14:30:14:39 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | django_bad.py:12:18:12:58 | ControlFlowNode for Attribute() | user-provided value | -| flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | flask_bad.py:9:18:9:24 | ControlFlowNode for request | flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_bad.py:9:18:9:24 | ControlFlowNode for request | user-provided value | -| flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | flask_bad.py:19:18:19:24 | ControlFlowNode for request | flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_bad.py:19:18:19:24 | ControlFlowNode for request | user-provided value | -| flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | flask_bad.py:27:18:27:24 | ControlFlowNode for request | flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_bad.py:27:18:27:24 | ControlFlowNode for request | user-provided value | -| flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | flask_bad.py:35:18:35:24 | ControlFlowNode for request | flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_bad.py:35:18:35:24 | ControlFlowNode for request | user-provided value | +| flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | flask_bad.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_bad.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value | +| flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | flask_bad.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_bad.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value | +| flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | flask_bad.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_bad.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value | +| flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | flask_bad.py:1:29:1:35 | ControlFlowNode for ImportMember | flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_bad.py:1:29:1:35 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-1236/CsvInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-1236/CsvInjection.expected index 2b6fb18f47b..5b6b8a4bc24 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-1236/CsvInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-1236/CsvInjection.expected @@ -1,10 +1,17 @@ edges +| csv_bad.py:0:0:0:0 | ModuleVariableNode for csv_bad.request | csv_bad.py:16:16:16:22 | ControlFlowNode for request | +| csv_bad.py:0:0:0:0 | ModuleVariableNode for csv_bad.request | csv_bad.py:24:16:24:22 | ControlFlowNode for request | +| csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:9:19:9:25 | GSSA Variable request | +| csv_bad.py:9:19:9:25 | GSSA Variable request | csv_bad.py:0:0:0:0 | ModuleVariableNode for csv_bad.request | | csv_bad.py:16:16:16:22 | ControlFlowNode for request | csv_bad.py:16:16:16:27 | ControlFlowNode for Attribute | | csv_bad.py:16:16:16:27 | ControlFlowNode for Attribute | csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | | csv_bad.py:16:16:16:27 | ControlFlowNode for Attribute | csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | | csv_bad.py:24:16:24:22 | ControlFlowNode for request | csv_bad.py:24:16:24:27 | ControlFlowNode for Attribute | | csv_bad.py:24:16:24:27 | ControlFlowNode for Attribute | csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | nodes +| csv_bad.py:0:0:0:0 | ModuleVariableNode for csv_bad.request | semmle.label | ModuleVariableNode for csv_bad.request | +| csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| csv_bad.py:9:19:9:25 | GSSA Variable request | semmle.label | GSSA Variable request | | csv_bad.py:16:16:16:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | csv_bad.py:16:16:16:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | semmle.label | ControlFlowNode for csv_data | @@ -14,6 +21,6 @@ nodes | csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | semmle.label | ControlFlowNode for csv_data | subpaths #select -| csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | csv_bad.py:16:16:16:22 | ControlFlowNode for request | csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:16:16:16:22 | ControlFlowNode for request | this user input | -| csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | csv_bad.py:16:16:16:22 | ControlFlowNode for request | csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:16:16:16:22 | ControlFlowNode for request | this user input | -| csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | csv_bad.py:24:16:24:22 | ControlFlowNode for request | csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:24:16:24:22 | ControlFlowNode for request | this user input | +| csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:18:24:18:31 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input | +| csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:19:25:19:32 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input | +| csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | csv_bad.py:25:46:25:53 | ControlFlowNode for csv_data | Csv injection might include code from $@. | csv_bad.py:9:19:9:25 | ControlFlowNode for ImportMember | this user input | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.expected b/python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.expected index a2d5f215057..ec408995b0f 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.expected @@ -1,4 +1,7 @@ edges +| ldap3_remote.py:0:0:0:0 | ModuleVariableNode for ldap3_remote.request | ldap3_remote.py:138:21:138:27 | ControlFlowNode for request | +| ldap3_remote.py:2:19:2:25 | ControlFlowNode for ImportMember | ldap3_remote.py:2:19:2:25 | GSSA Variable request | +| ldap3_remote.py:2:19:2:25 | GSSA Variable request | ldap3_remote.py:0:0:0:0 | ModuleVariableNode for ldap3_remote.request | | ldap3_remote.py:101:12:101:49 | ControlFlowNode for BinaryExpr | ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | | ldap3_remote.py:114:12:114:49 | ControlFlowNode for BinaryExpr | ldap3_remote.py:115:18:115:21 | ControlFlowNode for host | | ldap3_remote.py:126:12:126:31 | ControlFlowNode for BinaryExpr | ldap3_remote.py:127:18:127:21 | ControlFlowNode for host | @@ -8,6 +11,9 @@ edges nodes | ldap2_remote.py:45:41:45:60 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | ldap2_remote.py:56:41:56:60 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| ldap3_remote.py:0:0:0:0 | ModuleVariableNode for ldap3_remote.request | semmle.label | ModuleVariableNode for ldap3_remote.request | +| ldap3_remote.py:2:19:2:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| ldap3_remote.py:2:19:2:25 | GSSA Variable request | semmle.label | GSSA Variable request | | ldap3_remote.py:101:12:101:49 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | | ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | semmle.label | ControlFlowNode for host | | ldap3_remote.py:114:12:114:49 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | @@ -25,4 +31,4 @@ subpaths | ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | ldap3_remote.py:101:12:101:49 | ControlFlowNode for BinaryExpr | ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. | | ldap3_remote.py:115:18:115:21 | ControlFlowNode for host | ldap3_remote.py:114:12:114:49 | ControlFlowNode for BinaryExpr | ldap3_remote.py:115:18:115:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. | | ldap3_remote.py:127:18:127:21 | ControlFlowNode for host | ldap3_remote.py:126:12:126:31 | ControlFlowNode for BinaryExpr | ldap3_remote.py:127:18:127:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. | -| ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | ldap3_remote.py:138:21:138:27 | ControlFlowNode for request | ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. | +| ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | ldap3_remote.py:2:19:2:25 | ControlFlowNode for ImportMember | ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.expected index d246f8b14d6..5cc54fbdad2 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-614/CookieInjection.expected @@ -1,6 +1,12 @@ edges | django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | flask_bad.py:24:21:24:27 | ControlFlowNode for request | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | flask_bad.py:24:49:24:55 | ControlFlowNode for request | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | flask_bad.py:32:37:32:43 | ControlFlowNode for request | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | flask_bad.py:32:60:32:66 | ControlFlowNode for request | +| flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:1:26:1:32 | GSSA Variable request | +| flask_bad.py:1:26:1:32 | GSSA Variable request | flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | | flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:21:24:32 | ControlFlowNode for Attribute | | flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:49:24:60 | ControlFlowNode for Attribute | | flask_bad.py:24:21:24:32 | ControlFlowNode for Attribute | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | @@ -19,6 +25,9 @@ nodes | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | semmle.label | ControlFlowNode for Fstring | | django_bad.py:27:33:27:67 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| flask_bad.py:0:0:0:0 | ModuleVariableNode for flask_bad.request | semmle.label | ModuleVariableNode for flask_bad.request | +| flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| flask_bad.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | flask_bad.py:24:21:24:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_bad.py:24:21:24:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -46,18 +55,12 @@ subpaths | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its httponly flag is not properly set. | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | user-supplied input | | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its samesite flag is not properly set. | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | user-supplied input | | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | django_bad.py:27:30:27:124 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its secure flag is not properly set. | django_bad.py:27:71:27:106 | ControlFlowNode for Attribute() | user-supplied input | -| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:24:21:24:27 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:24:21:24:27 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:24:21:24:27 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:24:21:24:27 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:24:21:24:27 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:24:21:24:27 | ControlFlowNode for request | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:24:21:24:27 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:24:49:24:55 | ControlFlowNode for request | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:24:49:24:55 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:24:49:24:55 | ControlFlowNode for request | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:24:49:24:55 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:24:49:24:55 | ControlFlowNode for request | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:24:49:24:55 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:32:37:32:43 | ControlFlowNode for request | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:32:37:32:43 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:32:37:32:43 | ControlFlowNode for request | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:32:37:32:43 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:32:37:32:43 | ControlFlowNode for request | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:32:37:32:43 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:32:60:32:66 | ControlFlowNode for request | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:32:60:32:66 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:32:60:32:66 | ControlFlowNode for request | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:32:60:32:66 | ControlFlowNode for request | user-supplied input | -| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:32:60:32:66 | ControlFlowNode for request | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:32:60:32:66 | ControlFlowNode for request | user-supplied input | +| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | +| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | +| flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:21:24:40 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | +| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | +| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | +| flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:24:49:24:69 | ControlFlowNode for Subscript | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | +| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its httponly flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | +| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its samesite flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | +| flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_bad.py:32:34:32:98 | ControlFlowNode for Fstring | Cookie is constructed from a $@,and its secure flag is not properly set. | flask_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-supplied input | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected index 7a4c8aa5967..400288d7ea2 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected @@ -1,4 +1,8 @@ edges +| flask_mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for flask_mongoengine_bad.request | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | +| flask_mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for flask_mongoengine_bad.request | flask_mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | +| flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_mongoengine_bad.py:1:26:1:32 | GSSA Variable request | +| flask_mongoengine_bad.py:1:26:1:32 | GSSA Variable request | flask_mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for flask_mongoengine_bad.request | | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_bad.py:19:21:19:32 | ControlFlowNode for Attribute | | flask_mongoengine_bad.py:19:21:19:32 | ControlFlowNode for Attribute | flask_mongoengine_bad.py:19:21:19:42 | ControlFlowNode for Subscript | | flask_mongoengine_bad.py:19:21:19:42 | ControlFlowNode for Subscript | flask_mongoengine_bad.py:20:30:20:42 | ControlFlowNode for unsafe_search | @@ -9,11 +13,22 @@ edges | flask_mongoengine_bad.py:26:21:26:42 | ControlFlowNode for Subscript | flask_mongoengine_bad.py:27:30:27:42 | ControlFlowNode for unsafe_search | | flask_mongoengine_bad.py:27:19:27:43 | ControlFlowNode for Attribute() | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | | flask_mongoengine_bad.py:27:30:27:42 | ControlFlowNode for unsafe_search | flask_mongoengine_bad.py:27:19:27:43 | ControlFlowNode for Attribute() | +| flask_pymongo_bad.py:0:0:0:0 | ModuleVariableNode for flask_pymongo_bad.request | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | +| flask_pymongo_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_pymongo_bad.py:1:26:1:32 | GSSA Variable request | +| flask_pymongo_bad.py:1:26:1:32 | GSSA Variable request | flask_pymongo_bad.py:0:0:0:0 | ModuleVariableNode for flask_pymongo_bad.request | | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | | flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | | flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | flask_pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | | flask_pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | | flask_pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | flask_pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | +| mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for mongoengine_bad.request | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | +| mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for mongoengine_bad.request | mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | +| mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for mongoengine_bad.request | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | +| mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for mongoengine_bad.request | mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | +| mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for mongoengine_bad.request | mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | +| mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for mongoengine_bad.request | mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | +| mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | mongoengine_bad.py:1:26:1:32 | GSSA Variable request | +| mongoengine_bad.py:1:26:1:32 | GSSA Variable request | mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for mongoengine_bad.request | | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_bad.py:18:21:18:32 | ControlFlowNode for Attribute | | mongoengine_bad.py:18:21:18:32 | ControlFlowNode for Attribute | mongoengine_bad.py:18:21:18:42 | ControlFlowNode for Subscript | | mongoengine_bad.py:18:21:18:42 | ControlFlowNode for Subscript | mongoengine_bad.py:19:30:19:42 | ControlFlowNode for unsafe_search | @@ -44,6 +59,11 @@ edges | mongoengine_bad.py:57:21:57:42 | ControlFlowNode for Subscript | mongoengine_bad.py:58:30:58:42 | ControlFlowNode for unsafe_search | | mongoengine_bad.py:58:19:58:43 | ControlFlowNode for Attribute() | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | | mongoengine_bad.py:58:30:58:42 | ControlFlowNode for unsafe_search | mongoengine_bad.py:58:19:58:43 | ControlFlowNode for Attribute() | +| pymongo_test.py:0:0:0:0 | ModuleVariableNode for pymongo_test.request | pymongo_test.py:12:21:12:27 | ControlFlowNode for request | +| pymongo_test.py:0:0:0:0 | ModuleVariableNode for pymongo_test.request | pymongo_test.py:29:27:29:33 | ControlFlowNode for request | +| pymongo_test.py:0:0:0:0 | ModuleVariableNode for pymongo_test.request | pymongo_test.py:39:27:39:33 | ControlFlowNode for request | +| pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:1:26:1:32 | GSSA Variable request | +| pymongo_test.py:1:26:1:32 | GSSA Variable request | pymongo_test.py:0:0:0:0 | ModuleVariableNode for pymongo_test.request | | pymongo_test.py:12:21:12:27 | ControlFlowNode for request | pymongo_test.py:12:21:12:32 | ControlFlowNode for Attribute | | pymongo_test.py:12:21:12:32 | ControlFlowNode for Attribute | pymongo_test.py:12:21:12:42 | ControlFlowNode for Subscript | | pymongo_test.py:12:21:12:42 | ControlFlowNode for Subscript | pymongo_test.py:13:30:13:42 | ControlFlowNode for unsafe_search | @@ -58,6 +78,9 @@ edges | pymongo_test.py:39:27:39:38 | ControlFlowNode for Attribute | pymongo_test.py:39:27:39:50 | ControlFlowNode for Subscript | | pymongo_test.py:39:27:39:50 | ControlFlowNode for Subscript | pymongo_test.py:39:16:39:51 | ControlFlowNode for Attribute() | nodes +| flask_mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for flask_mongoengine_bad.request | semmle.label | ModuleVariableNode for flask_mongoengine_bad.request | +| flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| flask_mongoengine_bad.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_mongoengine_bad.py:19:21:19:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_mongoengine_bad.py:19:21:19:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -70,12 +93,18 @@ nodes | flask_mongoengine_bad.py:27:19:27:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | flask_mongoengine_bad.py:27:30:27:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| flask_pymongo_bad.py:0:0:0:0 | ModuleVariableNode for flask_pymongo_bad.request | semmle.label | ModuleVariableNode for flask_pymongo_bad.request | +| flask_pymongo_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| flask_pymongo_bad.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_pymongo_bad.py:11:21:11:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_pymongo_bad.py:11:21:11:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | flask_pymongo_bad.py:12:19:12:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | flask_pymongo_bad.py:12:30:12:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| mongoengine_bad.py:0:0:0:0 | ModuleVariableNode for mongoengine_bad.request | semmle.label | ModuleVariableNode for mongoengine_bad.request | +| mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| mongoengine_bad.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | mongoengine_bad.py:18:21:18:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | mongoengine_bad.py:18:21:18:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -112,6 +141,9 @@ nodes | mongoengine_bad.py:58:19:58:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | | mongoengine_bad.py:58:30:58:42 | ControlFlowNode for unsafe_search | semmle.label | ControlFlowNode for unsafe_search | | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | +| pymongo_test.py:0:0:0:0 | ModuleVariableNode for pymongo_test.request | semmle.label | ModuleVariableNode for pymongo_test.request | +| pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| pymongo_test.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | pymongo_test.py:12:21:12:27 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | pymongo_test.py:12:21:12:32 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | pymongo_test.py:12:21:12:42 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -130,15 +162,15 @@ nodes | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | subpaths #select -| flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | This NoSQL query contains an unsanitized $@. | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | user-provided value | -| flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | flask_mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | flask_mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | user-provided value | -| flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | user-provided value | -| pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | pymongo_test.py:12:21:12:27 | ControlFlowNode for request | pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | pymongo_test.py:12:21:12:27 | ControlFlowNode for request | user-provided value | -| pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | pymongo_test.py:29:27:29:33 | ControlFlowNode for request | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | pymongo_test.py:29:27:29:33 | ControlFlowNode for request | user-provided value | -| pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | pymongo_test.py:39:27:39:33 | ControlFlowNode for request | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | pymongo_test.py:39:27:39:33 | ControlFlowNode for request | user-provided value | +| flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | This NoSQL query contains an unsanitized $@. | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | flask_mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | flask_pymongo_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | flask_pymongo_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | pymongo_test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected index fcb2d3103eb..c64a6943813 100644 --- a/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected +++ b/python/ql/test/query-tests/Security/CWE-020-ExternalAPIs/UntrustedDataToExternalAPI.expected @@ -1,10 +1,16 @@ edges +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:13:16:13:22 | ControlFlowNode for request | +| test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:5:26:5:32 | GSSA Variable request | +| test.py:5:26:5:32 | GSSA Variable request | test.py:0:0:0:0 | ModuleVariableNode for test.request | | test.py:13:16:13:22 | ControlFlowNode for request | test.py:13:16:13:27 | ControlFlowNode for Attribute | | test.py:13:16:13:27 | ControlFlowNode for Attribute | test.py:15:36:15:39 | ControlFlowNode for data | nodes +| test.py:0:0:0:0 | ModuleVariableNode for test.request | semmle.label | ModuleVariableNode for test.request | +| test.py:5:26:5:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test.py:5:26:5:32 | GSSA Variable request | semmle.label | GSSA Variable request | | test.py:13:16:13:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test.py:13:16:13:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:15:36:15:39 | ControlFlowNode for data | semmle.label | ControlFlowNode for data | subpaths #select -| test.py:15:36:15:39 | ControlFlowNode for data | test.py:13:16:13:22 | ControlFlowNode for request | test.py:15:36:15:39 | ControlFlowNode for data | Call to hmac.new [param 1] with untrusted data from $@. | test.py:13:16:13:22 | ControlFlowNode for request | ControlFlowNode for request | +| test.py:15:36:15:39 | ControlFlowNode for data | test.py:5:26:5:32 | ControlFlowNode for ImportMember | test.py:15:36:15:39 | ControlFlowNode for data | Call to hmac.new [param 1] with untrusted data from $@. | test.py:5:26:5:32 | ControlFlowNode for ImportMember | ControlFlowNode for ImportMember | diff --git a/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected b/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected index a206bf683cf..4d92275ff36 100644 --- a/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected @@ -1,6 +1,22 @@ edges +| flask_path_injection.py:0:0:0:0 | ModuleVariableNode for flask_path_injection.request | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | +| flask_path_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_path_injection.py:1:26:1:32 | GSSA Variable request | +| flask_path_injection.py:1:26:1:32 | GSSA Variable request | flask_path_injection.py:0:0:0:0 | ModuleVariableNode for flask_path_injection.request | | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | flask_path_injection.py:19:15:19:26 | ControlFlowNode for Attribute | | flask_path_injection.py:19:15:19:26 | ControlFlowNode for Attribute | flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:12:16:12:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:19:16:19:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:27:16:27:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:46:16:46:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:63:16:63:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:84:16:84:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:107:16:107:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:118:16:118:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:129:16:129:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:138:16:138:22 | ControlFlowNode for request | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | path_injection.py:149:16:149:22 | ControlFlowNode for request | +| path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:3:26:3:32 | GSSA Variable request | +| path_injection.py:3:26:3:32 | GSSA Variable request | path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | | path_injection.py:12:16:12:22 | ControlFlowNode for request | path_injection.py:12:16:12:27 | ControlFlowNode for Attribute | | path_injection.py:12:16:12:27 | ControlFlowNode for Attribute | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | | path_injection.py:19:16:19:22 | ControlFlowNode for request | path_injection.py:19:16:19:27 | ControlFlowNode for Attribute | @@ -33,6 +49,9 @@ edges | path_injection.py:138:16:138:27 | ControlFlowNode for Attribute | path_injection.py:142:14:142:17 | ControlFlowNode for path | | path_injection.py:149:16:149:22 | ControlFlowNode for request | path_injection.py:149:16:149:27 | ControlFlowNode for Attribute | | path_injection.py:149:16:149:27 | ControlFlowNode for Attribute | path_injection.py:152:18:152:21 | ControlFlowNode for path | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:9:12:9:18 | ControlFlowNode for request | +| test.py:3:26:3:32 | ControlFlowNode for ImportMember | test.py:3:26:3:32 | GSSA Variable request | +| test.py:3:26:3:32 | GSSA Variable request | test.py:0:0:0:0 | ModuleVariableNode for test.request | | test.py:9:12:9:18 | ControlFlowNode for request | test.py:9:12:9:23 | ControlFlowNode for Attribute | | test.py:9:12:9:23 | ControlFlowNode for Attribute | test.py:9:12:9:39 | ControlFlowNode for Attribute() | | test.py:9:12:9:39 | ControlFlowNode for Attribute() | test.py:18:9:18:16 | ControlFlowNode for source() | @@ -52,9 +71,15 @@ edges | test.py:48:23:48:23 | ControlFlowNode for x | test.py:12:15:12:15 | ControlFlowNode for x | | test.py:48:23:48:23 | ControlFlowNode for x | test.py:48:13:48:24 | ControlFlowNode for normalize() | nodes +| flask_path_injection.py:0:0:0:0 | ModuleVariableNode for flask_path_injection.request | semmle.label | ModuleVariableNode for flask_path_injection.request | +| flask_path_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| flask_path_injection.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | flask_path_injection.py:19:15:19:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | semmle.label | ControlFlowNode for dirname | +| path_injection.py:0:0:0:0 | ModuleVariableNode for path_injection.request | semmle.label | ModuleVariableNode for path_injection.request | +| path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| path_injection.py:3:26:3:32 | GSSA Variable request | semmle.label | GSSA Variable request | | path_injection.py:12:16:12:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | path_injection.py:12:16:12:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | @@ -100,6 +125,9 @@ nodes | path_injection.py:149:16:149:22 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | path_injection.py:149:16:149:27 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | path_injection.py:152:18:152:21 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | semmle.label | ModuleVariableNode for test.request | +| test.py:3:26:3:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test.py:3:26:3:32 | GSSA Variable request | semmle.label | GSSA Variable request | | test.py:9:12:9:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test.py:9:12:9:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:9:12:9:39 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | @@ -122,21 +150,21 @@ subpaths | test.py:25:19:25:19 | ControlFlowNode for x | test.py:12:15:12:15 | ControlFlowNode for x | test.py:13:12:13:30 | ControlFlowNode for Attribute() | test.py:25:9:25:20 | ControlFlowNode for normalize() | | test.py:48:23:48:23 | ControlFlowNode for x | test.py:12:15:12:15 | ControlFlowNode for x | test.py:13:12:13:30 | ControlFlowNode for Attribute() | test.py:48:13:48:24 | ControlFlowNode for normalize() | #select -| flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | This path depends on a $@. | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | user-provided value | -| path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | path_injection.py:12:16:12:22 | ControlFlowNode for request | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | This path depends on a $@. | path_injection.py:12:16:12:22 | ControlFlowNode for request | user-provided value | -| path_injection.py:21:14:21:18 | ControlFlowNode for npath | path_injection.py:19:16:19:22 | ControlFlowNode for request | path_injection.py:21:14:21:18 | ControlFlowNode for npath | This path depends on a $@. | path_injection.py:19:16:19:22 | ControlFlowNode for request | user-provided value | -| path_injection.py:31:14:31:18 | ControlFlowNode for npath | path_injection.py:27:16:27:22 | ControlFlowNode for request | path_injection.py:31:14:31:18 | ControlFlowNode for npath | This path depends on a $@. | path_injection.py:27:16:27:22 | ControlFlowNode for request | user-provided value | -| path_injection.py:48:14:48:18 | ControlFlowNode for npath | path_injection.py:46:16:46:22 | ControlFlowNode for request | path_injection.py:48:14:48:18 | ControlFlowNode for npath | This path depends on a $@. | path_injection.py:46:16:46:22 | ControlFlowNode for request | user-provided value | -| path_injection.py:65:14:65:18 | ControlFlowNode for npath | path_injection.py:63:16:63:22 | ControlFlowNode for request | path_injection.py:65:14:65:18 | ControlFlowNode for npath | This path depends on a $@. | path_injection.py:63:16:63:22 | ControlFlowNode for request | user-provided value | -| path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | path_injection.py:84:16:84:22 | ControlFlowNode for request | path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | This path depends on a $@. | path_injection.py:84:16:84:22 | ControlFlowNode for request | user-provided value | +| flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | flask_path_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | This path depends on a $@. | flask_path_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | This path depends on a $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| path_injection.py:21:14:21:18 | ControlFlowNode for npath | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:21:14:21:18 | ControlFlowNode for npath | This path depends on a $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| path_injection.py:31:14:31:18 | ControlFlowNode for npath | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:31:14:31:18 | ControlFlowNode for npath | This path depends on a $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| path_injection.py:48:14:48:18 | ControlFlowNode for npath | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:48:14:48:18 | ControlFlowNode for npath | This path depends on a $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| path_injection.py:65:14:65:18 | ControlFlowNode for npath | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:65:14:65:18 | ControlFlowNode for npath | This path depends on a $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | This path depends on a $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | | path_injection.py:94:14:94:17 | ControlFlowNode for path | path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | path_injection.py:94:14:94:17 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | user-provided value | | path_injection.py:102:14:102:17 | ControlFlowNode for path | path_injection.py:98:20:98:22 | ControlFlowNode for foo | path_injection.py:102:14:102:17 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:98:20:98:22 | ControlFlowNode for foo | user-provided value | -| path_injection.py:113:14:113:17 | ControlFlowNode for path | path_injection.py:107:16:107:22 | ControlFlowNode for request | path_injection.py:113:14:113:17 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:107:16:107:22 | ControlFlowNode for request | user-provided value | -| path_injection.py:124:14:124:17 | ControlFlowNode for path | path_injection.py:118:16:118:22 | ControlFlowNode for request | path_injection.py:124:14:124:17 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:118:16:118:22 | ControlFlowNode for request | user-provided value | -| path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | path_injection.py:129:16:129:22 | ControlFlowNode for request | path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | This path depends on a $@. | path_injection.py:129:16:129:22 | ControlFlowNode for request | user-provided value | -| path_injection.py:142:14:142:17 | ControlFlowNode for path | path_injection.py:138:16:138:22 | ControlFlowNode for request | path_injection.py:142:14:142:17 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:138:16:138:22 | ControlFlowNode for request | user-provided value | -| path_injection.py:152:18:152:21 | ControlFlowNode for path | path_injection.py:149:16:149:22 | ControlFlowNode for request | path_injection.py:152:18:152:21 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:149:16:149:22 | ControlFlowNode for request | user-provided value | -| test.py:19:10:19:10 | ControlFlowNode for x | test.py:9:12:9:18 | ControlFlowNode for request | test.py:19:10:19:10 | ControlFlowNode for x | This path depends on a $@. | test.py:9:12:9:18 | ControlFlowNode for request | user-provided value | -| test.py:26:10:26:10 | ControlFlowNode for y | test.py:9:12:9:18 | ControlFlowNode for request | test.py:26:10:26:10 | ControlFlowNode for y | This path depends on a $@. | test.py:9:12:9:18 | ControlFlowNode for request | user-provided value | -| test.py:33:14:33:14 | ControlFlowNode for x | test.py:9:12:9:18 | ControlFlowNode for request | test.py:33:14:33:14 | ControlFlowNode for x | This path depends on a $@. | test.py:9:12:9:18 | ControlFlowNode for request | user-provided value | -| test.py:49:14:49:14 | ControlFlowNode for y | test.py:9:12:9:18 | ControlFlowNode for request | test.py:49:14:49:14 | ControlFlowNode for y | This path depends on a $@. | test.py:9:12:9:18 | ControlFlowNode for request | user-provided value | +| path_injection.py:113:14:113:17 | ControlFlowNode for path | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:113:14:113:17 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| path_injection.py:124:14:124:17 | ControlFlowNode for path | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:124:14:124:17 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | This path depends on a $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| path_injection.py:142:14:142:17 | ControlFlowNode for path | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:142:14:142:17 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| path_injection.py:152:18:152:21 | ControlFlowNode for path | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | path_injection.py:152:18:152:21 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| test.py:19:10:19:10 | ControlFlowNode for x | test.py:3:26:3:32 | ControlFlowNode for ImportMember | test.py:19:10:19:10 | ControlFlowNode for x | This path depends on a $@. | test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| test.py:26:10:26:10 | ControlFlowNode for y | test.py:3:26:3:32 | ControlFlowNode for ImportMember | test.py:26:10:26:10 | ControlFlowNode for y | This path depends on a $@. | test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| test.py:33:14:33:14 | ControlFlowNode for x | test.py:3:26:3:32 | ControlFlowNode for ImportMember | test.py:33:14:33:14 | ControlFlowNode for x | This path depends on a $@. | test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | +| test.py:49:14:49:14 | ControlFlowNode for y | test.py:3:26:3:32 | ControlFlowNode for ImportMember | test.py:49:14:49:14 | ControlFlowNode for y | This path depends on a $@. | test.py:3:26:3:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected index 8930b1a067c..81ae4e63c2f 100644 --- a/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected @@ -1,4 +1,7 @@ edges +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:18:13:18:19 | ControlFlowNode for request | +| command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:5:26:5:32 | GSSA Variable request | +| command_injection.py:5:26:5:32 | GSSA Variable request | command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | @@ -10,6 +13,9 @@ edges | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | nodes +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | semmle.label | ModuleVariableNode for command_injection.request | +| command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| command_injection.py:5:26:5:32 | GSSA Variable request | semmle.label | GSSA Variable request | | command_injection.py:18:13:18:19 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | @@ -23,12 +29,12 @@ nodes | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | subpaths #select -| command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | -| command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | -| command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | -| command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | -| command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | -| command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | -| command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | -| command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | -| command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | +| command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected index 3f072d83d2a..a203a43374d 100644 --- a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected @@ -1,4 +1,14 @@ edges +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:11:13:11:19 | ControlFlowNode for request | +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:18:13:18:19 | ControlFlowNode for request | +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:25:11:25:17 | ControlFlowNode for request | +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:31:13:31:19 | ControlFlowNode for request | +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:38:15:38:21 | ControlFlowNode for request | +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:54:15:54:21 | ControlFlowNode for request | +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:71:12:71:18 | ControlFlowNode for request | +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | command_injection.py:78:12:78:18 | ControlFlowNode for request | +| command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:5:26:5:32 | GSSA Variable request | +| command_injection.py:5:26:5:32 | GSSA Variable request | command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | | command_injection.py:11:13:11:19 | ControlFlowNode for request | command_injection.py:11:13:11:24 | ControlFlowNode for Attribute | | command_injection.py:11:13:11:24 | ControlFlowNode for Attribute | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:18:13:18:24 | ControlFlowNode for Attribute | @@ -21,6 +31,9 @@ edges | command_injection.py:78:12:78:18 | ControlFlowNode for request | command_injection.py:78:12:78:23 | ControlFlowNode for Attribute | | command_injection.py:78:12:78:23 | ControlFlowNode for Attribute | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | nodes +| command_injection.py:0:0:0:0 | ModuleVariableNode for command_injection.request | semmle.label | ModuleVariableNode for command_injection.request | +| command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| command_injection.py:5:26:5:32 | GSSA Variable request | semmle.label | GSSA Variable request | | command_injection.py:11:13:11:19 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | command_injection.py:11:13:11:24 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | @@ -52,16 +65,16 @@ nodes | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | subpaths #select -| command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | command_injection.py:11:13:11:19 | ControlFlowNode for request | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:11:13:11:19 | ControlFlowNode for request | user-provided value | -| command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | -| command_injection.py:26:23:26:25 | ControlFlowNode for cmd | command_injection.py:25:11:25:17 | ControlFlowNode for request | command_injection.py:26:23:26:25 | ControlFlowNode for cmd | This command line depends on a $@. | command_injection.py:25:11:25:17 | ControlFlowNode for request | user-provided value | -| command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | command_injection.py:31:13:31:19 | ControlFlowNode for request | command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:31:13:31:19 | ControlFlowNode for request | user-provided value | -| command_injection.py:41:15:41:21 | ControlFlowNode for command | command_injection.py:38:15:38:21 | ControlFlowNode for request | command_injection.py:41:15:41:21 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:38:15:38:21 | ControlFlowNode for request | user-provided value | -| command_injection.py:42:15:42:21 | ControlFlowNode for command | command_injection.py:38:15:38:21 | ControlFlowNode for request | command_injection.py:42:15:42:21 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:38:15:38:21 | ControlFlowNode for request | user-provided value | -| command_injection.py:55:15:55:21 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:55:15:55:21 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | user-provided value | -| command_injection.py:56:14:56:20 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:56:14:56:20 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | user-provided value | -| command_injection.py:57:21:57:27 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:57:21:57:27 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | user-provided value | -| command_injection.py:58:27:58:33 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:58:27:58:33 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | user-provided value | -| command_injection.py:59:20:59:26 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:59:20:59:26 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | user-provided value | -| command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | command_injection.py:71:12:71:18 | ControlFlowNode for request | command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:71:12:71:18 | ControlFlowNode for request | user-provided value | -| command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | command_injection.py:78:12:78:18 | ControlFlowNode for request | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:78:12:78:18 | ControlFlowNode for request | user-provided value | +| command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:26:23:26:25 | ControlFlowNode for cmd | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:26:23:26:25 | ControlFlowNode for cmd | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:41:15:41:21 | ControlFlowNode for command | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:41:15:41:21 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:42:15:42:21 | ControlFlowNode for command | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:42:15:42:21 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:55:15:55:21 | ControlFlowNode for command | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:55:15:55:21 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:56:14:56:20 | ControlFlowNode for command | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:56:14:56:20 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:57:21:57:27 | ControlFlowNode for command | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:57:21:57:27 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:58:27:58:33 | ControlFlowNode for command | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:58:27:58:33 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:59:20:59:26 | ControlFlowNode for command | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:59:20:59:26 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | +| command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:5:26:5:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected index 00f98fbaa6c..dfdbce34124 100644 --- a/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected +++ b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected @@ -1,4 +1,9 @@ edges +| reflected_xss.py:0:0:0:0 | ModuleVariableNode for reflected_xss.request | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | +| reflected_xss.py:0:0:0:0 | ModuleVariableNode for reflected_xss.request | reflected_xss.py:21:23:21:29 | ControlFlowNode for request | +| reflected_xss.py:0:0:0:0 | ModuleVariableNode for reflected_xss.request | reflected_xss.py:27:23:27:29 | ControlFlowNode for request | +| reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | reflected_xss.py:2:26:2:32 | GSSA Variable request | +| reflected_xss.py:2:26:2:32 | GSSA Variable request | reflected_xss.py:0:0:0:0 | ModuleVariableNode for reflected_xss.request | | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | reflected_xss.py:9:18:9:29 | ControlFlowNode for Attribute | | reflected_xss.py:9:18:9:29 | ControlFlowNode for Attribute | reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | | reflected_xss.py:21:23:21:29 | ControlFlowNode for request | reflected_xss.py:21:23:21:34 | ControlFlowNode for Attribute | @@ -6,6 +11,9 @@ edges | reflected_xss.py:27:23:27:29 | ControlFlowNode for request | reflected_xss.py:27:23:27:34 | ControlFlowNode for Attribute | | reflected_xss.py:27:23:27:34 | ControlFlowNode for Attribute | reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | nodes +| reflected_xss.py:0:0:0:0 | ModuleVariableNode for reflected_xss.request | semmle.label | ModuleVariableNode for reflected_xss.request | +| reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| reflected_xss.py:2:26:2:32 | GSSA Variable request | semmle.label | GSSA Variable request | | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | reflected_xss.py:9:18:9:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | @@ -17,6 +25,6 @@ nodes | reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | subpaths #select -| reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | Cross-site scripting vulnerability due to a $@. | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | user-provided value | -| reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | reflected_xss.py:21:23:21:29 | ControlFlowNode for request | reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to a $@. | reflected_xss.py:21:23:21:29 | ControlFlowNode for request | user-provided value | -| reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | reflected_xss.py:27:23:27:29 | ControlFlowNode for request | reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to a $@. | reflected_xss.py:27:23:27:29 | ControlFlowNode for request | user-provided value | +| reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | Cross-site scripting vulnerability due to a $@. | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to a $@. | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to a $@. | reflected_xss.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.expected b/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.expected index 186e1b02181..6b71a42cd5e 100644 --- a/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.expected @@ -1,4 +1,14 @@ edges +| ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | +| ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | +| ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | ldap3_bad.py:14:21:14:27 | ControlFlowNode for request | +| ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | +| ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | +| ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | ldap3_bad.py:31:21:31:27 | ControlFlowNode for request | +| ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:1:19:1:25 | GSSA Variable request | +| ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:1:19:1:25 | GSSA Variable request | +| ldap3_bad.py:1:19:1:25 | GSSA Variable request | ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | +| ldap3_bad.py:1:19:1:25 | GSSA Variable request | ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | ldap3_bad.py:13:17:13:28 | ControlFlowNode for Attribute | | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | ldap3_bad.py:14:21:14:32 | ControlFlowNode for Attribute | | ldap3_bad.py:13:17:13:28 | ControlFlowNode for Attribute | ldap3_bad.py:13:17:13:34 | ControlFlowNode for Subscript | @@ -13,6 +23,19 @@ edges | ldap3_bad.py:31:21:31:27 | ControlFlowNode for request | ldap3_bad.py:31:21:31:32 | ControlFlowNode for Attribute | | ldap3_bad.py:31:21:31:32 | ControlFlowNode for Attribute | ldap3_bad.py:31:21:31:44 | ControlFlowNode for Subscript | | ldap3_bad.py:31:21:31:44 | ControlFlowNode for Subscript | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:14:21:14:27 | ControlFlowNode for request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:31:21:31:27 | ControlFlowNode for request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | ldap_bad.py:48:21:48:27 | ControlFlowNode for request | +| ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:1:19:1:25 | GSSA Variable request | +| ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:1:19:1:25 | GSSA Variable request | +| ldap_bad.py:1:19:1:25 | GSSA Variable request | ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | +| ldap_bad.py:1:19:1:25 | GSSA Variable request | ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | ldap_bad.py:13:17:13:28 | ControlFlowNode for Attribute | | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | ldap_bad.py:14:21:14:32 | ControlFlowNode for Attribute | | ldap_bad.py:13:17:13:28 | ControlFlowNode for Attribute | ldap_bad.py:13:17:13:34 | ControlFlowNode for Subscript | @@ -35,6 +58,12 @@ edges | ldap_bad.py:48:21:48:32 | ControlFlowNode for Attribute | ldap_bad.py:48:21:48:44 | ControlFlowNode for Subscript | | ldap_bad.py:48:21:48:44 | ControlFlowNode for Subscript | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | nodes +| ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | semmle.label | ModuleVariableNode for ldap3_bad.request | +| ldap3_bad.py:0:0:0:0 | ModuleVariableNode for ldap3_bad.request | semmle.label | ModuleVariableNode for ldap3_bad.request | +| ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| ldap3_bad.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | +| ldap3_bad.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | ldap3_bad.py:13:17:13:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -53,6 +82,12 @@ nodes | ldap3_bad.py:31:21:31:44 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | semmle.label | ControlFlowNode for dn | | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | semmle.label | ControlFlowNode for search_filter | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | semmle.label | ModuleVariableNode for ldap_bad.request | +| ldap_bad.py:0:0:0:0 | ModuleVariableNode for ldap_bad.request | semmle.label | ModuleVariableNode for ldap_bad.request | +| ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| ldap_bad.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | +| ldap_bad.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | ldap_bad.py:13:17:13:28 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -82,18 +117,13 @@ nodes | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | semmle.label | ControlFlowNode for search_filter | subpaths #select -| ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | user-provided value | -| ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | user-provided value | -| ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | ldap3_bad.py:14:21:14:27 | ControlFlowNode for request | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap3_bad.py:14:21:14:27 | ControlFlowNode for request | user-provided value | -| ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | user-provided value | -| ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | user-provided value | -| ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | ldap3_bad.py:31:21:31:27 | ControlFlowNode for request | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap3_bad.py:31:21:31:27 | ControlFlowNode for request | user-provided value | -| ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | user-provided value | -| ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | user-provided value | -| ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | ldap_bad.py:14:21:14:27 | ControlFlowNode for request | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:14:21:14:27 | ControlFlowNode for request | user-provided value | -| ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | user-provided value | -| ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | user-provided value | -| ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | ldap_bad.py:31:21:31:27 | ControlFlowNode for request | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:31:21:31:27 | ControlFlowNode for request | user-provided value | -| ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | user-provided value | -| ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | user-provided value | -| ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | ldap_bad.py:48:21:48:27 | ControlFlowNode for request | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:48:21:48:27 | ControlFlowNode for request | user-provided value | +| ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap3_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-094-CodeInjection/CodeInjection.expected b/python/ql/test/query-tests/Security/CWE-094-CodeInjection/CodeInjection.expected index 6b543c3aa18..68cc9d9916a 100644 --- a/python/ql/test/query-tests/Security/CWE-094-CodeInjection/CodeInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-094-CodeInjection/CodeInjection.expected @@ -1,4 +1,8 @@ edges +| code_injection.py:0:0:0:0 | ModuleVariableNode for code_injection.request | code_injection.py:6:12:6:18 | ControlFlowNode for request | +| code_injection.py:0:0:0:0 | ModuleVariableNode for code_injection.request | code_injection.py:18:16:18:22 | ControlFlowNode for request | +| code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | code_injection.py:1:26:1:32 | GSSA Variable request | +| code_injection.py:1:26:1:32 | GSSA Variable request | code_injection.py:0:0:0:0 | ModuleVariableNode for code_injection.request | | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | | code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | code_injection.py:7:10:7:13 | ControlFlowNode for code | | code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | code_injection.py:8:10:8:13 | ControlFlowNode for code | @@ -6,6 +10,9 @@ edges | code_injection.py:18:16:18:22 | ControlFlowNode for request | code_injection.py:18:16:18:27 | ControlFlowNode for Attribute | | code_injection.py:18:16:18:27 | ControlFlowNode for Attribute | code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | nodes +| code_injection.py:0:0:0:0 | ModuleVariableNode for code_injection.request | semmle.label | ModuleVariableNode for code_injection.request | +| code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| code_injection.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | code_injection.py:6:12:6:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | code_injection.py:6:12:6:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | code_injection.py:7:10:7:13 | ControlFlowNode for code | semmle.label | ControlFlowNode for code | @@ -16,7 +23,7 @@ nodes | code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | semmle.label | ControlFlowNode for obj_name | subpaths #select -| code_injection.py:7:10:7:13 | ControlFlowNode for code | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:7:10:7:13 | ControlFlowNode for code | This code execution depends on a $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | user-provided value | -| code_injection.py:8:10:8:13 | ControlFlowNode for code | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:8:10:8:13 | ControlFlowNode for code | This code execution depends on a $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | user-provided value | -| code_injection.py:10:10:10:12 | ControlFlowNode for cmd | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:10:10:10:12 | ControlFlowNode for cmd | This code execution depends on a $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | user-provided value | -| code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | code_injection.py:18:16:18:22 | ControlFlowNode for request | code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | This code execution depends on a $@. | code_injection.py:18:16:18:22 | ControlFlowNode for request | user-provided value | +| code_injection.py:7:10:7:13 | ControlFlowNode for code | code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | code_injection.py:7:10:7:13 | ControlFlowNode for code | This code execution depends on a $@. | code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| code_injection.py:8:10:8:13 | ControlFlowNode for code | code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | code_injection.py:8:10:8:13 | ControlFlowNode for code | This code execution depends on a $@. | code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| code_injection.py:10:10:10:12 | ControlFlowNode for cmd | code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | code_injection.py:10:10:10:12 | ControlFlowNode for cmd | This code execution depends on a $@. | code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | This code execution depends on a $@. | code_injection.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-117-LogInjection/LogInjection.expected b/python/ql/test/query-tests/Security/CWE-117-LogInjection/LogInjection.expected index e9faa8b46f9..561c898a928 100644 --- a/python/ql/test/query-tests/Security/CWE-117-LogInjection/LogInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-117-LogInjection/LogInjection.expected @@ -1,4 +1,10 @@ edges +| LogInjectionBad.py:0:0:0:0 | ModuleVariableNode for LogInjectionBad.request | LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | +| LogInjectionBad.py:0:0:0:0 | ModuleVariableNode for LogInjectionBad.request | LogInjectionBad.py:23:12:23:18 | ControlFlowNode for request | +| LogInjectionBad.py:0:0:0:0 | ModuleVariableNode for LogInjectionBad.request | LogInjectionBad.py:29:12:29:18 | ControlFlowNode for request | +| LogInjectionBad.py:0:0:0:0 | ModuleVariableNode for LogInjectionBad.request | LogInjectionBad.py:35:12:35:18 | ControlFlowNode for request | +| LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | LogInjectionBad.py:7:19:7:25 | GSSA Variable request | +| LogInjectionBad.py:7:19:7:25 | GSSA Variable request | LogInjectionBad.py:0:0:0:0 | ModuleVariableNode for LogInjectionBad.request | | LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | LogInjectionBad.py:17:12:17:23 | ControlFlowNode for Attribute | | LogInjectionBad.py:17:12:17:23 | ControlFlowNode for Attribute | LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | | LogInjectionBad.py:23:12:23:18 | ControlFlowNode for request | LogInjectionBad.py:23:12:23:23 | ControlFlowNode for Attribute | @@ -8,6 +14,9 @@ edges | LogInjectionBad.py:35:12:35:18 | ControlFlowNode for request | LogInjectionBad.py:35:12:35:23 | ControlFlowNode for Attribute | | LogInjectionBad.py:35:12:35:23 | ControlFlowNode for Attribute | LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | nodes +| LogInjectionBad.py:0:0:0:0 | ModuleVariableNode for LogInjectionBad.request | semmle.label | ModuleVariableNode for LogInjectionBad.request | +| LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| LogInjectionBad.py:7:19:7:25 | GSSA Variable request | semmle.label | GSSA Variable request | | LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | LogInjectionBad.py:17:12:17:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | @@ -22,7 +31,7 @@ nodes | LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | subpaths #select -| LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | This log entry depends on a $@. | LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | user-provided value | -| LogInjectionBad.py:24:18:24:37 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:23:12:23:18 | ControlFlowNode for request | LogInjectionBad.py:24:18:24:37 | ControlFlowNode for BinaryExpr | This log entry depends on a $@. | LogInjectionBad.py:23:12:23:18 | ControlFlowNode for request | user-provided value | -| LogInjectionBad.py:30:25:30:44 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:29:12:29:18 | ControlFlowNode for request | LogInjectionBad.py:30:25:30:44 | ControlFlowNode for BinaryExpr | This log entry depends on a $@. | LogInjectionBad.py:29:12:29:18 | ControlFlowNode for request | user-provided value | -| LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:35:12:35:18 | ControlFlowNode for request | LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | This log entry depends on a $@. | LogInjectionBad.py:35:12:35:18 | ControlFlowNode for request | user-provided value | +| LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | This log entry depends on a $@. | LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | user-provided value | +| LogInjectionBad.py:24:18:24:37 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | LogInjectionBad.py:24:18:24:37 | ControlFlowNode for BinaryExpr | This log entry depends on a $@. | LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | user-provided value | +| LogInjectionBad.py:30:25:30:44 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | LogInjectionBad.py:30:25:30:44 | ControlFlowNode for BinaryExpr | This log entry depends on a $@. | LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | user-provided value | +| LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | This log entry depends on a $@. | LogInjectionBad.py:7:19:7:25 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected b/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected index 2a456dbcc70..80dd354c35c 100644 --- a/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected +++ b/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected @@ -1,10 +1,16 @@ edges +| unsafe_deserialization.py:0:0:0:0 | ModuleVariableNode for unsafe_deserialization.request | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | +| unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | unsafe_deserialization.py:8:26:8:32 | GSSA Variable request | +| unsafe_deserialization.py:8:26:8:32 | GSSA Variable request | unsafe_deserialization.py:0:0:0:0 | ModuleVariableNode for unsafe_deserialization.request | | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | nodes +| unsafe_deserialization.py:0:0:0:0 | ModuleVariableNode for unsafe_deserialization.request | semmle.label | ModuleVariableNode for unsafe_deserialization.request | +| unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| unsafe_deserialization.py:8:26:8:32 | GSSA Variable request | semmle.label | GSSA Variable request | | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | unsafe_deserialization.py:14:15:14:26 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload | @@ -13,7 +19,7 @@ nodes | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload | subpaths #select -| unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | Unsafe deserialization depends on a $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | user-provided value | -| unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | Unsafe deserialization depends on a $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | user-provided value | -| unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | Unsafe deserialization depends on a $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | user-provided value | -| unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | Unsafe deserialization depends on a $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | user-provided value | +| unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | Unsafe deserialization depends on a $@. | unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | user-provided value | +| unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | Unsafe deserialization depends on a $@. | unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | user-provided value | +| unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | Unsafe deserialization depends on a $@. | unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | user-provided value | +| unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | Unsafe deserialization depends on a $@. | unsafe_deserialization.py:8:26:8:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected index dddd8fc4b0b..43e62be9707 100644 --- a/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected +++ b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected @@ -1,4 +1,14 @@ edges +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:7:14:7:20 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:30:17:30:23 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:37:17:37:23 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:44:17:44:23 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:60:17:60:23 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:67:17:67:23 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:74:17:74:23 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:81:17:81:23 | ControlFlowNode for request | +| test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:1:26:1:32 | GSSA Variable request | +| test.py:1:26:1:32 | GSSA Variable request | test.py:0:0:0:0 | ModuleVariableNode for test.request | | test.py:7:14:7:20 | ControlFlowNode for request | test.py:7:14:7:25 | ControlFlowNode for Attribute | | test.py:7:14:7:25 | ControlFlowNode for Attribute | test.py:8:21:8:26 | ControlFlowNode for target | | test.py:30:17:30:23 | ControlFlowNode for request | test.py:30:17:30:28 | ControlFlowNode for Attribute | @@ -16,6 +26,9 @@ edges | test.py:81:17:81:23 | ControlFlowNode for request | test.py:81:17:81:28 | ControlFlowNode for Attribute | | test.py:81:17:81:28 | ControlFlowNode for Attribute | test.py:83:21:83:26 | ControlFlowNode for unsafe | nodes +| test.py:0:0:0:0 | ModuleVariableNode for test.request | semmle.label | ModuleVariableNode for test.request | +| test.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | test.py:7:14:7:20 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test.py:7:14:7:25 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:8:21:8:26 | ControlFlowNode for target | semmle.label | ControlFlowNode for target | @@ -42,11 +55,11 @@ nodes | test.py:83:21:83:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe | subpaths #select -| test.py:8:21:8:26 | ControlFlowNode for target | test.py:7:14:7:20 | ControlFlowNode for request | test.py:8:21:8:26 | ControlFlowNode for target | Untrusted URL redirection depends on a $@. | test.py:7:14:7:20 | ControlFlowNode for request | user-provided value | -| test.py:32:21:32:24 | ControlFlowNode for safe | test.py:30:17:30:23 | ControlFlowNode for request | test.py:32:21:32:24 | ControlFlowNode for safe | Untrusted URL redirection depends on a $@. | test.py:30:17:30:23 | ControlFlowNode for request | user-provided value | -| test.py:39:21:39:24 | ControlFlowNode for safe | test.py:37:17:37:23 | ControlFlowNode for request | test.py:39:21:39:24 | ControlFlowNode for safe | Untrusted URL redirection depends on a $@. | test.py:37:17:37:23 | ControlFlowNode for request | user-provided value | -| test.py:46:21:46:24 | ControlFlowNode for safe | test.py:44:17:44:23 | ControlFlowNode for request | test.py:46:21:46:24 | ControlFlowNode for safe | Untrusted URL redirection depends on a $@. | test.py:44:17:44:23 | ControlFlowNode for request | user-provided value | -| test.py:62:21:62:26 | ControlFlowNode for unsafe | test.py:60:17:60:23 | ControlFlowNode for request | test.py:62:21:62:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:60:17:60:23 | ControlFlowNode for request | user-provided value | -| test.py:69:21:69:26 | ControlFlowNode for unsafe | test.py:67:17:67:23 | ControlFlowNode for request | test.py:69:21:69:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:67:17:67:23 | ControlFlowNode for request | user-provided value | -| test.py:76:21:76:26 | ControlFlowNode for unsafe | test.py:74:17:74:23 | ControlFlowNode for request | test.py:76:21:76:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:74:17:74:23 | ControlFlowNode for request | user-provided value | -| test.py:83:21:83:26 | ControlFlowNode for unsafe | test.py:81:17:81:23 | ControlFlowNode for request | test.py:83:21:83:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:81:17:81:23 | ControlFlowNode for request | user-provided value | +| test.py:8:21:8:26 | ControlFlowNode for target | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:8:21:8:26 | ControlFlowNode for target | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| test.py:32:21:32:24 | ControlFlowNode for safe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:32:21:32:24 | ControlFlowNode for safe | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| test.py:39:21:39:24 | ControlFlowNode for safe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:39:21:39:24 | ControlFlowNode for safe | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| test.py:46:21:46:24 | ControlFlowNode for safe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:46:21:46:24 | ControlFlowNode for safe | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| test.py:62:21:62:26 | ControlFlowNode for unsafe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:62:21:62:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| test.py:69:21:69:26 | ControlFlowNode for unsafe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:69:21:69:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| test.py:76:21:76:26 | ControlFlowNode for unsafe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:76:21:76:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| test.py:83:21:83:26 | ControlFlowNode for unsafe | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:83:21:83:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-611-Xxe/Xxe.expected b/python/ql/test/query-tests/Security/CWE-611-Xxe/Xxe.expected index 7cddfb74205..3084f83c396 100644 --- a/python/ql/test/query-tests/Security/CWE-611-Xxe/Xxe.expected +++ b/python/ql/test/query-tests/Security/CWE-611-Xxe/Xxe.expected @@ -1,4 +1,8 @@ edges +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:8:19:8:25 | ControlFlowNode for request | +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:19:19:19:25 | ControlFlowNode for request | +| test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:1:26:1:32 | GSSA Variable request | +| test.py:1:26:1:32 | GSSA Variable request | test.py:0:0:0:0 | ModuleVariableNode for test.request | | test.py:8:19:8:25 | ControlFlowNode for request | test.py:8:19:8:30 | ControlFlowNode for Attribute | | test.py:8:19:8:30 | ControlFlowNode for Attribute | test.py:8:19:8:45 | ControlFlowNode for Subscript | | test.py:8:19:8:45 | ControlFlowNode for Subscript | test.py:9:34:9:44 | ControlFlowNode for xml_content | @@ -6,6 +10,9 @@ edges | test.py:19:19:19:30 | ControlFlowNode for Attribute | test.py:19:19:19:45 | ControlFlowNode for Subscript | | test.py:19:19:19:45 | ControlFlowNode for Subscript | test.py:30:34:30:44 | ControlFlowNode for xml_content | nodes +| test.py:0:0:0:0 | ModuleVariableNode for test.request | semmle.label | ModuleVariableNode for test.request | +| test.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | test.py:8:19:8:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test.py:8:19:8:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:8:19:8:45 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -16,5 +23,5 @@ nodes | test.py:30:34:30:44 | ControlFlowNode for xml_content | semmle.label | ControlFlowNode for xml_content | subpaths #select -| test.py:9:34:9:44 | ControlFlowNode for xml_content | test.py:8:19:8:25 | ControlFlowNode for request | test.py:9:34:9:44 | ControlFlowNode for xml_content | XML parsing depends on a $@ without guarding against external entity expansion. | test.py:8:19:8:25 | ControlFlowNode for request | user-provided value | -| test.py:30:34:30:44 | ControlFlowNode for xml_content | test.py:19:19:19:25 | ControlFlowNode for request | test.py:30:34:30:44 | ControlFlowNode for xml_content | XML parsing depends on a $@ without guarding against external entity expansion. | test.py:19:19:19:25 | ControlFlowNode for request | user-provided value | +| test.py:9:34:9:44 | ControlFlowNode for xml_content | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:9:34:9:44 | ControlFlowNode for xml_content | XML parsing depends on a $@ without guarding against external entity expansion. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| test.py:30:34:30:44 | ControlFlowNode for xml_content | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:30:34:30:44 | ControlFlowNode for xml_content | XML parsing depends on a $@ without guarding against external entity expansion. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-643-XPathInjection/XpathInjection.expected b/python/ql/test/query-tests/Security/CWE-643-XPathInjection/XpathInjection.expected index 1a08fb7530a..6ecac65dad0 100644 --- a/python/ql/test/query-tests/Security/CWE-643-XPathInjection/XpathInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-643-XPathInjection/XpathInjection.expected @@ -2,6 +2,13 @@ edges | xpathBad.py:9:7:9:13 | ControlFlowNode for request | xpathBad.py:10:13:10:23 | ControlFlowNode for Attribute | | xpathBad.py:10:13:10:23 | ControlFlowNode for Attribute | xpathBad.py:10:13:10:32 | ControlFlowNode for Subscript | | xpathBad.py:10:13:10:32 | ControlFlowNode for Subscript | xpathBad.py:13:20:13:43 | ControlFlowNode for BinaryExpr | +| xpathFlow.py:0:0:0:0 | ModuleVariableNode for xpathFlow.request | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | +| xpathFlow.py:0:0:0:0 | ModuleVariableNode for xpathFlow.request | xpathFlow.py:20:18:20:24 | ControlFlowNode for request | +| xpathFlow.py:0:0:0:0 | ModuleVariableNode for xpathFlow.request | xpathFlow.py:30:18:30:24 | ControlFlowNode for request | +| xpathFlow.py:0:0:0:0 | ModuleVariableNode for xpathFlow.request | xpathFlow.py:39:18:39:24 | ControlFlowNode for request | +| xpathFlow.py:0:0:0:0 | ModuleVariableNode for xpathFlow.request | xpathFlow.py:47:18:47:24 | ControlFlowNode for request | +| xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | xpathFlow.py:2:26:2:32 | GSSA Variable request | +| xpathFlow.py:2:26:2:32 | GSSA Variable request | xpathFlow.py:0:0:0:0 | ModuleVariableNode for xpathFlow.request | | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | xpathFlow.py:11:18:11:29 | ControlFlowNode for Attribute | | xpathFlow.py:11:18:11:29 | ControlFlowNode for Attribute | xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | | xpathFlow.py:20:18:20:24 | ControlFlowNode for request | xpathFlow.py:20:18:20:29 | ControlFlowNode for Attribute | @@ -17,6 +24,9 @@ nodes | xpathBad.py:10:13:10:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | xpathBad.py:10:13:10:32 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | xpathBad.py:13:20:13:43 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | +| xpathFlow.py:0:0:0:0 | ModuleVariableNode for xpathFlow.request | semmle.label | ModuleVariableNode for xpathFlow.request | +| xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| xpathFlow.py:2:26:2:32 | GSSA Variable request | semmle.label | GSSA Variable request | | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | xpathFlow.py:11:18:11:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | semmle.label | ControlFlowNode for xpathQuery | @@ -35,8 +45,8 @@ nodes subpaths #select | xpathBad.py:13:20:13:43 | ControlFlowNode for BinaryExpr | xpathBad.py:9:7:9:13 | ControlFlowNode for request | xpathBad.py:13:20:13:43 | ControlFlowNode for BinaryExpr | XPath expression depends on a $@. | xpathBad.py:9:7:9:13 | ControlFlowNode for request | user-provided value | -| xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | XPath expression depends on a $@. | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | user-provided value | -| xpathFlow.py:23:29:23:38 | ControlFlowNode for xpathQuery | xpathFlow.py:20:18:20:24 | ControlFlowNode for request | xpathFlow.py:23:29:23:38 | ControlFlowNode for xpathQuery | XPath expression depends on a $@. | xpathFlow.py:20:18:20:24 | ControlFlowNode for request | user-provided value | -| xpathFlow.py:32:29:32:38 | ControlFlowNode for xpathQuery | xpathFlow.py:30:18:30:24 | ControlFlowNode for request | xpathFlow.py:32:29:32:38 | ControlFlowNode for xpathQuery | XPath expression depends on a $@. | xpathFlow.py:30:18:30:24 | ControlFlowNode for request | user-provided value | -| xpathFlow.py:41:31:41:40 | ControlFlowNode for xpathQuery | xpathFlow.py:39:18:39:24 | ControlFlowNode for request | xpathFlow.py:41:31:41:40 | ControlFlowNode for xpathQuery | XPath expression depends on a $@. | xpathFlow.py:39:18:39:24 | ControlFlowNode for request | user-provided value | -| xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | xpathFlow.py:47:18:47:24 | ControlFlowNode for request | xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | XPath expression depends on a $@. | xpathFlow.py:47:18:47:24 | ControlFlowNode for request | user-provided value | +| xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | XPath expression depends on a $@. | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| xpathFlow.py:23:29:23:38 | ControlFlowNode for xpathQuery | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | xpathFlow.py:23:29:23:38 | ControlFlowNode for xpathQuery | XPath expression depends on a $@. | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| xpathFlow.py:32:29:32:38 | ControlFlowNode for xpathQuery | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | xpathFlow.py:32:29:32:38 | ControlFlowNode for xpathQuery | XPath expression depends on a $@. | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| xpathFlow.py:41:31:41:40 | ControlFlowNode for xpathQuery | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | xpathFlow.py:41:31:41:40 | ControlFlowNode for xpathQuery | XPath expression depends on a $@. | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | XPath expression depends on a $@. | xpathFlow.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | 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 5e081c1d093..424b07a0b9d 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 @@ -1,13 +1,19 @@ edges +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:7:12:7:18 | ControlFlowNode for request | +| test.py:2:26:2:32 | ControlFlowNode for ImportMember | test.py:2:26:2:32 | GSSA Variable request | +| test.py:2:26:2:32 | GSSA Variable request | test.py:0:0:0:0 | ModuleVariableNode for test.request | | test.py:7:12:7:18 | ControlFlowNode for request | test.py:7:12:7:23 | ControlFlowNode for Attribute | | test.py:7:12:7:23 | ControlFlowNode for Attribute | test.py:8:30:8:33 | ControlFlowNode for text | | test.py:7:12:7:23 | ControlFlowNode for Attribute | test.py:9:32:9:35 | ControlFlowNode for text | nodes +| test.py:0:0:0:0 | ModuleVariableNode for test.request | semmle.label | ModuleVariableNode for test.request | +| test.py:2:26:2:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test.py:2:26:2:32 | GSSA Variable request | semmle.label | GSSA Variable request | | test.py:7:12:7:18 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test.py:7:12:7:23 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:8:30:8:33 | ControlFlowNode for text | semmle.label | ControlFlowNode for text | | test.py:9:32:9:35 | ControlFlowNode for text | semmle.label | ControlFlowNode for text | subpaths #select -| test.py:8:30:8:33 | ControlFlowNode for text | test.py:7:12:7:18 | ControlFlowNode for request | test.py:8:30:8:33 | ControlFlowNode for text | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | test.py:8:21:8:23 | \\s+ | regular expression | test.py:7:12:7:18 | ControlFlowNode for request | user-provided value | -| test.py:9:32:9:35 | ControlFlowNode for text | test.py:7:12:7:18 | ControlFlowNode for request | test.py:9:32:9:35 | ControlFlowNode for text | This $@ that depends on a $@ may run slow on strings with many repetitions of '99'. | test.py:9:27:9:29 | \\d+ | regular expression | test.py:7:12:7:18 | ControlFlowNode for request | user-provided value | +| test.py:8:30:8:33 | ControlFlowNode for text | test.py:2:26:2:32 | ControlFlowNode for ImportMember | test.py:8:30:8:33 | ControlFlowNode for text | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | test.py:8:21:8:23 | \\s+ | regular expression | test.py:2:26:2:32 | ControlFlowNode for ImportMember | user-provided value | +| 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 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 | diff --git a/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected b/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected index 965df0d664f..9e87a8cbbea 100644 --- a/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected @@ -1,4 +1,9 @@ edges +| re_bad.py:0:0:0:0 | ModuleVariableNode for re_bad.request | re_bad.py:13:22:13:28 | ControlFlowNode for request | +| re_bad.py:0:0:0:0 | ModuleVariableNode for re_bad.request | re_bad.py:24:22:24:28 | ControlFlowNode for request | +| re_bad.py:0:0:0:0 | ModuleVariableNode for re_bad.request | re_bad.py:36:22:36:28 | ControlFlowNode for request | +| re_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | re_bad.py:1:19:1:25 | GSSA Variable request | +| re_bad.py:1:19:1:25 | GSSA Variable request | re_bad.py:0:0:0:0 | ModuleVariableNode for re_bad.request | | re_bad.py:13:22:13:28 | ControlFlowNode for request | re_bad.py:13:22:13:33 | ControlFlowNode for Attribute | | re_bad.py:13:22:13:33 | ControlFlowNode for Attribute | re_bad.py:13:22:13:44 | ControlFlowNode for Subscript | | re_bad.py:13:22:13:44 | ControlFlowNode for Subscript | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | @@ -9,6 +14,9 @@ edges | re_bad.py:36:22:36:33 | ControlFlowNode for Attribute | re_bad.py:36:22:36:44 | ControlFlowNode for Subscript | | re_bad.py:36:22:36:44 | ControlFlowNode for Subscript | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | nodes +| re_bad.py:0:0:0:0 | ModuleVariableNode for re_bad.request | semmle.label | ModuleVariableNode for re_bad.request | +| re_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| re_bad.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | re_bad.py:13:22:13:28 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | re_bad.py:13:22:13:33 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | re_bad.py:13:22:13:44 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | @@ -23,6 +31,6 @@ nodes | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | semmle.label | ControlFlowNode for unsafe_pattern | subpaths #select -| re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | re_bad.py:13:22:13:28 | ControlFlowNode for request | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | This regular expression depends on a $@ and is executed by $@. | re_bad.py:13:22:13:28 | ControlFlowNode for request | user-provided value | re_bad.py:14:5:14:33 | ControlFlowNode for Attribute() | re.search | -| re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | re_bad.py:24:22:24:28 | ControlFlowNode for request | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | This regular expression depends on a $@ and is executed by $@. | re_bad.py:24:22:24:28 | ControlFlowNode for request | user-provided value | re_bad.py:26:5:26:31 | ControlFlowNode for Attribute() | re.search | -| re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | re_bad.py:36:22:36:28 | ControlFlowNode for request | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | This regular expression depends on a $@ and is executed by $@. | re_bad.py:36:22:36:28 | ControlFlowNode for request | user-provided value | re_bad.py:37:5:37:41 | ControlFlowNode for Attribute() | re.search | +| re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | re_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | This regular expression depends on a $@ and is executed by $@. | re_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | re_bad.py:14:5:14:33 | ControlFlowNode for Attribute() | re.search | +| re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | re_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | This regular expression depends on a $@ and is executed by $@. | re_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | re_bad.py:26:5:26:31 | ControlFlowNode for Attribute() | re.search | +| re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | re_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | This regular expression depends on a $@ and is executed by $@. | re_bad.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | re_bad.py:37:5:37:41 | ControlFlowNode for Attribute() | re.search | diff --git a/python/ql/test/query-tests/Security/CWE-776-XmlBomb/XmlBomb.expected b/python/ql/test/query-tests/Security/CWE-776-XmlBomb/XmlBomb.expected index 492120581fd..44913020a05 100644 --- a/python/ql/test/query-tests/Security/CWE-776-XmlBomb/XmlBomb.expected +++ b/python/ql/test/query-tests/Security/CWE-776-XmlBomb/XmlBomb.expected @@ -1,12 +1,18 @@ edges +| test.py:0:0:0:0 | ModuleVariableNode for test.request | test.py:19:19:19:25 | ControlFlowNode for request | +| test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:1:26:1:32 | GSSA Variable request | +| test.py:1:26:1:32 | GSSA Variable request | test.py:0:0:0:0 | ModuleVariableNode for test.request | | test.py:19:19:19:25 | ControlFlowNode for request | test.py:19:19:19:30 | ControlFlowNode for Attribute | | test.py:19:19:19:30 | ControlFlowNode for Attribute | test.py:19:19:19:45 | ControlFlowNode for Subscript | | test.py:19:19:19:45 | ControlFlowNode for Subscript | test.py:30:34:30:44 | ControlFlowNode for xml_content | nodes +| test.py:0:0:0:0 | ModuleVariableNode for test.request | semmle.label | ModuleVariableNode for test.request | +| test.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | test.py:19:19:19:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test.py:19:19:19:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | test.py:19:19:19:45 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | test.py:30:34:30:44 | ControlFlowNode for xml_content | semmle.label | ControlFlowNode for xml_content | subpaths #select -| test.py:30:34:30:44 | ControlFlowNode for xml_content | test.py:19:19:19:25 | ControlFlowNode for request | test.py:30:34:30:44 | ControlFlowNode for xml_content | XML parsing depends on a $@ without guarding against uncontrolled entity expansion. | test.py:19:19:19:25 | ControlFlowNode for request | user-provided value | +| test.py:30:34:30:44 | ControlFlowNode for xml_content | test.py:1:26:1:32 | ControlFlowNode for ImportMember | test.py:30:34:30:44 | ControlFlowNode for xml_content | XML parsing depends on a $@ without guarding against uncontrolled entity expansion. | test.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected index 6a08b56d7c4..d8ea245581a 100644 --- a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected +++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected @@ -1,4 +1,26 @@ edges +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:8:17:8:23 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:38:17:38:23 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:58:17:58:23 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:72:17:72:23 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:86:18:86:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:92:18:92:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:98:18:98:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:104:18:104:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:110:18:110:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:1:19:1:25 | GSSA Variable request | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:1:19:1:25 | GSSA Variable request | +| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | +| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute | @@ -79,6 +101,15 @@ edges | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute | | full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute | full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript | | full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:9:19:9:25 | ControlFlowNode for request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:9:19:9:25 | ControlFlowNode for request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:10:19:10:25 | ControlFlowNode for request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:10:19:10:25 | ControlFlowNode for request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:11:18:11:24 | ControlFlowNode for request | +| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:1:26:1:32 | GSSA Variable request | +| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:1:26:1:32 | GSSA Variable request | +| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | +| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | @@ -107,6 +138,12 @@ edges | test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute | test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | | test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | test_http_client.py:33:25:33:28 | ControlFlowNode for path | | test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | test_http_client.py:37:25:37:28 | ControlFlowNode for path | +| test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | test_requests.py:6:18:6:24 | ControlFlowNode for request | +| test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | test_requests.py:6:18:6:24 | ControlFlowNode for request | +| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:1:19:1:25 | GSSA Variable request | +| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:1:19:1:25 | GSSA Variable request | +| test_requests.py:1:19:1:25 | GSSA Variable request | test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | +| test_requests.py:1:19:1:25 | GSSA Variable request | test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | | test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | | test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | @@ -114,6 +151,12 @@ edges | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | nodes +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | semmle.label | ModuleVariableNode for full_partial_test.request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | semmle.label | ModuleVariableNode for full_partial_test.request | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| full_partial_test.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | +| full_partial_test.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -204,6 +247,12 @@ nodes | full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | semmle.label | ModuleVariableNode for test_http_client.request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | semmle.label | ModuleVariableNode for test_http_client.request | +| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_http_client.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | +| test_http_client.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -233,6 +282,12 @@ nodes | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | | test_http_client.py:33:25:33:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | | test_http_client.py:37:25:37:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | +| test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | semmle.label | ModuleVariableNode for test_requests.request | +| test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | semmle.label | ModuleVariableNode for test_requests.request | +| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_requests.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | +| test_requests.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -243,24 +298,22 @@ nodes | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | subpaths #select -| full_partial_test.py:10:5:10:28 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | The full URL of this request depends on a $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:13:5:13:21 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:13:18:13:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:19:5:19:21 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:19:18:19:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:23:5:23:21 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:23:18:23:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:42:5:42:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:42:18:42:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:45:5:45:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:45:18:45:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:48:5:48:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:48:18:48:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:51:5:51:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:51:18:51:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:54:5:54:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:54:18:54:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:62:5:62:21 | ControlFlowNode for Attribute() | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:62:18:62:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:65:5:65:21 | ControlFlowNode for Attribute() | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:65:18:65:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:76:5:76:21 | ControlFlowNode for Attribute() | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:76:18:76:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:79:5:79:21 | ControlFlowNode for Attribute() | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:79:18:79:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:82:5:82:21 | ControlFlowNode for Attribute() | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:82:18:82:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | user-provided value | -| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | -| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | -| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on a $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | user-provided value | -| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | -| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | -| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on a $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | user-provided value | -| test_requests.py:8:5:8:28 | ControlFlowNode for Attribute() | test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | The full URL of this request depends on a $@. | test_requests.py:6:18:6:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:10:5:10:28 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:13:5:13:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:13:18:13:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:19:5:19:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:19:18:19:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:23:5:23:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:23:18:23:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:42:5:42:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:42:18:42:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:45:5:45:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:45:18:45:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:48:5:48:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:48:18:48:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:51:5:51:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:51:18:51:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:54:5:54:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:54:18:54:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:62:5:62:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:62:18:62:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:65:5:65:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:65:18:65:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:76:5:76:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:76:18:76:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:79:5:79:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:79:18:79:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:82:5:82:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:82:18:82:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| test_requests.py:8:5:8:28 | ControlFlowNode for Attribute() | test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | The full URL of this request depends on a $@. | test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected index bfca61c3a3a..5bc17ef2572 100644 --- a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected +++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected @@ -1,4 +1,26 @@ edges +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:8:17:8:23 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:38:17:38:23 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:58:17:58:23 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:72:17:72:23 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:86:18:86:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:92:18:92:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:98:18:98:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:104:18:104:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:110:18:110:24 | ControlFlowNode for request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:1:19:1:25 | GSSA Variable request | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:1:19:1:25 | GSSA Variable request | +| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | +| full_partial_test.py:1:19:1:25 | GSSA Variable request | full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:8:17:8:28 | ControlFlowNode for Attribute | @@ -79,6 +101,15 @@ edges | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute | | full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute | full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript | | full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:9:19:9:25 | ControlFlowNode for request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:9:19:9:25 | ControlFlowNode for request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:10:19:10:25 | ControlFlowNode for request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:10:19:10:25 | ControlFlowNode for request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | test_http_client.py:11:18:11:24 | ControlFlowNode for request | +| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:1:26:1:32 | GSSA Variable request | +| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:1:26:1:32 | GSSA Variable request | +| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | +| test_http_client.py:1:26:1:32 | GSSA Variable request | test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:10:19:10:30 | ControlFlowNode for Attribute | @@ -107,6 +138,12 @@ edges | test_http_client.py:11:18:11:29 | ControlFlowNode for Attribute | test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | | test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | test_http_client.py:33:25:33:28 | ControlFlowNode for path | | test_http_client.py:11:18:11:48 | ControlFlowNode for Subscript | test_http_client.py:37:25:37:28 | ControlFlowNode for path | +| test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | test_requests.py:6:18:6:24 | ControlFlowNode for request | +| test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | test_requests.py:6:18:6:24 | ControlFlowNode for request | +| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:1:19:1:25 | GSSA Variable request | +| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | test_requests.py:1:19:1:25 | GSSA Variable request | +| test_requests.py:1:19:1:25 | GSSA Variable request | test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | +| test_requests.py:1:19:1:25 | GSSA Variable request | test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | | test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | | test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | @@ -114,6 +151,12 @@ edges | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | | test_requests.py:6:18:6:48 | ControlFlowNode for Subscript | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | nodes +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | semmle.label | ModuleVariableNode for full_partial_test.request | +| full_partial_test.py:0:0:0:0 | ModuleVariableNode for full_partial_test.request | semmle.label | ModuleVariableNode for full_partial_test.request | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| full_partial_test.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | +| full_partial_test.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | full_partial_test.py:7:18:7:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -204,6 +247,12 @@ nodes | full_partial_test.py:119:18:119:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | | full_partial_test.py:119:18:119:48 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | semmle.label | ControlFlowNode for url | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | semmle.label | ModuleVariableNode for test_http_client.request | +| test_http_client.py:0:0:0:0 | ModuleVariableNode for test_http_client.request | semmle.label | ModuleVariableNode for test_http_client.request | +| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_http_client.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | +| test_http_client.py:1:26:1:32 | GSSA Variable request | semmle.label | GSSA Variable request | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_http_client.py:9:19:9:25 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_http_client.py:9:19:9:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -233,6 +282,12 @@ nodes | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | semmle.label | ControlFlowNode for unsafe_path | | test_http_client.py:33:25:33:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | | test_http_client.py:37:25:37:28 | ControlFlowNode for path | semmle.label | ControlFlowNode for path | +| test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | semmle.label | ModuleVariableNode for test_requests.request | +| test_requests.py:0:0:0:0 | ModuleVariableNode for test_requests.request | semmle.label | ModuleVariableNode for test_requests.request | +| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_requests.py:1:19:1:25 | ControlFlowNode for ImportMember | semmle.label | ControlFlowNode for ImportMember | +| test_requests.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | +| test_requests.py:1:19:1:25 | GSSA Variable request | semmle.label | GSSA Variable request | | test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_requests.py:6:18:6:24 | ControlFlowNode for request | semmle.label | ControlFlowNode for request | | test_requests.py:6:18:6:29 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | @@ -243,21 +298,15 @@ nodes | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | subpaths #select -| full_partial_test.py:68:5:68:21 | ControlFlowNode for Attribute() | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:68:18:68:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:68:5:68:21 | ControlFlowNode for Attribute() | full_partial_test.py:58:17:58:23 | ControlFlowNode for request | full_partial_test.py:68:18:68:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:58:17:58:23 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:89:5:89:21 | ControlFlowNode for Attribute() | full_partial_test.py:86:18:86:24 | ControlFlowNode for request | full_partial_test.py:89:18:89:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:86:18:86:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:95:5:95:21 | ControlFlowNode for Attribute() | full_partial_test.py:92:18:92:24 | ControlFlowNode for request | full_partial_test.py:95:18:95:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:92:18:92:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:101:5:101:21 | ControlFlowNode for Attribute() | full_partial_test.py:98:18:98:24 | ControlFlowNode for request | full_partial_test.py:101:18:101:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:98:18:98:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:107:5:107:21 | ControlFlowNode for Attribute() | full_partial_test.py:104:18:104:24 | ControlFlowNode for request | full_partial_test.py:107:18:107:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:104:18:104:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:116:5:116:21 | ControlFlowNode for Attribute() | full_partial_test.py:110:18:110:24 | ControlFlowNode for request | full_partial_test.py:116:18:116:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:110:18:110:24 | ControlFlowNode for request | user-provided value | -| full_partial_test.py:122:5:122:21 | ControlFlowNode for Attribute() | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | user-provided value | -| test_http_client.py:22:5:22:31 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | -| test_http_client.py:26:5:26:31 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | -| test_http_client.py:29:5:29:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | Part of the URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | -| test_http_client.py:29:5:29:36 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | Part of the URL of this request depends on a $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | user-provided value | -| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | -| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | user-provided value | -| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:11:18:11:24 | ControlFlowNode for request | user-provided value | -| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | -| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | user-provided value | -| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:11:18:11:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:68:5:68:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:68:18:68:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:89:5:89:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:89:18:89:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:95:5:95:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:95:18:95:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:101:5:101:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:101:18:101:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:107:5:107:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:107:18:107:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:116:5:116:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:116:18:116:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| full_partial_test.py:122:5:122:21 | ControlFlowNode for Attribute() | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:1:19:1:25 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:22:5:22:31 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:26:5:26:31 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:29:5:29:36 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | Part of the URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | +| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:1:26:1:32 | ControlFlowNode for ImportMember | user-provided value | diff --git a/ruby/ql/lib/CHANGELOG.md b/ruby/ql/lib/CHANGELOG.md index 1a96d857e7f..677403b9a16 100644 --- a/ruby/ql/lib/CHANGELOG.md +++ b/ruby/ql/lib/CHANGELOG.md @@ -1,3 +1,26 @@ +## 0.4.1 + +### Minor Analysis Improvements + +* The following classes have been moved from `codeql.ruby.frameworks.ActionController` to `codeql.ruby.frameworks.Rails`: + * `ParamsCall`, now accessed as `Rails::ParamsCall`. + * `CookieCall`, now accessed as `Rails::CookieCall`. +* The following classes have been moved from `codeql.ruby.frameworks.ActionView` to `codeql.ruby.frameworks.Rails`: + * `HtmlSafeCall`, now accessed as `Rails::HtmlSafeCall`. + * `HtmlEscapeCall`, now accessed as `Rails::HtmlEscapeCall`. + * `RenderCall`, now accessed as `Rails::RenderCall`. + * `RenderToCall`, now accessed as `Rails::RenderToCall`. +* Subclasses of `ActionController::Metal` are now recognised as controllers. +* `ActionController::DataStreaming::send_file` is now recognized as a + `FileSystemAccess`. +* Various XSS sinks in the ActionView library are now recognized. +* Calls to `ActiveRecord::Base.create` are now recognized as model + instantiations. +* Various code executions, command executions and HTTP requests in the + ActiveStorage library are now recognized. +* `MethodBase` now has two new predicates related to visibility: `isPublic` and + `isProtected`. These hold, respectively, if the method is public or protected. + ## 0.4.0 ### Breaking Changes diff --git a/ruby/ql/lib/change-notes/2022-08-16-protected-methods.md b/ruby/ql/lib/change-notes/2022-08-16-protected-methods.md deleted file mode 100644 index 7647517c06c..00000000000 --- a/ruby/ql/lib/change-notes/2022-08-16-protected-methods.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -category: minorAnalysis ---- -* `MethodBase` now has two new predicates related to visibility: `isPublic` and - `isProtected`. These hold, respectively, if the method is public or protected. diff --git a/ruby/ql/lib/change-notes/2022-08-30-activestorage.md b/ruby/ql/lib/change-notes/2022-08-30-activestorage.md deleted file mode 100644 index b5ab9e34479..00000000000 --- a/ruby/ql/lib/change-notes/2022-08-30-activestorage.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -category: minorAnalysis ---- -* Various code executions, command executions and HTTP requests in the - ActiveStorage library are now recognized. - diff --git a/ruby/ql/lib/change-notes/2022-09-27-actioncontroller-parameters.md b/ruby/ql/lib/change-notes/2022-09-27-actioncontroller-parameters.md new file mode 100644 index 00000000000..e0c2597ec90 --- /dev/null +++ b/ruby/ql/lib/change-notes/2022-09-27-actioncontroller-parameters.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Taint flow through `ActionController::Parameters` is tracked more accurately. diff --git a/ruby/ql/lib/change-notes/2022-09-27-actionview.md b/ruby/ql/lib/change-notes/2022-09-27-actionview.md deleted file mode 100644 index d8f392971ad..00000000000 --- a/ruby/ql/lib/change-notes/2022-09-27-actionview.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* Various XSS sinks in the ActionView library are now recognized. diff --git a/ruby/ql/lib/change-notes/2022-09-27-activerecord-create.md b/ruby/ql/lib/change-notes/2022-09-27-activerecord-create.md deleted file mode 100644 index b16da83f611..00000000000 --- a/ruby/ql/lib/change-notes/2022-09-27-activerecord-create.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -category: minorAnalysis ---- -* Calls to `ActiveRecord::Base.create` are now recognized as model - instantiations. diff --git a/ruby/ql/lib/change-notes/2022-09-28-actioncontroller-metal.md b/ruby/ql/lib/change-notes/2022-09-28-actioncontroller-metal.md deleted file mode 100644 index 4d4e2fef174..00000000000 --- a/ruby/ql/lib/change-notes/2022-09-28-actioncontroller-metal.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* Subclasses of `ActionController::Metal` are now recognised as controllers. diff --git a/ruby/ql/lib/change-notes/2022-09-28-actioncontroller-sendfile.md b/ruby/ql/lib/change-notes/2022-09-28-actioncontroller-sendfile.md deleted file mode 100644 index 93bf546f4a5..00000000000 --- a/ruby/ql/lib/change-notes/2022-09-28-actioncontroller-sendfile.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -category: minorAnalysis ---- -* `ActionController::DataStreaming::send_file` is now recognized as a - `FileSystemAccess`. - diff --git a/ruby/ql/lib/change-notes/2022-10-04-actionview-controller-renames.md b/ruby/ql/lib/change-notes/2022-10-04-actionview-controller-renames.md deleted file mode 100644 index f269442dcf4..00000000000 --- a/ruby/ql/lib/change-notes/2022-10-04-actionview-controller-renames.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -category: minorAnalysis ---- -* The following classes have been moved from `codeql.ruby.frameworks.ActionController` to `codeql.ruby.frameworks.Rails`: - * `ParamsCall`, now accessed as `Rails::ParamsCall`. - * `CookieCall`, now accessed as `Rails::CookieCall`. -* The following classes have been moved from `codeql.ruby.frameworks.ActionView` to `codeql.ruby.frameworks.Rails`: - * `HtmlSafeCall`, now accessed as `Rails::HtmlSafeCall`. - * `HtmlEscapeCall`, now accessed as `Rails::HtmlEscapeCall`. - * `RenderCall`, now accessed as `Rails::RenderCall`. - * `RenderToCall`, now accessed as `Rails::RenderToCall`. diff --git a/ruby/ql/lib/change-notes/released/0.4.1.md b/ruby/ql/lib/change-notes/released/0.4.1.md new file mode 100644 index 00000000000..9c492f4ac7e --- /dev/null +++ b/ruby/ql/lib/change-notes/released/0.4.1.md @@ -0,0 +1,22 @@ +## 0.4.1 + +### Minor Analysis Improvements + +* The following classes have been moved from `codeql.ruby.frameworks.ActionController` to `codeql.ruby.frameworks.Rails`: + * `ParamsCall`, now accessed as `Rails::ParamsCall`. + * `CookieCall`, now accessed as `Rails::CookieCall`. +* The following classes have been moved from `codeql.ruby.frameworks.ActionView` to `codeql.ruby.frameworks.Rails`: + * `HtmlSafeCall`, now accessed as `Rails::HtmlSafeCall`. + * `HtmlEscapeCall`, now accessed as `Rails::HtmlEscapeCall`. + * `RenderCall`, now accessed as `Rails::RenderCall`. + * `RenderToCall`, now accessed as `Rails::RenderToCall`. +* Subclasses of `ActionController::Metal` are now recognised as controllers. +* `ActionController::DataStreaming::send_file` is now recognized as a + `FileSystemAccess`. +* Various XSS sinks in the ActionView library are now recognized. +* Calls to `ActiveRecord::Base.create` are now recognized as model + instantiations. +* Various code executions, command executions and HTTP requests in the + ActiveStorage library are now recognized. +* `MethodBase` now has two new predicates related to visibility: `isPublic` and + `isProtected`. These hold, respectively, if the method is public or protected. diff --git a/ruby/ql/lib/codeql-pack.release.yml b/ruby/ql/lib/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/ruby/ql/lib/codeql-pack.release.yml +++ b/ruby/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll index 9a9626cf74f..67b53baa51c 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll @@ -486,12 +486,15 @@ private import ResolveImpl * methods evaluate the block in the context of some other module/class instead of * the enclosing one. */ -private ModuleBase enclosingModule(AstNode node) { result = parent*(node).getParent() } - -private AstNode parent(AstNode n) { - result = n.getParent() and - not result instanceof ModuleBase and - not result instanceof Block +private ModuleBase enclosingModule(AstNode node) { + result = node.getParent() + or + exists(AstNode mid | + result = enclosingModule(mid) and + mid = node.getParent() and + not mid instanceof ModuleBase and + not mid instanceof Block + ) } private Module getAncestors(Module m) { diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll index 6eaafee71af..1ab4435a85a 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll @@ -118,7 +118,11 @@ class Synthesis extends TSynthesis { private class Desugared extends AstNode { Desugared() { this = any(AstNode sugar).getDesugared() } - AstNode getADescendant() { result = this.getAChild*() } + AstNode getADescendant() { + result = this + or + result = this.getADescendant().getAChild() + } } /** @@ -132,7 +136,10 @@ int desugarLevel(AstNode n) { result = count(Desugared desugared | n = desugared * Holds if `n` appears in a context that is desugared. That is, a * transitive, reflexive parent of `n` is a desugared node. */ -predicate isInDesugaredContext(AstNode n) { n = any(AstNode sugar).getDesugared().getAChild*() } +predicate isInDesugaredContext(AstNode n) { + n = any(AstNode sugar).getDesugared() or + n = any(AstNode mid | isInDesugaredContext(mid)).getAChild() +} /** * Holds if `n` is a node that only exists as a result of desugaring some diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll index 7615357453d..fe4cca24d69 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll @@ -71,18 +71,22 @@ private predicate completionIsValidForStmt(AstNode n, Completion c) { c = TReturnCompletion() } +private AstNode getARescuableBodyChild() { + exists(Trees::BodyStmtTree bst | result = bst.getBodyChild(_, true) | + exists(bst.getARescue()) + or + exists(bst.getEnsure()) + ) + or + result = getARescuableBodyChild().getAChild() +} + /** * Holds if `c` happens in an exception-aware context, that is, it may be * `rescue`d or `ensure`d. In such cases, we assume that the target of `c` * may raise an exception (in addition to evaluating normally). */ -private predicate mayRaise(Call c) { - exists(Trees::BodyStmtTree bst | c = bst.getBodyChild(_, true).getAChild*() | - exists(bst.getARescue()) - or - exists(bst.getEnsure()) - ) -} +private predicate mayRaise(Call c) { c = getARescuableBodyChild() } /** A completion of a statement or an expression. */ abstract class Completion extends TCompletion { diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll index b7e9b14a910..f988ea43779 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowDispatch.qll @@ -389,7 +389,7 @@ private module Cached { // ``` exists(DataFlow::Node sourceNode, Module m | flowsToMethodCall(call, sourceNode, method) and - singletonMethodOnModule(result, method, m) + result = lookupSingletonMethod(m, method) | // ```rb // def C.singleton; end # <- result @@ -725,7 +725,10 @@ private predicate singletonMethodOnModule(MethodBase method, string name, Module selfInModule(object.(SelfVariableReadAccess).getVariable(), m) ) or - flowsToSingletonMethodObject(trackModuleAccess(m), method, name) + exists(DataFlow::LocalSourceNode sourceNode | + m = resolveConstantReadAccess(sourceNode.asExpr().getExpr()) and + flowsToSingletonMethodObject(sourceNode, method, name) + ) or exists(Module other | extendCallModule(m, other) and @@ -733,6 +736,26 @@ private predicate singletonMethodOnModule(MethodBase method, string name, Module ) } +/** + * Holds if `method` is a singleton method named `name`, defined on module + * `m`, or any transitive base class of `m`. + */ +pragma[nomagic] +private MethodBase lookupSingletonMethod(Module m, string name) { + singletonMethodOnModule(result, name, m) + or + // cannot be part of `singletonMethodOnModule` because it would introduce + // negative recursion below + exists(DataFlow::LocalSourceNode sourceNode | + sourceNode = trackModuleAccess(m) and + not m = resolveConstantReadAccess(sourceNode.asExpr().getExpr()) and + flowsToSingletonMethodObject(sourceNode, result, name) + ) + or + not singletonMethodOnModule(_, name, m) and + result = lookupSingletonMethod(m.getSuperClass(), name) +} + /** * Holds if `method` is a singleton method named `name`, defined on expression * `object`, where `object` is not likely to resolve to a module: diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration. diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll index c4562d4dfd2..8556c167b5d 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll @@ -382,3 +382,123 @@ private class SendFile extends FileSystemAccess::Range, DataFlow::CallNode { override DataFlow::Node getAPathArgument() { result = this.getArgument(0) } } + +private module ParamsSummaries { + private import codeql.ruby.dataflow.FlowSummary + + /** + * An instance of `ActionController::Parameters`, including those returned + * from method calls on other instances. + */ + private class ParamsInstance extends DataFlow::Node { + ParamsInstance() { + this.asExpr().getExpr() instanceof Rails::ParamsCall + or + this = + any(DataFlow::CallNode call | + call.getReceiver() instanceof ParamsInstance and + call.getMethodName() = paramsMethodReturningParamsInstance() + ) + or + exists(ParamsInstance prev | prev.(DataFlow::LocalSourceNode).flowsTo(this)) + } + } + + /** + * Methods on `ActionController::Parameters` that return an instance of + * `ActionController::Parameters`. + */ + string paramsMethodReturningParamsInstance() { + result = + [ + "concat", "concat!", "compact_blank", "deep_dup", "deep_transform_keys", "delete_if", + // dig doesn't always return a Parameters instance, but it will if the + // given key refers to a nested hash parameter. + "dig", "each", "each_key", "each_pair", "each_value", "except", "keep_if", "merge", + "merge!", "permit", "reject", "reject!", "reverse_merge", "reverse_merge!", "select", + "select!", "slice", "slice!", "transform_keys", "transform_keys!", "transform_values", + "transform_values!", "with_defaults", "with_defaults!" + ] + } + + /** + * Methods on `ActionController::Parameters` that propagate taint from + * receiver to return value. + */ + string methodReturnsTaintFromSelf() { + result = + [ + "as_json", "permit", "require", "required", "deep_dup", "deep_transform_keys", + "deep_transform_keys!", "delete_if", "extract!", "keep_if", "select", "select!", "reject", + "reject!", "to_h", "to_hash", "to_query", "to_param", "to_unsafe_h", "to_unsafe_hash", + "transform_keys", "transform_keys!", "transform_values", "transform_values!", "values_at" + ] + } + + /** + * A flow summary for methods on `ActionController::Parameters` which + * propagate taint from receiver to return value. + */ + private class MethodsReturningParamsInstanceSummary extends SummarizedCallable { + MethodsReturningParamsInstanceSummary() { this = "ActionController::Parameters#" } + + override MethodCall getACall() { + any(ParamsInstance i).asExpr().getExpr() = result.getReceiver() and + result.getMethodName() = methodReturnsTaintFromSelf() + } + + override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { + input = "Argument[self]" and + output = "ReturnValue" and + preservesValue = false + } + } + + /** + * `#merge` + * Returns a new ActionController::Parameters with all keys from other_hash merged into current hash. + * `#reverse_merge` + * `#with_defaults` + * Returns a new ActionController::Parameters with all keys from current hash merged into other_hash. + */ + private class MergeSummary extends SummarizedCallable { + MergeSummary() { this = "ActionController::Parameters#merge" } + + override MethodCall getACall() { + result.getMethodName() = ["merge", "reverse_merge", "with_defaults"] and + exists(ParamsInstance i | + i.asExpr().getExpr() = [result.getReceiver(), result.getArgument(0)] + ) + } + + override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { + input = ["Argument[self]", "Argument[0]"] and + output = "ReturnValue" and + preservesValue = false + } + } + + /** + * `#merge!` + * Returns current ActionController::Parameters instance with current hash merged into other_hash. + * `#reverse_merge!` + * `#with_defaults!` + * Returns a new ActionController::Parameters with all keys from current hash merged into other_hash. + */ + private class MergeBangSummary extends SummarizedCallable { + MergeBangSummary() { this = "ActionController::Parameters#merge!" } + + override MethodCall getACall() { + result.getMethodName() = ["merge!", "reverse_merge!", "with_defaults!"] and + exists(ParamsInstance i | + i.asExpr().getExpr() = [result.getReceiver(), result.getArgument(0)] + ) + } + + override predicate propagatesFlowExt(string input, string output, boolean preservesValue) { + input = ["Argument[self]", "Argument[0]"] and + output = ["ReturnValue", "Argument[self]"] and + preservesValue = false + } + } +} diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Excon.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Excon.qll index 4468f8ffa58..37b3cdbd576 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Excon.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Excon.qll @@ -70,6 +70,7 @@ class ExconHttpRequest extends Http::Client::Request::Range, DataFlow::CallNode ) } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Faraday.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Faraday.qll index ae4bb25c265..139a484f87a 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Faraday.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Faraday.qll @@ -71,6 +71,7 @@ class FaradayHttpRequest extends Http::Client::Request::Range, DataFlow::CallNod ) } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/HttpClient.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/HttpClient.qll index 0d8e6cfa0fc..51537e25148 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/HttpClient.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/HttpClient.qll @@ -61,6 +61,7 @@ class HttpClientRequest extends Http::Client::Request::Range, DataFlow::CallNode .getArgument(0) } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll index 08ab0f94141..e0b5de43351 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll @@ -53,6 +53,7 @@ class HttpartyRequest extends Http::Client::Request::Range, DataFlow::CallNode { result = this.getKeywordArgumentIncludeHashArgument(["verify", "verify_peer"]) } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll index f12f6fa8e30..d6dbd581f86 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll @@ -80,6 +80,7 @@ class NetHttpRequest extends Http::Client::Request::Range, DataFlow::CallNode { ) } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/OpenURI.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/OpenURI.qll index f11a4b2908f..68ca62beaf8 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/OpenURI.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/OpenURI.qll @@ -42,6 +42,7 @@ class OpenUriRequest extends Http::Client::Request::Range, DataFlow::CallNode { result = this.getKeywordArgumentIncludeHashArgument("ssl_verify_mode") } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { @@ -91,6 +92,7 @@ class OpenUriKernelOpenRequest extends Http::Client::Request::Range, DataFlow::C ) } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/RestClient.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/RestClient.qll index 4b9ddfaab41..7df9875b00c 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/RestClient.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/RestClient.qll @@ -54,6 +54,7 @@ class RestClientHttpRequest extends Http::Client::Request::Range, DataFlow::Call ) } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Typhoeus.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Typhoeus.qll index 163560e61f9..e41add437d3 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Typhoeus.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Typhoeus.qll @@ -34,6 +34,7 @@ class TyphoeusHttpRequest extends Http::Client::Request::Range, DataFlow::CallNo result = this.getKeywordArgumentIncludeHashArgument("ssl_verifypeer") } + cached override predicate disablesCertificateValidation( DataFlow::Node disablingNode, DataFlow::Node argumentOrigin ) { diff --git a/ruby/ql/lib/codeql/ruby/frameworks/stdlib/Pathname.qll b/ruby/ql/lib/codeql/ruby/frameworks/stdlib/Pathname.qll index 0939e6c17c8..85db78252c8 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/stdlib/Pathname.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/stdlib/Pathname.qll @@ -27,6 +27,7 @@ module Pathname { * Every `PathnameInstance` is considered to be a `FileNameSource`. */ class PathnameInstance extends FileNameSource { + cached PathnameInstance() { any(PathnameConfiguration c).hasFlowTo(this) } } diff --git a/ruby/ql/lib/qlpack.yml b/ruby/ql/lib/qlpack.yml index 97c480b8f6e..1ed112d89d4 100644 --- a/ruby/ql/lib/qlpack.yml +++ b/ruby/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-all -version: 0.4.1-dev +version: 0.4.2-dev groups: ruby extractor: ruby dbscheme: ruby.dbscheme diff --git a/ruby/ql/src/CHANGELOG.md b/ruby/ql/src/CHANGELOG.md index e45d4e8c250..6792b3e61c0 100644 --- a/ruby/ql/src/CHANGELOG.md +++ b/ruby/ql/src/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.4.1 + +### Minor Analysis Improvements + +* The `rb/xxe` query has been updated to add the following sinks for XML external entity expansion: + 1. Calls to parse XML using `LibXML` when its `default_substitute_entities` option is enabled. + 2. Uses of the Rails methods `ActiveSupport::XmlMini.parse`, `Hash.from_xml`, and `Hash.from_trusted_xml` when `ActiveSupport::XmlMini` is configured to use `LibXML` as its backend, and its `default_substitute_entities` option is enabled. + ## 0.4.0 ### New Queries diff --git a/ruby/ql/src/change-notes/2022-09-27-libxml-xxe.md b/ruby/ql/src/change-notes/released/0.4.1.md similarity index 80% rename from ruby/ql/src/change-notes/2022-09-27-libxml-xxe.md rename to ruby/ql/src/change-notes/released/0.4.1.md index a3084c62f2a..a3ee4612257 100644 --- a/ruby/ql/src/change-notes/2022-09-27-libxml-xxe.md +++ b/ruby/ql/src/change-notes/released/0.4.1.md @@ -1,6 +1,7 @@ ---- -category: minorAnalysis ---- +## 0.4.1 + +### Minor Analysis Improvements + * The `rb/xxe` query has been updated to add the following sinks for XML external entity expansion: 1. Calls to parse XML using `LibXML` when its `default_substitute_entities` option is enabled. - 2. Uses of the Rails methods `ActiveSupport::XmlMini.parse`, `Hash.from_xml`, and `Hash.from_trusted_xml` when `ActiveSupport::XmlMini` is configured to use `LibXML` as its backend, and its `default_substitute_entities` option is enabled. \ No newline at end of file + 2. Uses of the Rails methods `ActiveSupport::XmlMini.parse`, `Hash.from_xml`, and `Hash.from_trusted_xml` when `ActiveSupport::XmlMini` is configured to use `LibXML` as its backend, and its `default_substitute_entities` option is enabled. diff --git a/ruby/ql/src/codeql-pack.release.yml b/ruby/ql/src/codeql-pack.release.yml index 458bfbeccff..89fa3a87180 100644 --- a/ruby/ql/src/codeql-pack.release.yml +++ b/ruby/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.0 +lastReleaseVersion: 0.4.1 diff --git a/ruby/ql/src/qlpack.yml b/ruby/ql/src/qlpack.yml index 66f006ac2d5..43e9df97f13 100644 --- a/ruby/ql/src/qlpack.yml +++ b/ruby/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-queries -version: 0.4.1-dev +version: 0.4.2-dev groups: - ruby - queries diff --git a/ruby/ql/src/queries/meta/TaintedNodes.ql b/ruby/ql/src/queries/meta/TaintedNodes.ql new file mode 100644 index 00000000000..18997cfaaee --- /dev/null +++ b/ruby/ql/src/queries/meta/TaintedNodes.ql @@ -0,0 +1,28 @@ +/** + * @name Tainted nodes + * @description Nodes reachable from a remote flow source via default taint-tracking steps. + * @kind problem + * @problem.severity recommendation + * @id rb/meta/tainted-nodes + * @tags meta + * @precision very-low + */ + +import internal.TaintMetrics +import codeql.ruby.DataFlow +import codeql.ruby.TaintTracking + +class BasicTaintConfiguration extends TaintTracking::Configuration { + BasicTaintConfiguration() { this = "BasicTaintConfiguration" } + + override predicate isSource(DataFlow::Node node) { node = relevantTaintSource(_) } + + override predicate isSink(DataFlow::Node node) { + // To reduce noise from synthetic nodes, only count nodes that have an associated expression. + exists(node.asExpr().getExpr()) + } +} + +from DataFlow::Node node +where any(BasicTaintConfiguration cfg).hasFlow(_, node) +select node, "Tainted node" diff --git a/ruby/ql/src/queries/meta/internal/TaintMetrics.qll b/ruby/ql/src/queries/meta/internal/TaintMetrics.qll index 19e25f3a94b..19d26103cb9 100644 --- a/ruby/ql/src/queries/meta/internal/TaintMetrics.qll +++ b/ruby/ql/src/queries/meta/internal/TaintMetrics.qll @@ -36,3 +36,10 @@ DataFlow::Node relevantTaintSink(string kind) { kind = "UrlRedirect" and result instanceof UrlRedirect::Sink ) } + +/** + * Gets the root folder of the snapshot. + * + * This is selected as the location for project-wide metrics. + */ +Folder projectRoot() { result.getRelativePath() = "" } diff --git a/ruby/ql/test/library-tests/frameworks/ActionController.expected b/ruby/ql/test/library-tests/frameworks/ActionController.expected index f91583f29af..f5a5f703abf 100644 --- a/ruby/ql/test/library-tests/frameworks/ActionController.expected +++ b/ruby/ql/test/library-tests/frameworks/ActionController.expected @@ -1,4 +1,5 @@ actionControllerControllerClasses +| action_controller/params_flow.rb:1:1:151:3 | MyController | | active_record/ActiveRecord.rb:23:1:39:3 | FooController | | active_record/ActiveRecord.rb:41:1:64:3 | BarController | | active_record/ActiveRecord.rb:66:1:98:3 | BazController | @@ -11,6 +12,39 @@ actionControllerControllerClasses | app/controllers/tags_controller.rb:1:1:2:3 | TagsController | | app/controllers/users/notifications_controller.rb:2:3:5:5 | NotificationsController | actionControllerActionMethods +| action_controller/params_flow.rb:2:3:4:5 | m1 | +| action_controller/params_flow.rb:6:3:8:5 | m2 | +| action_controller/params_flow.rb:10:3:12:5 | m2 | +| action_controller/params_flow.rb:14:3:16:5 | m3 | +| action_controller/params_flow.rb:18:3:20:5 | m4 | +| action_controller/params_flow.rb:22:3:24:5 | m5 | +| action_controller/params_flow.rb:26:3:28:5 | m6 | +| action_controller/params_flow.rb:30:3:32:5 | m7 | +| action_controller/params_flow.rb:34:3:36:5 | m8 | +| action_controller/params_flow.rb:38:3:40:5 | m9 | +| action_controller/params_flow.rb:42:3:44:5 | m10 | +| action_controller/params_flow.rb:46:3:48:5 | m11 | +| action_controller/params_flow.rb:50:3:52:5 | m12 | +| action_controller/params_flow.rb:54:3:56:5 | m13 | +| action_controller/params_flow.rb:58:3:60:5 | m14 | +| action_controller/params_flow.rb:62:3:64:5 | m15 | +| action_controller/params_flow.rb:66:3:68:5 | m16 | +| action_controller/params_flow.rb:70:3:72:5 | m17 | +| action_controller/params_flow.rb:74:3:76:5 | m18 | +| action_controller/params_flow.rb:78:3:80:5 | m19 | +| action_controller/params_flow.rb:82:3:84:5 | m20 | +| action_controller/params_flow.rb:86:3:88:5 | m21 | +| action_controller/params_flow.rb:90:3:92:5 | m22 | +| action_controller/params_flow.rb:94:3:96:5 | m23 | +| action_controller/params_flow.rb:98:3:100:5 | m24 | +| action_controller/params_flow.rb:102:3:104:5 | m25 | +| action_controller/params_flow.rb:106:3:108:5 | m26 | +| action_controller/params_flow.rb:110:3:113:5 | m27 | +| action_controller/params_flow.rb:115:3:118:5 | m28 | +| action_controller/params_flow.rb:120:3:123:5 | m29 | +| action_controller/params_flow.rb:125:3:132:5 | m30 | +| action_controller/params_flow.rb:134:3:141:5 | m31 | +| action_controller/params_flow.rb:143:3:150:5 | m32 | | active_record/ActiveRecord.rb:27:3:38:5 | some_request_handler | | active_record/ActiveRecord.rb:42:3:47:5 | some_other_request_handler | | active_record/ActiveRecord.rb:49:3:63:5 | safe_paths | @@ -39,6 +73,48 @@ actionControllerActionMethods | app/controllers/posts_controller.rb:8:3:9:5 | upvote | | app/controllers/users/notifications_controller.rb:3:5:4:7 | mark_as_read | paramsCalls +| action_controller/params_flow.rb:3:10:3:15 | call to params | +| action_controller/params_flow.rb:7:10:7:15 | call to params | +| action_controller/params_flow.rb:11:10:11:15 | call to params | +| action_controller/params_flow.rb:15:10:15:15 | call to params | +| action_controller/params_flow.rb:19:10:19:15 | call to params | +| action_controller/params_flow.rb:23:10:23:15 | call to params | +| action_controller/params_flow.rb:27:10:27:15 | call to params | +| action_controller/params_flow.rb:31:10:31:15 | call to params | +| action_controller/params_flow.rb:35:10:35:15 | call to params | +| action_controller/params_flow.rb:39:10:39:15 | call to params | +| action_controller/params_flow.rb:43:10:43:15 | call to params | +| action_controller/params_flow.rb:47:10:47:15 | call to params | +| action_controller/params_flow.rb:51:10:51:15 | call to params | +| action_controller/params_flow.rb:55:10:55:15 | call to params | +| action_controller/params_flow.rb:59:10:59:15 | call to params | +| action_controller/params_flow.rb:63:10:63:15 | call to params | +| action_controller/params_flow.rb:67:10:67:15 | call to params | +| action_controller/params_flow.rb:71:10:71:15 | call to params | +| action_controller/params_flow.rb:75:10:75:15 | call to params | +| action_controller/params_flow.rb:79:10:79:15 | call to params | +| action_controller/params_flow.rb:83:10:83:15 | call to params | +| action_controller/params_flow.rb:87:10:87:15 | call to params | +| action_controller/params_flow.rb:91:10:91:15 | call to params | +| action_controller/params_flow.rb:95:10:95:15 | call to params | +| action_controller/params_flow.rb:99:10:99:15 | call to params | +| action_controller/params_flow.rb:103:10:103:15 | call to params | +| action_controller/params_flow.rb:107:10:107:15 | call to params | +| action_controller/params_flow.rb:111:10:111:15 | call to params | +| action_controller/params_flow.rb:112:23:112:28 | call to params | +| action_controller/params_flow.rb:116:10:116:15 | call to params | +| action_controller/params_flow.rb:117:31:117:36 | call to params | +| action_controller/params_flow.rb:121:10:121:15 | call to params | +| action_controller/params_flow.rb:122:31:122:36 | call to params | +| action_controller/params_flow.rb:126:10:126:15 | call to params | +| action_controller/params_flow.rb:127:24:127:29 | call to params | +| action_controller/params_flow.rb:130:14:130:19 | call to params | +| action_controller/params_flow.rb:135:10:135:15 | call to params | +| action_controller/params_flow.rb:136:32:136:37 | call to params | +| action_controller/params_flow.rb:139:22:139:27 | call to params | +| action_controller/params_flow.rb:144:10:144:15 | call to params | +| action_controller/params_flow.rb:145:32:145:37 | call to params | +| action_controller/params_flow.rb:148:22:148:27 | call to params | | active_record/ActiveRecord.rb:28:30:28:35 | call to params | | active_record/ActiveRecord.rb:29:29:29:34 | call to params | | active_record/ActiveRecord.rb:30:31:30:36 | call to params | @@ -71,6 +147,48 @@ paramsCalls | app/controllers/foo/bars_controller.rb:22:10:22:15 | call to params | | app/views/foo/bars/show.html.erb:5:9:5:14 | call to params | paramsSources +| action_controller/params_flow.rb:3:10:3:15 | call to params | +| action_controller/params_flow.rb:7:10:7:15 | call to params | +| action_controller/params_flow.rb:11:10:11:15 | call to params | +| action_controller/params_flow.rb:15:10:15:15 | call to params | +| action_controller/params_flow.rb:19:10:19:15 | call to params | +| action_controller/params_flow.rb:23:10:23:15 | call to params | +| action_controller/params_flow.rb:27:10:27:15 | call to params | +| action_controller/params_flow.rb:31:10:31:15 | call to params | +| action_controller/params_flow.rb:35:10:35:15 | call to params | +| action_controller/params_flow.rb:39:10:39:15 | call to params | +| action_controller/params_flow.rb:43:10:43:15 | call to params | +| action_controller/params_flow.rb:47:10:47:15 | call to params | +| action_controller/params_flow.rb:51:10:51:15 | call to params | +| action_controller/params_flow.rb:55:10:55:15 | call to params | +| action_controller/params_flow.rb:59:10:59:15 | call to params | +| action_controller/params_flow.rb:63:10:63:15 | call to params | +| action_controller/params_flow.rb:67:10:67:15 | call to params | +| action_controller/params_flow.rb:71:10:71:15 | call to params | +| action_controller/params_flow.rb:75:10:75:15 | call to params | +| action_controller/params_flow.rb:79:10:79:15 | call to params | +| action_controller/params_flow.rb:83:10:83:15 | call to params | +| action_controller/params_flow.rb:87:10:87:15 | call to params | +| action_controller/params_flow.rb:91:10:91:15 | call to params | +| action_controller/params_flow.rb:95:10:95:15 | call to params | +| action_controller/params_flow.rb:99:10:99:15 | call to params | +| action_controller/params_flow.rb:103:10:103:15 | call to params | +| action_controller/params_flow.rb:107:10:107:15 | call to params | +| action_controller/params_flow.rb:111:10:111:15 | call to params | +| action_controller/params_flow.rb:112:23:112:28 | call to params | +| action_controller/params_flow.rb:116:10:116:15 | call to params | +| action_controller/params_flow.rb:117:31:117:36 | call to params | +| action_controller/params_flow.rb:121:10:121:15 | call to params | +| action_controller/params_flow.rb:122:31:122:36 | call to params | +| action_controller/params_flow.rb:126:10:126:15 | call to params | +| action_controller/params_flow.rb:127:24:127:29 | call to params | +| action_controller/params_flow.rb:130:14:130:19 | call to params | +| action_controller/params_flow.rb:135:10:135:15 | call to params | +| action_controller/params_flow.rb:136:32:136:37 | call to params | +| action_controller/params_flow.rb:139:22:139:27 | call to params | +| action_controller/params_flow.rb:144:10:144:15 | call to params | +| action_controller/params_flow.rb:145:32:145:37 | call to params | +| action_controller/params_flow.rb:148:22:148:27 | call to params | | active_record/ActiveRecord.rb:28:30:28:35 | call to params | | active_record/ActiveRecord.rb:29:29:29:34 | call to params | | active_record/ActiveRecord.rb:30:31:30:36 | call to params | diff --git a/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.expected b/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.expected new file mode 100644 index 00000000000..d06e3862b30 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.expected @@ -0,0 +1,175 @@ +failures +edges +| params_flow.rb:3:10:3:15 | call to params : | params_flow.rb:3:10:3:19 | ...[...] | +| params_flow.rb:7:10:7:15 | call to params : | params_flow.rb:7:10:7:23 | call to as_json | +| params_flow.rb:15:10:15:15 | call to params : | params_flow.rb:15:10:15:33 | call to permit | +| params_flow.rb:19:10:19:15 | call to params : | params_flow.rb:19:10:19:34 | call to require | +| params_flow.rb:23:10:23:15 | call to params : | params_flow.rb:23:10:23:35 | call to required | +| params_flow.rb:27:10:27:15 | call to params : | params_flow.rb:27:10:27:24 | call to deep_dup | +| params_flow.rb:31:10:31:15 | call to params : | params_flow.rb:31:10:31:45 | call to deep_transform_keys | +| params_flow.rb:35:10:35:15 | call to params : | params_flow.rb:35:10:35:46 | call to deep_transform_keys! | +| params_flow.rb:39:10:39:15 | call to params : | params_flow.rb:39:10:39:48 | call to delete_if | +| params_flow.rb:43:10:43:15 | call to params : | params_flow.rb:43:10:43:32 | call to extract! | +| params_flow.rb:47:10:47:15 | call to params : | params_flow.rb:47:10:47:46 | call to keep_if | +| params_flow.rb:51:10:51:15 | call to params : | params_flow.rb:51:10:51:45 | call to select | +| params_flow.rb:55:10:55:15 | call to params : | params_flow.rb:55:10:55:46 | call to select! | +| params_flow.rb:59:10:59:15 | call to params : | params_flow.rb:59:10:59:45 | call to reject | +| params_flow.rb:63:10:63:15 | call to params : | params_flow.rb:63:10:63:46 | call to reject! | +| params_flow.rb:67:10:67:15 | call to params : | params_flow.rb:67:10:67:20 | call to to_h | +| params_flow.rb:71:10:71:15 | call to params : | params_flow.rb:71:10:71:23 | call to to_hash | +| params_flow.rb:75:10:75:15 | call to params : | params_flow.rb:75:10:75:24 | call to to_query | +| params_flow.rb:79:10:79:15 | call to params : | params_flow.rb:79:10:79:24 | call to to_param | +| params_flow.rb:83:10:83:15 | call to params : | params_flow.rb:83:10:83:27 | call to to_unsafe_h | +| params_flow.rb:87:10:87:15 | call to params : | params_flow.rb:87:10:87:30 | call to to_unsafe_hash | +| params_flow.rb:91:10:91:15 | call to params : | params_flow.rb:91:10:91:40 | call to transform_keys | +| params_flow.rb:95:10:95:15 | call to params : | params_flow.rb:95:10:95:41 | call to transform_keys! | +| params_flow.rb:99:10:99:15 | call to params : | params_flow.rb:99:10:99:42 | call to transform_values | +| params_flow.rb:103:10:103:15 | call to params : | params_flow.rb:103:10:103:43 | call to transform_values! | +| params_flow.rb:107:10:107:15 | call to params : | params_flow.rb:107:10:107:33 | call to values_at | +| params_flow.rb:111:10:111:15 | call to params : | params_flow.rb:111:10:111:29 | call to merge | +| params_flow.rb:112:23:112:28 | call to params : | params_flow.rb:112:10:112:29 | call to merge | +| params_flow.rb:116:10:116:15 | call to params : | params_flow.rb:116:10:116:37 | call to reverse_merge | +| params_flow.rb:117:31:117:36 | call to params : | params_flow.rb:117:10:117:37 | call to reverse_merge | +| params_flow.rb:121:10:121:15 | call to params : | params_flow.rb:121:10:121:43 | call to with_defaults | +| params_flow.rb:122:31:122:36 | call to params : | params_flow.rb:122:10:122:37 | call to with_defaults | +| params_flow.rb:126:10:126:15 | call to params : | params_flow.rb:126:10:126:30 | call to merge! | +| params_flow.rb:127:24:127:29 | call to params : | params_flow.rb:127:10:127:30 | call to merge! | +| params_flow.rb:130:5:130:5 | [post] p : | params_flow.rb:131:10:131:10 | p | +| params_flow.rb:130:14:130:19 | call to params : | params_flow.rb:130:5:130:5 | [post] p : | +| params_flow.rb:135:10:135:15 | call to params : | params_flow.rb:135:10:135:38 | call to reverse_merge! | +| params_flow.rb:136:32:136:37 | call to params : | params_flow.rb:136:10:136:38 | call to reverse_merge! | +| params_flow.rb:139:5:139:5 | [post] p : | params_flow.rb:140:10:140:10 | p | +| params_flow.rb:139:22:139:27 | call to params : | params_flow.rb:139:5:139:5 | [post] p : | +| params_flow.rb:144:10:144:15 | call to params : | params_flow.rb:144:10:144:44 | call to with_defaults! | +| params_flow.rb:145:32:145:37 | call to params : | params_flow.rb:145:10:145:38 | call to with_defaults! | +| params_flow.rb:148:5:148:5 | [post] p : | params_flow.rb:149:10:149:10 | p | +| params_flow.rb:148:22:148:27 | call to params : | params_flow.rb:148:5:148:5 | [post] p : | +nodes +| params_flow.rb:3:10:3:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:3:10:3:19 | ...[...] | semmle.label | ...[...] | +| params_flow.rb:7:10:7:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:7:10:7:23 | call to as_json | semmle.label | call to as_json | +| params_flow.rb:15:10:15:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:15:10:15:33 | call to permit | semmle.label | call to permit | +| params_flow.rb:19:10:19:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:19:10:19:34 | call to require | semmle.label | call to require | +| params_flow.rb:23:10:23:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:23:10:23:35 | call to required | semmle.label | call to required | +| params_flow.rb:27:10:27:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:27:10:27:24 | call to deep_dup | semmle.label | call to deep_dup | +| params_flow.rb:31:10:31:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:31:10:31:45 | call to deep_transform_keys | semmle.label | call to deep_transform_keys | +| params_flow.rb:35:10:35:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:35:10:35:46 | call to deep_transform_keys! | semmle.label | call to deep_transform_keys! | +| params_flow.rb:39:10:39:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:39:10:39:48 | call to delete_if | semmle.label | call to delete_if | +| params_flow.rb:43:10:43:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:43:10:43:32 | call to extract! | semmle.label | call to extract! | +| params_flow.rb:47:10:47:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:47:10:47:46 | call to keep_if | semmle.label | call to keep_if | +| params_flow.rb:51:10:51:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:51:10:51:45 | call to select | semmle.label | call to select | +| params_flow.rb:55:10:55:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:55:10:55:46 | call to select! | semmle.label | call to select! | +| params_flow.rb:59:10:59:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:59:10:59:45 | call to reject | semmle.label | call to reject | +| params_flow.rb:63:10:63:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:63:10:63:46 | call to reject! | semmle.label | call to reject! | +| params_flow.rb:67:10:67:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:67:10:67:20 | call to to_h | semmle.label | call to to_h | +| params_flow.rb:71:10:71:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:71:10:71:23 | call to to_hash | semmle.label | call to to_hash | +| params_flow.rb:75:10:75:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:75:10:75:24 | call to to_query | semmle.label | call to to_query | +| params_flow.rb:79:10:79:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:79:10:79:24 | call to to_param | semmle.label | call to to_param | +| params_flow.rb:83:10:83:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:83:10:83:27 | call to to_unsafe_h | semmle.label | call to to_unsafe_h | +| params_flow.rb:87:10:87:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:87:10:87:30 | call to to_unsafe_hash | semmle.label | call to to_unsafe_hash | +| params_flow.rb:91:10:91:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:91:10:91:40 | call to transform_keys | semmle.label | call to transform_keys | +| params_flow.rb:95:10:95:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:95:10:95:41 | call to transform_keys! | semmle.label | call to transform_keys! | +| params_flow.rb:99:10:99:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:99:10:99:42 | call to transform_values | semmle.label | call to transform_values | +| params_flow.rb:103:10:103:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:103:10:103:43 | call to transform_values! | semmle.label | call to transform_values! | +| params_flow.rb:107:10:107:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:107:10:107:33 | call to values_at | semmle.label | call to values_at | +| params_flow.rb:111:10:111:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:111:10:111:29 | call to merge | semmle.label | call to merge | +| params_flow.rb:112:10:112:29 | call to merge | semmle.label | call to merge | +| params_flow.rb:112:23:112:28 | call to params : | semmle.label | call to params : | +| params_flow.rb:116:10:116:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:116:10:116:37 | call to reverse_merge | semmle.label | call to reverse_merge | +| params_flow.rb:117:10:117:37 | call to reverse_merge | semmle.label | call to reverse_merge | +| params_flow.rb:117:31:117:36 | call to params : | semmle.label | call to params : | +| params_flow.rb:121:10:121:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:121:10:121:43 | call to with_defaults | semmle.label | call to with_defaults | +| params_flow.rb:122:10:122:37 | call to with_defaults | semmle.label | call to with_defaults | +| params_flow.rb:122:31:122:36 | call to params : | semmle.label | call to params : | +| params_flow.rb:126:10:126:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:126:10:126:30 | call to merge! | semmle.label | call to merge! | +| params_flow.rb:127:10:127:30 | call to merge! | semmle.label | call to merge! | +| params_flow.rb:127:24:127:29 | call to params : | semmle.label | call to params : | +| params_flow.rb:130:5:130:5 | [post] p : | semmle.label | [post] p : | +| params_flow.rb:130:14:130:19 | call to params : | semmle.label | call to params : | +| params_flow.rb:131:10:131:10 | p | semmle.label | p | +| params_flow.rb:135:10:135:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:135:10:135:38 | call to reverse_merge! | semmle.label | call to reverse_merge! | +| params_flow.rb:136:10:136:38 | call to reverse_merge! | semmle.label | call to reverse_merge! | +| params_flow.rb:136:32:136:37 | call to params : | semmle.label | call to params : | +| params_flow.rb:139:5:139:5 | [post] p : | semmle.label | [post] p : | +| params_flow.rb:139:22:139:27 | call to params : | semmle.label | call to params : | +| params_flow.rb:140:10:140:10 | p | semmle.label | p | +| params_flow.rb:144:10:144:15 | call to params : | semmle.label | call to params : | +| params_flow.rb:144:10:144:44 | call to with_defaults! | semmle.label | call to with_defaults! | +| params_flow.rb:145:10:145:38 | call to with_defaults! | semmle.label | call to with_defaults! | +| params_flow.rb:145:32:145:37 | call to params : | semmle.label | call to params : | +| params_flow.rb:148:5:148:5 | [post] p : | semmle.label | [post] p : | +| params_flow.rb:148:22:148:27 | call to params : | semmle.label | call to params : | +| params_flow.rb:149:10:149:10 | p | semmle.label | p | +subpaths +#select +| params_flow.rb:3:10:3:19 | ...[...] | params_flow.rb:3:10:3:15 | call to params : | params_flow.rb:3:10:3:19 | ...[...] | $@ | params_flow.rb:3:10:3:15 | call to params : | call to params : | +| params_flow.rb:7:10:7:23 | call to as_json | params_flow.rb:7:10:7:15 | call to params : | params_flow.rb:7:10:7:23 | call to as_json | $@ | params_flow.rb:7:10:7:15 | call to params : | call to params : | +| params_flow.rb:15:10:15:33 | call to permit | params_flow.rb:15:10:15:15 | call to params : | params_flow.rb:15:10:15:33 | call to permit | $@ | params_flow.rb:15:10:15:15 | call to params : | call to params : | +| params_flow.rb:19:10:19:34 | call to require | params_flow.rb:19:10:19:15 | call to params : | params_flow.rb:19:10:19:34 | call to require | $@ | params_flow.rb:19:10:19:15 | call to params : | call to params : | +| params_flow.rb:23:10:23:35 | call to required | params_flow.rb:23:10:23:15 | call to params : | params_flow.rb:23:10:23:35 | call to required | $@ | params_flow.rb:23:10:23:15 | call to params : | call to params : | +| params_flow.rb:27:10:27:24 | call to deep_dup | params_flow.rb:27:10:27:15 | call to params : | params_flow.rb:27:10:27:24 | call to deep_dup | $@ | params_flow.rb:27:10:27:15 | call to params : | call to params : | +| params_flow.rb:31:10:31:45 | call to deep_transform_keys | params_flow.rb:31:10:31:15 | call to params : | params_flow.rb:31:10:31:45 | call to deep_transform_keys | $@ | params_flow.rb:31:10:31:15 | call to params : | call to params : | +| params_flow.rb:35:10:35:46 | call to deep_transform_keys! | params_flow.rb:35:10:35:15 | call to params : | params_flow.rb:35:10:35:46 | call to deep_transform_keys! | $@ | params_flow.rb:35:10:35:15 | call to params : | call to params : | +| params_flow.rb:39:10:39:48 | call to delete_if | params_flow.rb:39:10:39:15 | call to params : | params_flow.rb:39:10:39:48 | call to delete_if | $@ | params_flow.rb:39:10:39:15 | call to params : | call to params : | +| params_flow.rb:43:10:43:32 | call to extract! | params_flow.rb:43:10:43:15 | call to params : | params_flow.rb:43:10:43:32 | call to extract! | $@ | params_flow.rb:43:10:43:15 | call to params : | call to params : | +| params_flow.rb:47:10:47:46 | call to keep_if | params_flow.rb:47:10:47:15 | call to params : | params_flow.rb:47:10:47:46 | call to keep_if | $@ | params_flow.rb:47:10:47:15 | call to params : | call to params : | +| params_flow.rb:51:10:51:45 | call to select | params_flow.rb:51:10:51:15 | call to params : | params_flow.rb:51:10:51:45 | call to select | $@ | params_flow.rb:51:10:51:15 | call to params : | call to params : | +| params_flow.rb:55:10:55:46 | call to select! | params_flow.rb:55:10:55:15 | call to params : | params_flow.rb:55:10:55:46 | call to select! | $@ | params_flow.rb:55:10:55:15 | call to params : | call to params : | +| params_flow.rb:59:10:59:45 | call to reject | params_flow.rb:59:10:59:15 | call to params : | params_flow.rb:59:10:59:45 | call to reject | $@ | params_flow.rb:59:10:59:15 | call to params : | call to params : | +| params_flow.rb:63:10:63:46 | call to reject! | params_flow.rb:63:10:63:15 | call to params : | params_flow.rb:63:10:63:46 | call to reject! | $@ | params_flow.rb:63:10:63:15 | call to params : | call to params : | +| params_flow.rb:67:10:67:20 | call to to_h | params_flow.rb:67:10:67:15 | call to params : | params_flow.rb:67:10:67:20 | call to to_h | $@ | params_flow.rb:67:10:67:15 | call to params : | call to params : | +| params_flow.rb:71:10:71:23 | call to to_hash | params_flow.rb:71:10:71:15 | call to params : | params_flow.rb:71:10:71:23 | call to to_hash | $@ | params_flow.rb:71:10:71:15 | call to params : | call to params : | +| params_flow.rb:75:10:75:24 | call to to_query | params_flow.rb:75:10:75:15 | call to params : | params_flow.rb:75:10:75:24 | call to to_query | $@ | params_flow.rb:75:10:75:15 | call to params : | call to params : | +| params_flow.rb:79:10:79:24 | call to to_param | params_flow.rb:79:10:79:15 | call to params : | params_flow.rb:79:10:79:24 | call to to_param | $@ | params_flow.rb:79:10:79:15 | call to params : | call to params : | +| params_flow.rb:83:10:83:27 | call to to_unsafe_h | params_flow.rb:83:10:83:15 | call to params : | params_flow.rb:83:10:83:27 | call to to_unsafe_h | $@ | params_flow.rb:83:10:83:15 | call to params : | call to params : | +| params_flow.rb:87:10:87:30 | call to to_unsafe_hash | params_flow.rb:87:10:87:15 | call to params : | params_flow.rb:87:10:87:30 | call to to_unsafe_hash | $@ | params_flow.rb:87:10:87:15 | call to params : | call to params : | +| params_flow.rb:91:10:91:40 | call to transform_keys | params_flow.rb:91:10:91:15 | call to params : | params_flow.rb:91:10:91:40 | call to transform_keys | $@ | params_flow.rb:91:10:91:15 | call to params : | call to params : | +| params_flow.rb:95:10:95:41 | call to transform_keys! | params_flow.rb:95:10:95:15 | call to params : | params_flow.rb:95:10:95:41 | call to transform_keys! | $@ | params_flow.rb:95:10:95:15 | call to params : | call to params : | +| params_flow.rb:99:10:99:42 | call to transform_values | params_flow.rb:99:10:99:15 | call to params : | params_flow.rb:99:10:99:42 | call to transform_values | $@ | params_flow.rb:99:10:99:15 | call to params : | call to params : | +| params_flow.rb:103:10:103:43 | call to transform_values! | params_flow.rb:103:10:103:15 | call to params : | params_flow.rb:103:10:103:43 | call to transform_values! | $@ | params_flow.rb:103:10:103:15 | call to params : | call to params : | +| params_flow.rb:107:10:107:33 | call to values_at | params_flow.rb:107:10:107:15 | call to params : | params_flow.rb:107:10:107:33 | call to values_at | $@ | params_flow.rb:107:10:107:15 | call to params : | call to params : | +| params_flow.rb:111:10:111:29 | call to merge | params_flow.rb:111:10:111:15 | call to params : | params_flow.rb:111:10:111:29 | call to merge | $@ | params_flow.rb:111:10:111:15 | call to params : | call to params : | +| params_flow.rb:112:10:112:29 | call to merge | params_flow.rb:112:23:112:28 | call to params : | params_flow.rb:112:10:112:29 | call to merge | $@ | params_flow.rb:112:23:112:28 | call to params : | call to params : | +| params_flow.rb:116:10:116:37 | call to reverse_merge | params_flow.rb:116:10:116:15 | call to params : | params_flow.rb:116:10:116:37 | call to reverse_merge | $@ | params_flow.rb:116:10:116:15 | call to params : | call to params : | +| params_flow.rb:117:10:117:37 | call to reverse_merge | params_flow.rb:117:31:117:36 | call to params : | params_flow.rb:117:10:117:37 | call to reverse_merge | $@ | params_flow.rb:117:31:117:36 | call to params : | call to params : | +| params_flow.rb:121:10:121:43 | call to with_defaults | params_flow.rb:121:10:121:15 | call to params : | params_flow.rb:121:10:121:43 | call to with_defaults | $@ | params_flow.rb:121:10:121:15 | call to params : | call to params : | +| params_flow.rb:122:10:122:37 | call to with_defaults | params_flow.rb:122:31:122:36 | call to params : | params_flow.rb:122:10:122:37 | call to with_defaults | $@ | params_flow.rb:122:31:122:36 | call to params : | call to params : | +| params_flow.rb:126:10:126:30 | call to merge! | params_flow.rb:126:10:126:15 | call to params : | params_flow.rb:126:10:126:30 | call to merge! | $@ | params_flow.rb:126:10:126:15 | call to params : | call to params : | +| params_flow.rb:127:10:127:30 | call to merge! | params_flow.rb:127:24:127:29 | call to params : | params_flow.rb:127:10:127:30 | call to merge! | $@ | params_flow.rb:127:24:127:29 | call to params : | call to params : | +| params_flow.rb:131:10:131:10 | p | params_flow.rb:130:14:130:19 | call to params : | params_flow.rb:131:10:131:10 | p | $@ | params_flow.rb:130:14:130:19 | call to params : | call to params : | +| params_flow.rb:135:10:135:38 | call to reverse_merge! | params_flow.rb:135:10:135:15 | call to params : | params_flow.rb:135:10:135:38 | call to reverse_merge! | $@ | params_flow.rb:135:10:135:15 | call to params : | call to params : | +| params_flow.rb:136:10:136:38 | call to reverse_merge! | params_flow.rb:136:32:136:37 | call to params : | params_flow.rb:136:10:136:38 | call to reverse_merge! | $@ | params_flow.rb:136:32:136:37 | call to params : | call to params : | +| params_flow.rb:140:10:140:10 | p | params_flow.rb:139:22:139:27 | call to params : | params_flow.rb:140:10:140:10 | p | $@ | params_flow.rb:139:22:139:27 | call to params : | call to params : | +| params_flow.rb:144:10:144:44 | call to with_defaults! | params_flow.rb:144:10:144:15 | call to params : | params_flow.rb:144:10:144:44 | call to with_defaults! | $@ | params_flow.rb:144:10:144:15 | call to params : | call to params : | +| params_flow.rb:145:10:145:38 | call to with_defaults! | params_flow.rb:145:32:145:37 | call to params : | params_flow.rb:145:10:145:38 | call to with_defaults! | $@ | params_flow.rb:145:32:145:37 | call to params : | call to params : | +| params_flow.rb:149:10:149:10 | p | params_flow.rb:148:22:148:27 | call to params : | params_flow.rb:149:10:149:10 | p | $@ | params_flow.rb:148:22:148:27 | call to params : | call to params : | diff --git a/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.ql b/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.ql new file mode 100644 index 00000000000..412ba5534b8 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_controller/params-flow.ql @@ -0,0 +1,18 @@ +/** + * @kind path-problem + */ + +import ruby +import TestUtilities.InlineFlowTest +import PathGraph +import codeql.ruby.frameworks.Rails + +class ParamsTaintFlowConf extends DefaultTaintFlowConf { + override predicate isSource(DataFlow::Node n) { + n.asExpr().getExpr() instanceof Rails::ParamsCall + } +} + +from DataFlow::PathNode source, DataFlow::PathNode sink, ParamsTaintFlowConf conf +where conf.hasFlowPath(source, sink) +select sink, source, sink, "$@", source, source.toString() diff --git a/ruby/ql/test/library-tests/frameworks/action_controller/params_flow.rb b/ruby/ql/test/library-tests/frameworks/action_controller/params_flow.rb new file mode 100644 index 00000000000..7b4dc634720 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_controller/params_flow.rb @@ -0,0 +1,151 @@ +class MyController < ActionController::Base + def m1 + sink params[:a] # $hasTaintFlow + end + + def m2 + sink params.as_json # $hasTaintFlow + end + + def m2 + sink params.not_a_method + end + + def m3 + sink params.permit(:some_key) # $hasTaintFlow + end + + def m4 + sink params.require(:some_key) # $hasTaintFlow + end + + def m5 + sink params.required(:some_key) # $hasTaintFlow + end + + def m6 + sink params.deep_dup # $hasTaintFlow + end + + def m7 + sink params.deep_transform_keys(&:upcase) # $hasTaintFlow + end + + def m8 + sink params.deep_transform_keys!(&:upcase) # $hasTaintFlow + end + + def m9 + sink params.delete_if { |v| v.match? regex } # $hasTaintFlow + end + + def m10 + sink params.extract!(:a, :b) # $hasTaintFlow + end + + def m11 + sink params.keep_if { |v| v.match? regex } # $hasTaintFlow + end + + def m12 + sink params.select { |v| v.match? regex } # $hasTaintFlow + end + + def m13 + sink params.select! { |v| v.match? regex } # $hasTaintFlow + end + + def m14 + sink params.reject { |v| v.match? regex } # $hasTaintFlow + end + + def m15 + sink params.reject! { |v| v.match? regex } # $hasTaintFlow + end + + def m16 + sink params.to_h # $hasTaintFlow + end + + def m17 + sink params.to_hash # $hasTaintFlow + end + + def m18 + sink params.to_query # $hasTaintFlow + end + + def m19 + sink params.to_param # $hasTaintFlow + end + + def m20 + sink params.to_unsafe_h # $hasTaintFlow + end + + def m21 + sink params.to_unsafe_hash # $hasTaintFlow + end + + def m22 + sink params.transform_keys(&:upcase) # $hasTaintFlow + end + + def m23 + sink params.transform_keys!(&:upcase) # $hasTaintFlow + end + + def m24 + sink params.transform_values(&:upcase) # $hasTaintFlow + end + + def m25 + sink params.transform_values!(&:upcase) # $hasTaintFlow + end + + def m26 + sink params.values_at(:a, :b) # $hasTaintFlow + end + + def m27 + sink params.merge({a: 1}) # $hasTaintFlow + sink {a: 1}.merge(params) # $hasTaintFlow + end + + def m28 + sink params.reverse_merge({a: 1}) # $hasTaintFlow + sink {a: 1}.reverse_merge(params) # $hasTaintFlow + end + + def m29 + sink params.with_defaults({a: 1, b: 2}) # $hasTaintFlow + sink {a: 1}.with_defaults(params) # $hasTaintFlow + end + + def m30 + sink params.merge!({a: 1}) # $hasTaintFlow + sink {a: 1}.merge!(params) # $hasTaintFlow + + p = {a: 1} + p.merge!(params) + sink p # $hasTaintFlow + end + + def m31 + sink params.reverse_merge!({a: 1}) # $hasTaintFlow + sink {a: 1}.reverse_merge!(params) # $hasTaintFlow + + p = {a: 1} + p.reverse_merge!(params) + sink p # $hasTaintFlow + end + + def m32 + sink params.with_defaults!({a: 1, b: 2}) # $hasTaintFlow + sink {a: 1}.with_defaults!(params) # $hasTaintFlow + + p = {a: 1} + p.with_defaults!(params) + sink p # $hasTaintFlow + end +end diff --git a/ruby/ql/test/library-tests/modules/ancestors.expected b/ruby/ql/test/library-tests/modules/ancestors.expected index 2de1b03148e..98cfa6c7186 100644 --- a/ruby/ql/test/library-tests/modules/ancestors.expected +++ b/ruby/ql/test/library-tests/modules/ancestors.expected @@ -89,25 +89,25 @@ calls.rb: # 377| SingletonOverride1 #-----| super -> Object -# 402| SingletonOverride2 +# 404| SingletonOverride2 #-----| super -> SingletonOverride1 -# 417| ConditionalInstanceMethods +# 421| ConditionalInstanceMethods #-----| super -> Object -# 480| ExtendSingletonMethod +# 484| ExtendSingletonMethod -# 490| ExtendSingletonMethod2 +# 494| ExtendSingletonMethod2 -# 496| ExtendSingletonMethod3 +# 500| ExtendSingletonMethod3 -# 509| ProtectedMethodInModule +# 513| ProtectedMethodInModule -# 515| ProtectedMethods +# 519| ProtectedMethods #-----| super -> Object #-----| include -> ProtectedMethodInModule -# 534| ProtectedMethodsSub +# 538| ProtectedMethodsSub #-----| super -> ProtectedMethods hello.rb: diff --git a/ruby/ql/test/library-tests/modules/callgraph.expected b/ruby/ql/test/library-tests/modules/callgraph.expected index 25147f93b1b..df2bffe2933 100644 --- a/ruby/ql/test/library-tests/modules/callgraph.expected +++ b/ruby/ql/test/library-tests/modules/callgraph.expected @@ -148,67 +148,73 @@ getTarget | calls.rb:375:1:375:11 | call to instance | calls.rb:368:5:370:7 | instance | | calls.rb:380:13:380:48 | call to puts | calls.rb:102:5:102:30 | puts | | calls.rb:384:13:384:22 | call to singleton1 | calls.rb:379:9:381:11 | singleton1 | -| calls.rb:384:13:384:22 | call to singleton1 | calls.rb:404:9:406:11 | singleton1 | +| calls.rb:384:13:384:22 | call to singleton1 | calls.rb:406:9:408:11 | singleton1 | | calls.rb:389:9:389:44 | call to puts | calls.rb:102:5:102:30 | puts | | calls.rb:393:9:393:18 | call to singleton2 | calls.rb:388:5:390:7 | singleton2 | -| calls.rb:393:9:393:18 | call to singleton2 | calls.rb:409:5:411:7 | singleton2 | +| calls.rb:393:9:393:18 | call to singleton2 | calls.rb:411:5:413:7 | singleton2 | | calls.rb:396:5:396:14 | call to singleton2 | calls.rb:388:5:390:7 | singleton2 | -| calls.rb:399:1:399:34 | call to call_singleton1 | calls.rb:383:9:385:11 | call_singleton1 | -| calls.rb:400:1:400:34 | call to call_singleton2 | calls.rb:392:5:394:7 | call_singleton2 | -| calls.rb:405:13:405:48 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:410:9:410:44 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:420:13:420:48 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:425:9:425:44 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:428:13:428:48 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:431:17:431:52 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:439:9:443:11 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:439:9:443:15 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:441:17:441:40 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:447:1:447:30 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:447:1:447:33 | call to m1 | calls.rb:419:9:421:11 | m1 | -| calls.rb:448:1:448:30 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:449:1:449:30 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:449:1:449:33 | call to m2 | calls.rb:424:5:436:7 | m2 | -| calls.rb:450:1:450:30 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:399:1:399:29 | call to singleton1 | calls.rb:379:9:381:11 | singleton1 | +| calls.rb:400:1:400:29 | call to singleton2 | calls.rb:388:5:390:7 | singleton2 | +| calls.rb:401:1:401:34 | call to call_singleton1 | calls.rb:383:9:385:11 | call_singleton1 | +| calls.rb:402:1:402:34 | call to call_singleton2 | calls.rb:392:5:394:7 | call_singleton2 | +| calls.rb:407:13:407:48 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:412:9:412:44 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:416:1:416:29 | call to singleton1 | calls.rb:406:9:408:11 | singleton1 | +| calls.rb:417:1:417:29 | call to singleton2 | calls.rb:411:5:413:7 | singleton2 | +| calls.rb:418:1:418:34 | call to call_singleton1 | calls.rb:383:9:385:11 | call_singleton1 | +| calls.rb:419:1:419:34 | call to call_singleton2 | calls.rb:392:5:394:7 | call_singleton2 | +| calls.rb:424:13:424:48 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:429:9:429:44 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:432:13:432:48 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:435:17:435:52 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:443:9:447:11 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:443:9:447:15 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:445:17:445:40 | call to puts | calls.rb:102:5:102:30 | puts | | calls.rb:451:1:451:30 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:451:1:451:33 | call to m1 | calls.rb:423:9:425:11 | m1 | | calls.rb:452:1:452:30 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:454:27:472:3 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:457:13:457:22 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:461:5:465:7 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:461:5:465:11 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:463:13:463:22 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:469:13:469:27 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:474:1:474:27 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:475:1:475:27 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:476:1:476:27 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:477:1:477:27 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:453:1:453:30 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:453:1:453:33 | call to m2 | calls.rb:428:5:440:7 | m2 | +| calls.rb:454:1:454:30 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:455:1:455:30 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:456:1:456:30 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:458:27:476:3 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:461:13:461:22 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:465:5:469:7 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:465:5:469:11 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:467:13:467:22 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:473:13:473:27 | call to puts | calls.rb:102:5:102:30 | puts | | calls.rb:478:1:478:27 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:488:1:488:31 | call to singleton | calls.rb:481:5:483:7 | singleton | -| calls.rb:494:1:494:32 | call to singleton | calls.rb:481:5:483:7 | singleton | -| calls.rb:501:1:501:32 | call to singleton | calls.rb:481:5:483:7 | singleton | -| calls.rb:507:1:507:13 | call to singleton | calls.rb:481:5:483:7 | singleton | -| calls.rb:516:5:516:35 | call to include | calls.rb:108:5:110:7 | include | -| calls.rb:519:9:519:35 | call to puts | calls.rb:102:5:102:30 | puts | -| calls.rb:523:9:523:11 | call to foo | calls.rb:510:15:512:7 | foo | -| calls.rb:524:9:524:11 | call to bar | calls.rb:518:15:520:7 | bar | -| calls.rb:525:9:525:28 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:525:9:525:32 | call to foo | calls.rb:510:15:512:7 | foo | -| calls.rb:526:9:526:28 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:526:9:526:32 | call to bar | calls.rb:518:15:520:7 | bar | -| calls.rb:530:1:530:20 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:531:1:531:20 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:532:1:532:20 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:532:1:532:24 | call to baz | calls.rb:522:5:527:7 | baz | -| calls.rb:536:9:536:11 | call to foo | calls.rb:510:15:512:7 | foo | -| calls.rb:537:9:537:31 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:537:9:537:35 | call to foo | calls.rb:510:15:512:7 | foo | -| calls.rb:541:1:541:23 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:542:1:542:23 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:543:1:543:23 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:543:1:543:27 | call to baz | calls.rb:535:5:538:7 | baz | -| calls.rb:545:2:545:6 | call to new | calls.rb:117:5:117:16 | new | -| calls.rb:545:20:545:24 | call to baz | calls.rb:51:5:57:7 | baz | -| calls.rb:546:26:546:37 | call to capitalize | calls.rb:97:5:97:23 | capitalize | +| calls.rb:479:1:479:27 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:480:1:480:27 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:481:1:481:27 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:482:1:482:27 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:492:1:492:31 | call to singleton | calls.rb:485:5:487:7 | singleton | +| calls.rb:498:1:498:32 | call to singleton | calls.rb:485:5:487:7 | singleton | +| calls.rb:505:1:505:32 | call to singleton | calls.rb:485:5:487:7 | singleton | +| calls.rb:511:1:511:13 | call to singleton | calls.rb:485:5:487:7 | singleton | +| calls.rb:520:5:520:35 | call to include | calls.rb:108:5:110:7 | include | +| calls.rb:523:9:523:35 | call to puts | calls.rb:102:5:102:30 | puts | +| calls.rb:527:9:527:11 | call to foo | calls.rb:514:15:516:7 | foo | +| calls.rb:528:9:528:11 | call to bar | calls.rb:522:15:524:7 | bar | +| calls.rb:529:9:529:28 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:529:9:529:32 | call to foo | calls.rb:514:15:516:7 | foo | +| calls.rb:530:9:530:28 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:530:9:530:32 | call to bar | calls.rb:522:15:524:7 | bar | +| calls.rb:534:1:534:20 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:535:1:535:20 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:536:1:536:20 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:536:1:536:24 | call to baz | calls.rb:526:5:531:7 | baz | +| calls.rb:540:9:540:11 | call to foo | calls.rb:514:15:516:7 | foo | +| calls.rb:541:9:541:31 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:541:9:541:35 | call to foo | calls.rb:514:15:516:7 | foo | +| calls.rb:545:1:545:23 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:546:1:546:23 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:547:1:547:23 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:547:1:547:27 | call to baz | calls.rb:539:5:542:7 | baz | +| calls.rb:549:2:549:6 | call to new | calls.rb:117:5:117:16 | new | +| calls.rb:549:20:549:24 | call to baz | calls.rb:51:5:57:7 | baz | +| calls.rb:550:26:550:37 | call to capitalize | calls.rb:97:5:97:23 | capitalize | | hello.rb:12:5:12:24 | call to include | calls.rb:108:5:110:7 | include | | hello.rb:14:16:14:20 | call to hello | hello.rb:2:5:4:7 | hello | | hello.rb:20:16:20:20 | call to super | hello.rb:13:5:15:7 | message | @@ -286,46 +292,44 @@ unresolvedCall | calls.rb:274:1:274:14 | call to singleton_g | | calls.rb:276:1:276:14 | call to singleton_g | | calls.rb:313:9:313:20 | call to instance | -| calls.rb:414:1:414:34 | call to call_singleton1 | -| calls.rb:415:1:415:34 | call to call_singleton2 | -| calls.rb:418:8:418:13 | call to rand | -| calls.rb:418:8:418:17 | ... > ... | -| calls.rb:435:9:435:10 | call to m3 | -| calls.rb:438:8:438:13 | call to rand | -| calls.rb:438:8:438:17 | ... > ... | -| calls.rb:439:9:443:18 | call to m5 | -| calls.rb:448:1:448:33 | call to m3 | -| calls.rb:450:1:450:33 | call to m3 | -| calls.rb:451:1:451:33 | call to m4 | -| calls.rb:452:1:452:33 | call to m5 | -| calls.rb:455:5:455:11 | call to [] | -| calls.rb:455:5:459:7 | call to each | -| calls.rb:461:5:465:15 | call to bar | -| calls.rb:467:5:467:11 | call to [] | -| calls.rb:467:5:471:7 | call to each | -| calls.rb:468:9:470:11 | call to define_method | -| calls.rb:474:1:474:31 | call to foo | -| calls.rb:475:1:475:31 | call to bar | -| calls.rb:476:1:476:33 | call to baz_0 | -| calls.rb:477:1:477:33 | call to baz_1 | -| calls.rb:478:1:478:33 | call to baz_2 | -| calls.rb:482:9:482:46 | call to puts | -| calls.rb:485:5:485:15 | call to extend | -| calls.rb:491:5:491:32 | call to extend | -| calls.rb:499:1:499:51 | call to extend | -| calls.rb:504:1:504:13 | call to singleton | -| calls.rb:505:1:505:32 | call to extend | -| calls.rb:510:5:512:7 | call to protected | -| calls.rb:511:9:511:42 | call to puts | -| calls.rb:518:5:520:7 | call to protected | -| calls.rb:530:1:530:24 | call to foo | -| calls.rb:531:1:531:24 | call to bar | -| calls.rb:541:1:541:27 | call to foo | -| calls.rb:542:1:542:27 | call to bar | -| calls.rb:545:1:545:7 | call to [] | -| calls.rb:545:1:545:26 | call to each | -| calls.rb:546:1:546:13 | call to [] | -| calls.rb:546:1:546:39 | call to each | +| calls.rb:422:8:422:13 | call to rand | +| calls.rb:422:8:422:17 | ... > ... | +| calls.rb:439:9:439:10 | call to m3 | +| calls.rb:442:8:442:13 | call to rand | +| calls.rb:442:8:442:17 | ... > ... | +| calls.rb:443:9:447:18 | call to m5 | +| calls.rb:452:1:452:33 | call to m3 | +| calls.rb:454:1:454:33 | call to m3 | +| calls.rb:455:1:455:33 | call to m4 | +| calls.rb:456:1:456:33 | call to m5 | +| calls.rb:459:5:459:11 | call to [] | +| calls.rb:459:5:463:7 | call to each | +| calls.rb:465:5:469:15 | call to bar | +| calls.rb:471:5:471:11 | call to [] | +| calls.rb:471:5:475:7 | call to each | +| calls.rb:472:9:474:11 | call to define_method | +| calls.rb:478:1:478:31 | call to foo | +| calls.rb:479:1:479:31 | call to bar | +| calls.rb:480:1:480:33 | call to baz_0 | +| calls.rb:481:1:481:33 | call to baz_1 | +| calls.rb:482:1:482:33 | call to baz_2 | +| calls.rb:486:9:486:46 | call to puts | +| calls.rb:489:5:489:15 | call to extend | +| calls.rb:495:5:495:32 | call to extend | +| calls.rb:503:1:503:51 | call to extend | +| calls.rb:508:1:508:13 | call to singleton | +| calls.rb:509:1:509:32 | call to extend | +| calls.rb:514:5:516:7 | call to protected | +| calls.rb:515:9:515:42 | call to puts | +| calls.rb:522:5:524:7 | call to protected | +| calls.rb:534:1:534:24 | call to foo | +| calls.rb:535:1:535:24 | call to bar | +| calls.rb:545:1:545:27 | call to foo | +| calls.rb:546:1:546:27 | call to bar | +| calls.rb:549:1:549:7 | call to [] | +| calls.rb:549:1:549:26 | call to each | +| calls.rb:550:1:550:13 | call to [] | +| calls.rb:550:1:550:39 | call to each | | hello.rb:20:16:20:26 | ... + ... | | hello.rb:20:16:20:34 | ... + ... | | hello.rb:20:16:20:40 | ... + ... | @@ -351,8 +355,8 @@ privateMethod | calls.rb:278:1:286:3 | create | | calls.rb:343:1:359:3 | pattern_dispatch | | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:456:9:458:11 | foo | -| calls.rb:462:9:464:11 | bar | +| calls.rb:460:9:462:11 | foo | +| calls.rb:466:9:468:11 | bar | | private.rb:2:11:3:5 | private1 | | private.rb:8:3:9:5 | private2 | | private.rb:14:3:15:5 | private3 | @@ -417,16 +421,16 @@ publicMethod | calls.rb:383:9:385:11 | call_singleton1 | | calls.rb:388:5:390:7 | singleton2 | | calls.rb:392:5:394:7 | call_singleton2 | -| calls.rb:404:9:406:11 | singleton1 | -| calls.rb:409:5:411:7 | singleton2 | -| calls.rb:419:9:421:11 | m1 | -| calls.rb:424:5:436:7 | m2 | -| calls.rb:427:9:433:11 | m3 | -| calls.rb:430:13:432:15 | m4 | -| calls.rb:440:13:442:15 | m5 | -| calls.rb:481:5:483:7 | singleton | -| calls.rb:522:5:527:7 | baz | -| calls.rb:535:5:538:7 | baz | +| calls.rb:406:9:408:11 | singleton1 | +| calls.rb:411:5:413:7 | singleton2 | +| calls.rb:423:9:425:11 | m1 | +| calls.rb:428:5:440:7 | m2 | +| calls.rb:431:9:437:11 | m3 | +| calls.rb:434:13:436:15 | m4 | +| calls.rb:444:13:446:15 | m5 | +| calls.rb:485:5:487:7 | singleton | +| calls.rb:526:5:531:7 | baz | +| calls.rb:539:5:542:7 | baz | | hello.rb:2:5:4:7 | hello | | hello.rb:5:5:7:7 | world | | hello.rb:13:5:15:7 | message | @@ -443,7 +447,7 @@ publicMethod | private.rb:66:3:67:5 | public | | private.rb:91:3:93:5 | call_m1 | protectedMethod -| calls.rb:510:15:512:7 | foo | -| calls.rb:518:15:520:7 | bar | +| calls.rb:514:15:516:7 | foo | +| calls.rb:522:15:524:7 | bar | | private.rb:32:3:33:5 | protected1 | | private.rb:35:3:36:5 | protected2 | diff --git a/ruby/ql/test/library-tests/modules/calls.rb b/ruby/ql/test/library-tests/modules/calls.rb index 4f5ab8bf966..4996ed93bb3 100644 --- a/ruby/ql/test/library-tests/modules/calls.rb +++ b/ruby/ql/test/library-tests/modules/calls.rb @@ -396,6 +396,8 @@ class SingletonOverride1 singleton2 end +SingletonOverride1.singleton1 +SingletonOverride1.singleton2 SingletonOverride1.call_singleton1 SingletonOverride1.call_singleton2 @@ -411,6 +413,8 @@ class SingletonOverride2 < SingletonOverride1 end end +SingletonOverride2.singleton1 +SingletonOverride2.singleton2 SingletonOverride2.call_singleton1 SingletonOverride2.call_singleton2 diff --git a/ruby/ql/test/library-tests/modules/methods.expected b/ruby/ql/test/library-tests/modules/methods.expected index b9ade37cf67..d7d30b4f2e7 100644 --- a/ruby/ql/test/library-tests/modules/methods.expected +++ b/ruby/ql/test/library-tests/modules/methods.expected @@ -36,13 +36,13 @@ getMethod | calls.rb:325:1:329:3 | C1 | instance | calls.rb:326:5:328:7 | instance | | calls.rb:331:1:335:3 | C2 | instance | calls.rb:332:5:334:7 | instance | | calls.rb:337:1:341:3 | C3 | instance | calls.rb:338:5:340:7 | instance | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | m1 | calls.rb:419:9:421:11 | m1 | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | m2 | calls.rb:424:5:436:7 | m2 | -| calls.rb:480:1:486:3 | ExtendSingletonMethod | singleton | calls.rb:481:5:483:7 | singleton | -| calls.rb:509:1:513:3 | ProtectedMethodInModule | foo | calls.rb:510:15:512:7 | foo | -| calls.rb:515:1:528:3 | ProtectedMethods | bar | calls.rb:518:15:520:7 | bar | -| calls.rb:515:1:528:3 | ProtectedMethods | baz | calls.rb:522:5:527:7 | baz | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | baz | calls.rb:535:5:538:7 | baz | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | m1 | calls.rb:423:9:425:11 | m1 | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | m2 | calls.rb:428:5:440:7 | m2 | +| calls.rb:484:1:490:3 | ExtendSingletonMethod | singleton | calls.rb:485:5:487:7 | singleton | +| calls.rb:513:1:517:3 | ProtectedMethodInModule | foo | calls.rb:514:15:516:7 | foo | +| calls.rb:519:1:532:3 | ProtectedMethods | bar | calls.rb:522:15:524:7 | bar | +| calls.rb:519:1:532:3 | ProtectedMethods | baz | calls.rb:526:5:531:7 | baz | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | baz | calls.rb:539:5:542:7 | baz | | hello.rb:1:1:8:3 | EnglishWords | hello | hello.rb:2:5:4:7 | hello | | hello.rb:1:1:8:3 | EnglishWords | world | hello.rb:5:5:7:7 | world | | hello.rb:11:1:16:3 | Greeting | message | hello.rb:13:5:15:7 | message | @@ -326,68 +326,68 @@ lookupMethod | calls.rb:377:1:397:3 | SingletonOverride1 | private_on_main | calls.rb:185:1:186:3 | private_on_main | | calls.rb:377:1:397:3 | SingletonOverride1 | puts | calls.rb:102:5:102:30 | puts | | calls.rb:377:1:397:3 | SingletonOverride1 | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:402:1:412:3 | SingletonOverride2 | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:402:1:412:3 | SingletonOverride2 | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:402:1:412:3 | SingletonOverride2 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:402:1:412:3 | SingletonOverride2 | create | calls.rb:278:1:286:3 | create | -| calls.rb:402:1:412:3 | SingletonOverride2 | foo | calls.rb:1:1:3:3 | foo | -| calls.rb:402:1:412:3 | SingletonOverride2 | foo | calls.rb:85:1:89:3 | foo | -| calls.rb:402:1:412:3 | SingletonOverride2 | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:402:1:412:3 | SingletonOverride2 | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:402:1:412:3 | SingletonOverride2 | new | calls.rb:117:5:117:16 | new | -| calls.rb:402:1:412:3 | SingletonOverride2 | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:402:1:412:3 | SingletonOverride2 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:402:1:412:3 | SingletonOverride2 | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:402:1:412:3 | SingletonOverride2 | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:402:1:412:3 | SingletonOverride2 | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | create | calls.rb:278:1:286:3 | create | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | foo | calls.rb:1:1:3:3 | foo | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | foo | calls.rb:85:1:89:3 | foo | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | m1 | calls.rb:419:9:421:11 | m1 | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | m2 | calls.rb:424:5:436:7 | m2 | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | new | calls.rb:117:5:117:16 | new | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:480:1:486:3 | ExtendSingletonMethod | singleton | calls.rb:481:5:483:7 | singleton | -| calls.rb:509:1:513:3 | ProtectedMethodInModule | foo | calls.rb:510:15:512:7 | foo | -| calls.rb:515:1:528:3 | ProtectedMethods | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:515:1:528:3 | ProtectedMethods | bar | calls.rb:518:15:520:7 | bar | -| calls.rb:515:1:528:3 | ProtectedMethods | baz | calls.rb:522:5:527:7 | baz | -| calls.rb:515:1:528:3 | ProtectedMethods | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:515:1:528:3 | ProtectedMethods | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:515:1:528:3 | ProtectedMethods | create | calls.rb:278:1:286:3 | create | -| calls.rb:515:1:528:3 | ProtectedMethods | foo | calls.rb:510:15:512:7 | foo | -| calls.rb:515:1:528:3 | ProtectedMethods | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:515:1:528:3 | ProtectedMethods | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:515:1:528:3 | ProtectedMethods | new | calls.rb:117:5:117:16 | new | -| calls.rb:515:1:528:3 | ProtectedMethods | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:515:1:528:3 | ProtectedMethods | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:515:1:528:3 | ProtectedMethods | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:515:1:528:3 | ProtectedMethods | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:515:1:528:3 | ProtectedMethods | to_s | calls.rb:172:5:173:7 | to_s | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | add_singleton | calls.rb:367:1:371:3 | add_singleton | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | bar | calls.rb:518:15:520:7 | bar | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | baz | calls.rb:535:5:538:7 | baz | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | call_block | calls.rb:81:1:83:3 | call_block | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | create | calls.rb:278:1:286:3 | create | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | foo | calls.rb:510:15:512:7 | foo | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | funny | calls.rb:140:1:142:3 | funny | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | indirect | calls.rb:158:1:160:3 | indirect | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | new | calls.rb:117:5:117:16 | new | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | optional_arg | calls.rb:76:1:79:3 | optional_arg | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | private_on_main | calls.rb:185:1:186:3 | private_on_main | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | puts | calls.rb:102:5:102:30 | puts | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:404:1:414:3 | SingletonOverride2 | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:404:1:414:3 | SingletonOverride2 | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:404:1:414:3 | SingletonOverride2 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:404:1:414:3 | SingletonOverride2 | create | calls.rb:278:1:286:3 | create | +| calls.rb:404:1:414:3 | SingletonOverride2 | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:404:1:414:3 | SingletonOverride2 | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:404:1:414:3 | SingletonOverride2 | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:404:1:414:3 | SingletonOverride2 | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:404:1:414:3 | SingletonOverride2 | new | calls.rb:117:5:117:16 | new | +| calls.rb:404:1:414:3 | SingletonOverride2 | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:404:1:414:3 | SingletonOverride2 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:404:1:414:3 | SingletonOverride2 | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:404:1:414:3 | SingletonOverride2 | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:404:1:414:3 | SingletonOverride2 | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | create | calls.rb:278:1:286:3 | create | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | foo | calls.rb:1:1:3:3 | foo | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | foo | calls.rb:85:1:89:3 | foo | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | m1 | calls.rb:423:9:425:11 | m1 | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | m2 | calls.rb:428:5:440:7 | m2 | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | new | calls.rb:117:5:117:16 | new | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:484:1:490:3 | ExtendSingletonMethod | singleton | calls.rb:485:5:487:7 | singleton | +| calls.rb:513:1:517:3 | ProtectedMethodInModule | foo | calls.rb:514:15:516:7 | foo | +| calls.rb:519:1:532:3 | ProtectedMethods | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:519:1:532:3 | ProtectedMethods | bar | calls.rb:522:15:524:7 | bar | +| calls.rb:519:1:532:3 | ProtectedMethods | baz | calls.rb:526:5:531:7 | baz | +| calls.rb:519:1:532:3 | ProtectedMethods | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:519:1:532:3 | ProtectedMethods | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:519:1:532:3 | ProtectedMethods | create | calls.rb:278:1:286:3 | create | +| calls.rb:519:1:532:3 | ProtectedMethods | foo | calls.rb:514:15:516:7 | foo | +| calls.rb:519:1:532:3 | ProtectedMethods | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:519:1:532:3 | ProtectedMethods | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:519:1:532:3 | ProtectedMethods | new | calls.rb:117:5:117:16 | new | +| calls.rb:519:1:532:3 | ProtectedMethods | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:519:1:532:3 | ProtectedMethods | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:519:1:532:3 | ProtectedMethods | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:519:1:532:3 | ProtectedMethods | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:519:1:532:3 | ProtectedMethods | to_s | calls.rb:172:5:173:7 | to_s | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | add_singleton | calls.rb:367:1:371:3 | add_singleton | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | bar | calls.rb:522:15:524:7 | bar | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | baz | calls.rb:539:5:542:7 | baz | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | call_block | calls.rb:81:1:83:3 | call_block | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | call_instance_m | calls.rb:39:1:41:3 | call_instance_m | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | create | calls.rb:278:1:286:3 | create | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | foo | calls.rb:514:15:516:7 | foo | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | funny | calls.rb:140:1:142:3 | funny | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | indirect | calls.rb:158:1:160:3 | indirect | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | new | calls.rb:117:5:117:16 | new | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | optional_arg | calls.rb:76:1:79:3 | optional_arg | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | private_on_main | calls.rb:185:1:186:3 | private_on_main | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | puts | calls.rb:102:5:102:30 | puts | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | to_s | calls.rb:172:5:173:7 | to_s | | file://:0:0:0:0 | Class | include | calls.rb:108:5:110:7 | include | | file://:0:0:0:0 | Class | module_eval | calls.rb:107:5:107:24 | module_eval | | file://:0:0:0:0 | Class | new | calls.rb:117:5:117:16 | new | @@ -765,73 +765,73 @@ enclosingMethod | calls.rb:389:15:389:43 | SingletonOverride1#singleton2 | calls.rb:388:5:390:7 | singleton2 | | calls.rb:393:9:393:18 | call to singleton2 | calls.rb:392:5:394:7 | call_singleton2 | | calls.rb:393:9:393:18 | self | calls.rb:392:5:394:7 | call_singleton2 | -| calls.rb:405:13:405:48 | call to puts | calls.rb:404:9:406:11 | singleton1 | -| calls.rb:405:13:405:48 | self | calls.rb:404:9:406:11 | singleton1 | -| calls.rb:405:18:405:48 | "SingletonOverride2#singleton1" | calls.rb:404:9:406:11 | singleton1 | -| calls.rb:405:19:405:47 | SingletonOverride2#singleton1 | calls.rb:404:9:406:11 | singleton1 | -| calls.rb:410:9:410:44 | call to puts | calls.rb:409:5:411:7 | singleton2 | -| calls.rb:410:9:410:44 | self | calls.rb:409:5:411:7 | singleton2 | -| calls.rb:410:14:410:44 | "SingletonOverride2#singleton2" | calls.rb:409:5:411:7 | singleton2 | -| calls.rb:410:15:410:43 | SingletonOverride2#singleton2 | calls.rb:409:5:411:7 | singleton2 | -| calls.rb:420:13:420:48 | call to puts | calls.rb:419:9:421:11 | m1 | -| calls.rb:420:13:420:48 | self | calls.rb:419:9:421:11 | m1 | -| calls.rb:420:18:420:48 | "ConditionalInstanceMethods#m1" | calls.rb:419:9:421:11 | m1 | -| calls.rb:420:19:420:47 | ConditionalInstanceMethods#m1 | calls.rb:419:9:421:11 | m1 | -| calls.rb:425:9:425:44 | call to puts | calls.rb:424:5:436:7 | m2 | -| calls.rb:425:9:425:44 | self | calls.rb:424:5:436:7 | m2 | -| calls.rb:425:14:425:44 | "ConditionalInstanceMethods#m2" | calls.rb:424:5:436:7 | m2 | -| calls.rb:425:15:425:43 | ConditionalInstanceMethods#m2 | calls.rb:424:5:436:7 | m2 | -| calls.rb:427:9:433:11 | m3 | calls.rb:424:5:436:7 | m2 | -| calls.rb:428:13:428:48 | call to puts | calls.rb:427:9:433:11 | m3 | -| calls.rb:428:13:428:48 | self | calls.rb:427:9:433:11 | m3 | -| calls.rb:428:18:428:48 | "ConditionalInstanceMethods#m3" | calls.rb:427:9:433:11 | m3 | -| calls.rb:428:19:428:47 | ConditionalInstanceMethods#m3 | calls.rb:427:9:433:11 | m3 | -| calls.rb:430:13:432:15 | m4 | calls.rb:427:9:433:11 | m3 | -| calls.rb:431:17:431:52 | call to puts | calls.rb:430:13:432:15 | m4 | -| calls.rb:431:17:431:52 | self | calls.rb:430:13:432:15 | m4 | -| calls.rb:431:22:431:52 | "ConditionalInstanceMethods#m4" | calls.rb:430:13:432:15 | m4 | -| calls.rb:431:23:431:51 | ConditionalInstanceMethods#m4 | calls.rb:430:13:432:15 | m4 | -| calls.rb:435:9:435:10 | call to m3 | calls.rb:424:5:436:7 | m2 | -| calls.rb:435:9:435:10 | self | calls.rb:424:5:436:7 | m2 | -| calls.rb:441:17:441:40 | call to puts | calls.rb:440:13:442:15 | m5 | -| calls.rb:441:17:441:40 | self | calls.rb:440:13:442:15 | m5 | -| calls.rb:441:22:441:40 | "AnonymousClass#m5" | calls.rb:440:13:442:15 | m5 | -| calls.rb:441:23:441:39 | AnonymousClass#m5 | calls.rb:440:13:442:15 | m5 | -| calls.rb:457:13:457:22 | call to puts | calls.rb:456:9:458:11 | foo | -| calls.rb:457:13:457:22 | self | calls.rb:456:9:458:11 | foo | -| calls.rb:457:18:457:22 | "foo" | calls.rb:456:9:458:11 | foo | -| calls.rb:457:19:457:21 | foo | calls.rb:456:9:458:11 | foo | -| calls.rb:463:13:463:22 | call to puts | calls.rb:462:9:464:11 | bar | -| calls.rb:463:13:463:22 | self | calls.rb:462:9:464:11 | bar | -| calls.rb:463:18:463:22 | "bar" | calls.rb:462:9:464:11 | bar | -| calls.rb:463:19:463:21 | bar | calls.rb:462:9:464:11 | bar | -| calls.rb:482:9:482:46 | call to puts | calls.rb:481:5:483:7 | singleton | -| calls.rb:482:9:482:46 | self | calls.rb:481:5:483:7 | singleton | -| calls.rb:482:14:482:46 | "ExtendSingletonMethod#singleton" | calls.rb:481:5:483:7 | singleton | -| calls.rb:482:15:482:45 | ExtendSingletonMethod#singleton | calls.rb:481:5:483:7 | singleton | -| calls.rb:511:9:511:42 | call to puts | calls.rb:510:15:512:7 | foo | -| calls.rb:511:9:511:42 | self | calls.rb:510:15:512:7 | foo | -| calls.rb:511:14:511:42 | "ProtectedMethodInModule#foo" | calls.rb:510:15:512:7 | foo | -| calls.rb:511:15:511:41 | ProtectedMethodInModule#foo | calls.rb:510:15:512:7 | foo | -| calls.rb:519:9:519:35 | call to puts | calls.rb:518:15:520:7 | bar | -| calls.rb:519:9:519:35 | self | calls.rb:518:15:520:7 | bar | -| calls.rb:519:14:519:35 | "ProtectedMethods#bar" | calls.rb:518:15:520:7 | bar | -| calls.rb:519:15:519:34 | ProtectedMethods#bar | calls.rb:518:15:520:7 | bar | -| calls.rb:523:9:523:11 | call to foo | calls.rb:522:5:527:7 | baz | -| calls.rb:523:9:523:11 | self | calls.rb:522:5:527:7 | baz | -| calls.rb:524:9:524:11 | call to bar | calls.rb:522:5:527:7 | baz | -| calls.rb:524:9:524:11 | self | calls.rb:522:5:527:7 | baz | -| calls.rb:525:9:525:24 | ProtectedMethods | calls.rb:522:5:527:7 | baz | -| calls.rb:525:9:525:28 | call to new | calls.rb:522:5:527:7 | baz | -| calls.rb:525:9:525:32 | call to foo | calls.rb:522:5:527:7 | baz | -| calls.rb:526:9:526:24 | ProtectedMethods | calls.rb:522:5:527:7 | baz | -| calls.rb:526:9:526:28 | call to new | calls.rb:522:5:527:7 | baz | -| calls.rb:526:9:526:32 | call to bar | calls.rb:522:5:527:7 | baz | -| calls.rb:536:9:536:11 | call to foo | calls.rb:535:5:538:7 | baz | -| calls.rb:536:9:536:11 | self | calls.rb:535:5:538:7 | baz | -| calls.rb:537:9:537:27 | ProtectedMethodsSub | calls.rb:535:5:538:7 | baz | -| calls.rb:537:9:537:31 | call to new | calls.rb:535:5:538:7 | baz | -| calls.rb:537:9:537:35 | call to foo | calls.rb:535:5:538:7 | baz | +| calls.rb:407:13:407:48 | call to puts | calls.rb:406:9:408:11 | singleton1 | +| calls.rb:407:13:407:48 | self | calls.rb:406:9:408:11 | singleton1 | +| calls.rb:407:18:407:48 | "SingletonOverride2#singleton1" | calls.rb:406:9:408:11 | singleton1 | +| calls.rb:407:19:407:47 | SingletonOverride2#singleton1 | calls.rb:406:9:408:11 | singleton1 | +| calls.rb:412:9:412:44 | call to puts | calls.rb:411:5:413:7 | singleton2 | +| calls.rb:412:9:412:44 | self | calls.rb:411:5:413:7 | singleton2 | +| calls.rb:412:14:412:44 | "SingletonOverride2#singleton2" | calls.rb:411:5:413:7 | singleton2 | +| calls.rb:412:15:412:43 | SingletonOverride2#singleton2 | calls.rb:411:5:413:7 | singleton2 | +| calls.rb:424:13:424:48 | call to puts | calls.rb:423:9:425:11 | m1 | +| calls.rb:424:13:424:48 | self | calls.rb:423:9:425:11 | m1 | +| calls.rb:424:18:424:48 | "ConditionalInstanceMethods#m1" | calls.rb:423:9:425:11 | m1 | +| calls.rb:424:19:424:47 | ConditionalInstanceMethods#m1 | calls.rb:423:9:425:11 | m1 | +| calls.rb:429:9:429:44 | call to puts | calls.rb:428:5:440:7 | m2 | +| calls.rb:429:9:429:44 | self | calls.rb:428:5:440:7 | m2 | +| calls.rb:429:14:429:44 | "ConditionalInstanceMethods#m2" | calls.rb:428:5:440:7 | m2 | +| calls.rb:429:15:429:43 | ConditionalInstanceMethods#m2 | calls.rb:428:5:440:7 | m2 | +| calls.rb:431:9:437:11 | m3 | calls.rb:428:5:440:7 | m2 | +| calls.rb:432:13:432:48 | call to puts | calls.rb:431:9:437:11 | m3 | +| calls.rb:432:13:432:48 | self | calls.rb:431:9:437:11 | m3 | +| calls.rb:432:18:432:48 | "ConditionalInstanceMethods#m3" | calls.rb:431:9:437:11 | m3 | +| calls.rb:432:19:432:47 | ConditionalInstanceMethods#m3 | calls.rb:431:9:437:11 | m3 | +| calls.rb:434:13:436:15 | m4 | calls.rb:431:9:437:11 | m3 | +| calls.rb:435:17:435:52 | call to puts | calls.rb:434:13:436:15 | m4 | +| calls.rb:435:17:435:52 | self | calls.rb:434:13:436:15 | m4 | +| calls.rb:435:22:435:52 | "ConditionalInstanceMethods#m4" | calls.rb:434:13:436:15 | m4 | +| calls.rb:435:23:435:51 | ConditionalInstanceMethods#m4 | calls.rb:434:13:436:15 | m4 | +| calls.rb:439:9:439:10 | call to m3 | calls.rb:428:5:440:7 | m2 | +| calls.rb:439:9:439:10 | self | calls.rb:428:5:440:7 | m2 | +| calls.rb:445:17:445:40 | call to puts | calls.rb:444:13:446:15 | m5 | +| calls.rb:445:17:445:40 | self | calls.rb:444:13:446:15 | m5 | +| calls.rb:445:22:445:40 | "AnonymousClass#m5" | calls.rb:444:13:446:15 | m5 | +| calls.rb:445:23:445:39 | AnonymousClass#m5 | calls.rb:444:13:446:15 | m5 | +| calls.rb:461:13:461:22 | call to puts | calls.rb:460:9:462:11 | foo | +| calls.rb:461:13:461:22 | self | calls.rb:460:9:462:11 | foo | +| calls.rb:461:18:461:22 | "foo" | calls.rb:460:9:462:11 | foo | +| calls.rb:461:19:461:21 | foo | calls.rb:460:9:462:11 | foo | +| calls.rb:467:13:467:22 | call to puts | calls.rb:466:9:468:11 | bar | +| calls.rb:467:13:467:22 | self | calls.rb:466:9:468:11 | bar | +| calls.rb:467:18:467:22 | "bar" | calls.rb:466:9:468:11 | bar | +| calls.rb:467:19:467:21 | bar | calls.rb:466:9:468:11 | bar | +| calls.rb:486:9:486:46 | call to puts | calls.rb:485:5:487:7 | singleton | +| calls.rb:486:9:486:46 | self | calls.rb:485:5:487:7 | singleton | +| calls.rb:486:14:486:46 | "ExtendSingletonMethod#singleton" | calls.rb:485:5:487:7 | singleton | +| calls.rb:486:15:486:45 | ExtendSingletonMethod#singleton | calls.rb:485:5:487:7 | singleton | +| calls.rb:515:9:515:42 | call to puts | calls.rb:514:15:516:7 | foo | +| calls.rb:515:9:515:42 | self | calls.rb:514:15:516:7 | foo | +| calls.rb:515:14:515:42 | "ProtectedMethodInModule#foo" | calls.rb:514:15:516:7 | foo | +| calls.rb:515:15:515:41 | ProtectedMethodInModule#foo | calls.rb:514:15:516:7 | foo | +| calls.rb:523:9:523:35 | call to puts | calls.rb:522:15:524:7 | bar | +| calls.rb:523:9:523:35 | self | calls.rb:522:15:524:7 | bar | +| calls.rb:523:14:523:35 | "ProtectedMethods#bar" | calls.rb:522:15:524:7 | bar | +| calls.rb:523:15:523:34 | ProtectedMethods#bar | calls.rb:522:15:524:7 | bar | +| calls.rb:527:9:527:11 | call to foo | calls.rb:526:5:531:7 | baz | +| calls.rb:527:9:527:11 | self | calls.rb:526:5:531:7 | baz | +| calls.rb:528:9:528:11 | call to bar | calls.rb:526:5:531:7 | baz | +| calls.rb:528:9:528:11 | self | calls.rb:526:5:531:7 | baz | +| calls.rb:529:9:529:24 | ProtectedMethods | calls.rb:526:5:531:7 | baz | +| calls.rb:529:9:529:28 | call to new | calls.rb:526:5:531:7 | baz | +| calls.rb:529:9:529:32 | call to foo | calls.rb:526:5:531:7 | baz | +| calls.rb:530:9:530:24 | ProtectedMethods | calls.rb:526:5:531:7 | baz | +| calls.rb:530:9:530:28 | call to new | calls.rb:526:5:531:7 | baz | +| calls.rb:530:9:530:32 | call to bar | calls.rb:526:5:531:7 | baz | +| calls.rb:540:9:540:11 | call to foo | calls.rb:539:5:542:7 | baz | +| calls.rb:540:9:540:11 | self | calls.rb:539:5:542:7 | baz | +| calls.rb:541:9:541:27 | ProtectedMethodsSub | calls.rb:539:5:542:7 | baz | +| calls.rb:541:9:541:31 | call to new | calls.rb:539:5:542:7 | baz | +| calls.rb:541:9:541:35 | call to foo | calls.rb:539:5:542:7 | baz | | hello.rb:3:9:3:22 | return | hello.rb:2:5:4:7 | hello | | hello.rb:3:16:3:22 | "hello" | hello.rb:2:5:4:7 | hello | | hello.rb:3:17:3:21 | hello | hello.rb:2:5:4:7 | hello | diff --git a/ruby/ql/test/library-tests/modules/modules.expected b/ruby/ql/test/library-tests/modules/modules.expected index 2ef6ed4405c..93bcb04aec5 100644 --- a/ruby/ql/test/library-tests/modules/modules.expected +++ b/ruby/ql/test/library-tests/modules/modules.expected @@ -18,14 +18,14 @@ getModule | calls.rb:331:1:335:3 | C2 | | calls.rb:337:1:341:3 | C3 | | calls.rb:377:1:397:3 | SingletonOverride1 | -| calls.rb:402:1:412:3 | SingletonOverride2 | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:480:1:486:3 | ExtendSingletonMethod | -| calls.rb:490:1:492:3 | ExtendSingletonMethod2 | -| calls.rb:496:1:497:3 | ExtendSingletonMethod3 | -| calls.rb:509:1:513:3 | ProtectedMethodInModule | -| calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | +| calls.rb:404:1:414:3 | SingletonOverride2 | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:484:1:490:3 | ExtendSingletonMethod | +| calls.rb:494:1:496:3 | ExtendSingletonMethod2 | +| calls.rb:500:1:501:3 | ExtendSingletonMethod3 | +| calls.rb:513:1:517:3 | ProtectedMethodInModule | +| calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | | file://:0:0:0:0 | BasicObject | | file://:0:0:0:0 | Class | | file://:0:0:0:0 | Complex | @@ -84,7 +84,7 @@ getADeclaration | calls.rb:96:1:98:3 | String | calls.rb:96:1:98:3 | String | | calls.rb:100:1:103:3 | Kernel | calls.rb:100:1:103:3 | Kernel | | calls.rb:105:1:113:3 | Module | calls.rb:105:1:113:3 | Module | -| calls.rb:115:1:118:3 | Object | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:115:1:118:3 | Object | calls.rb:1:1:550:40 | calls.rb | | calls.rb:115:1:118:3 | Object | calls.rb:115:1:118:3 | Object | | calls.rb:115:1:118:3 | Object | hello.rb:1:1:22:3 | hello.rb | | calls.rb:115:1:118:3 | Object | modules.rb:1:1:129:4 | modules.rb | @@ -102,14 +102,14 @@ getADeclaration | calls.rb:331:1:335:3 | C2 | calls.rb:331:1:335:3 | C2 | | calls.rb:337:1:341:3 | C3 | calls.rb:337:1:341:3 | C3 | | calls.rb:377:1:397:3 | SingletonOverride1 | calls.rb:377:1:397:3 | SingletonOverride1 | -| calls.rb:402:1:412:3 | SingletonOverride2 | calls.rb:402:1:412:3 | SingletonOverride2 | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:480:1:486:3 | ExtendSingletonMethod | calls.rb:480:1:486:3 | ExtendSingletonMethod | -| calls.rb:490:1:492:3 | ExtendSingletonMethod2 | calls.rb:490:1:492:3 | ExtendSingletonMethod2 | -| calls.rb:496:1:497:3 | ExtendSingletonMethod3 | calls.rb:496:1:497:3 | ExtendSingletonMethod3 | -| calls.rb:509:1:513:3 | ProtectedMethodInModule | calls.rb:509:1:513:3 | ProtectedMethodInModule | -| calls.rb:515:1:528:3 | ProtectedMethods | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | calls.rb:534:1:539:3 | ProtectedMethodsSub | +| calls.rb:404:1:414:3 | SingletonOverride2 | calls.rb:404:1:414:3 | SingletonOverride2 | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:484:1:490:3 | ExtendSingletonMethod | calls.rb:484:1:490:3 | ExtendSingletonMethod | +| calls.rb:494:1:496:3 | ExtendSingletonMethod2 | calls.rb:494:1:496:3 | ExtendSingletonMethod2 | +| calls.rb:500:1:501:3 | ExtendSingletonMethod3 | calls.rb:500:1:501:3 | ExtendSingletonMethod3 | +| calls.rb:513:1:517:3 | ProtectedMethodInModule | calls.rb:513:1:517:3 | ProtectedMethodInModule | +| calls.rb:519:1:532:3 | ProtectedMethods | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | calls.rb:538:1:543:3 | ProtectedMethodsSub | | hello.rb:1:1:8:3 | EnglishWords | hello.rb:1:1:8:3 | EnglishWords | | hello.rb:11:1:16:3 | Greeting | hello.rb:11:1:16:3 | Greeting | | hello.rb:18:1:22:3 | HelloWorld | hello.rb:18:1:22:3 | HelloWorld | @@ -171,10 +171,10 @@ getSuperClass | calls.rb:331:1:335:3 | C2 | calls.rb:325:1:329:3 | C1 | | calls.rb:337:1:341:3 | C3 | calls.rb:331:1:335:3 | C2 | | calls.rb:377:1:397:3 | SingletonOverride1 | calls.rb:115:1:118:3 | Object | -| calls.rb:402:1:412:3 | SingletonOverride2 | calls.rb:377:1:397:3 | SingletonOverride1 | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | calls.rb:115:1:118:3 | Object | -| calls.rb:515:1:528:3 | ProtectedMethods | calls.rb:115:1:118:3 | Object | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | calls.rb:515:1:528:3 | ProtectedMethods | +| calls.rb:404:1:414:3 | SingletonOverride2 | calls.rb:377:1:397:3 | SingletonOverride1 | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | calls.rb:115:1:118:3 | Object | +| calls.rb:519:1:532:3 | ProtectedMethods | calls.rb:115:1:118:3 | Object | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | calls.rb:519:1:532:3 | ProtectedMethods | | file://:0:0:0:0 | Class | calls.rb:105:1:113:3 | Module | | file://:0:0:0:0 | Complex | file://:0:0:0:0 | Numeric | | file://:0:0:0:0 | FalseClass | calls.rb:115:1:118:3 | Object | @@ -206,7 +206,7 @@ getAPrependedModule getAnIncludedModule | calls.rb:43:1:58:3 | C | calls.rb:21:1:34:3 | M | | calls.rb:115:1:118:3 | Object | calls.rb:100:1:103:3 | Kernel | -| calls.rb:515:1:528:3 | ProtectedMethods | calls.rb:509:1:513:3 | ProtectedMethodInModule | +| calls.rb:519:1:532:3 | ProtectedMethods | calls.rb:513:1:517:3 | ProtectedMethodInModule | | hello.rb:11:1:16:3 | Greeting | hello.rb:1:1:8:3 | EnglishWords | | modules.rb:88:1:93:3 | IncludeTest | modules.rb:63:1:81:3 | Test | | modules.rb:95:1:99:3 | IncludeTest2 | modules.rb:63:1:81:3 | Test | @@ -258,41 +258,45 @@ resolveConstantReadAccess | calls.rb:373:6:373:7 | C1 | C1 | | calls.rb:399:1:399:18 | SingletonOverride1 | SingletonOverride1 | | calls.rb:400:1:400:18 | SingletonOverride1 | SingletonOverride1 | -| calls.rb:402:28:402:45 | SingletonOverride1 | SingletonOverride1 | -| calls.rb:414:1:414:18 | SingletonOverride2 | SingletonOverride2 | -| calls.rb:415:1:415:18 | SingletonOverride2 | SingletonOverride2 | -| calls.rb:439:9:439:13 | Class | Class | -| calls.rb:447:1:447:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | -| calls.rb:448:1:448:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | -| calls.rb:449:1:449:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | -| calls.rb:450:1:450:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | +| calls.rb:401:1:401:18 | SingletonOverride1 | SingletonOverride1 | +| calls.rb:402:1:402:18 | SingletonOverride1 | SingletonOverride1 | +| calls.rb:404:28:404:45 | SingletonOverride1 | SingletonOverride1 | +| calls.rb:416:1:416:18 | SingletonOverride2 | SingletonOverride2 | +| calls.rb:417:1:417:18 | SingletonOverride2 | SingletonOverride2 | +| calls.rb:418:1:418:18 | SingletonOverride2 | SingletonOverride2 | +| calls.rb:419:1:419:18 | SingletonOverride2 | SingletonOverride2 | +| calls.rb:443:9:443:13 | Class | Class | | calls.rb:451:1:451:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | | calls.rb:452:1:452:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | -| calls.rb:454:27:454:31 | Class | Class | -| calls.rb:455:5:455:11 | Array | Array | -| calls.rb:461:5:461:9 | Class | Class | -| calls.rb:467:5:467:11 | Array | Array | -| calls.rb:488:1:488:21 | ExtendSingletonMethod | ExtendSingletonMethod | -| calls.rb:491:12:491:32 | ExtendSingletonMethod | ExtendSingletonMethod | -| calls.rb:494:1:494:22 | ExtendSingletonMethod2 | ExtendSingletonMethod2 | -| calls.rb:499:1:499:22 | ExtendSingletonMethod3 | ExtendSingletonMethod3 | -| calls.rb:499:31:499:51 | ExtendSingletonMethod | ExtendSingletonMethod | -| calls.rb:501:1:501:22 | ExtendSingletonMethod3 | ExtendSingletonMethod3 | -| calls.rb:505:12:505:32 | ExtendSingletonMethod | ExtendSingletonMethod | -| calls.rb:516:13:516:35 | ProtectedMethodInModule | ProtectedMethodInModule | -| calls.rb:525:9:525:24 | ProtectedMethods | ProtectedMethods | -| calls.rb:526:9:526:24 | ProtectedMethods | ProtectedMethods | -| calls.rb:530:1:530:16 | ProtectedMethods | ProtectedMethods | -| calls.rb:531:1:531:16 | ProtectedMethods | ProtectedMethods | -| calls.rb:532:1:532:16 | ProtectedMethods | ProtectedMethods | -| calls.rb:534:29:534:44 | ProtectedMethods | ProtectedMethods | -| calls.rb:537:9:537:27 | ProtectedMethodsSub | ProtectedMethodsSub | -| calls.rb:541:1:541:19 | ProtectedMethodsSub | ProtectedMethodsSub | -| calls.rb:542:1:542:19 | ProtectedMethodsSub | ProtectedMethodsSub | -| calls.rb:543:1:543:19 | ProtectedMethodsSub | ProtectedMethodsSub | -| calls.rb:545:1:545:7 | Array | Array | -| calls.rb:545:2:545:2 | C | C | -| calls.rb:546:1:546:13 | Array | Array | +| calls.rb:453:1:453:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | +| calls.rb:454:1:454:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | +| calls.rb:455:1:455:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | +| calls.rb:456:1:456:26 | ConditionalInstanceMethods | ConditionalInstanceMethods | +| calls.rb:458:27:458:31 | Class | Class | +| calls.rb:459:5:459:11 | Array | Array | +| calls.rb:465:5:465:9 | Class | Class | +| calls.rb:471:5:471:11 | Array | Array | +| calls.rb:492:1:492:21 | ExtendSingletonMethod | ExtendSingletonMethod | +| calls.rb:495:12:495:32 | ExtendSingletonMethod | ExtendSingletonMethod | +| calls.rb:498:1:498:22 | ExtendSingletonMethod2 | ExtendSingletonMethod2 | +| calls.rb:503:1:503:22 | ExtendSingletonMethod3 | ExtendSingletonMethod3 | +| calls.rb:503:31:503:51 | ExtendSingletonMethod | ExtendSingletonMethod | +| calls.rb:505:1:505:22 | ExtendSingletonMethod3 | ExtendSingletonMethod3 | +| calls.rb:509:12:509:32 | ExtendSingletonMethod | ExtendSingletonMethod | +| calls.rb:520:13:520:35 | ProtectedMethodInModule | ProtectedMethodInModule | +| calls.rb:529:9:529:24 | ProtectedMethods | ProtectedMethods | +| calls.rb:530:9:530:24 | ProtectedMethods | ProtectedMethods | +| calls.rb:534:1:534:16 | ProtectedMethods | ProtectedMethods | +| calls.rb:535:1:535:16 | ProtectedMethods | ProtectedMethods | +| calls.rb:536:1:536:16 | ProtectedMethods | ProtectedMethods | +| calls.rb:538:29:538:44 | ProtectedMethods | ProtectedMethods | +| calls.rb:541:9:541:27 | ProtectedMethodsSub | ProtectedMethodsSub | +| calls.rb:545:1:545:19 | ProtectedMethodsSub | ProtectedMethodsSub | +| calls.rb:546:1:546:19 | ProtectedMethodsSub | ProtectedMethodsSub | +| calls.rb:547:1:547:19 | ProtectedMethodsSub | ProtectedMethodsSub | +| calls.rb:549:1:549:7 | Array | Array | +| calls.rb:549:2:549:2 | C | C | +| calls.rb:550:1:550:13 | Array | Array | | hello.rb:12:13:12:24 | EnglishWords | EnglishWords | | hello.rb:18:20:18:27 | Greeting | Greeting | | modules.rb:48:8:48:10 | Foo | Foo | @@ -348,15 +352,15 @@ resolveConstantWriteAccess | calls.rb:331:1:335:3 | C2 | C2 | | calls.rb:337:1:341:3 | C3 | C3 | | calls.rb:377:1:397:3 | SingletonOverride1 | SingletonOverride1 | -| calls.rb:402:1:412:3 | SingletonOverride2 | SingletonOverride2 | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | ConditionalInstanceMethods | -| calls.rb:454:1:454:23 | EsotericInstanceMethods | EsotericInstanceMethods | -| calls.rb:480:1:486:3 | ExtendSingletonMethod | ExtendSingletonMethod | -| calls.rb:490:1:492:3 | ExtendSingletonMethod2 | ExtendSingletonMethod2 | -| calls.rb:496:1:497:3 | ExtendSingletonMethod3 | ExtendSingletonMethod3 | -| calls.rb:509:1:513:3 | ProtectedMethodInModule | ProtectedMethodInModule | -| calls.rb:515:1:528:3 | ProtectedMethods | ProtectedMethods | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | ProtectedMethodsSub | +| calls.rb:404:1:414:3 | SingletonOverride2 | SingletonOverride2 | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | ConditionalInstanceMethods | +| calls.rb:458:1:458:23 | EsotericInstanceMethods | EsotericInstanceMethods | +| calls.rb:484:1:490:3 | ExtendSingletonMethod | ExtendSingletonMethod | +| calls.rb:494:1:496:3 | ExtendSingletonMethod2 | ExtendSingletonMethod2 | +| calls.rb:500:1:501:3 | ExtendSingletonMethod3 | ExtendSingletonMethod3 | +| calls.rb:513:1:517:3 | ProtectedMethodInModule | ProtectedMethodInModule | +| calls.rb:519:1:532:3 | ProtectedMethods | ProtectedMethods | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | ProtectedMethodsSub | | hello.rb:1:1:8:3 | EnglishWords | EnglishWords | | hello.rb:11:1:16:3 | Greeting | Greeting | | hello.rb:18:1:22:3 | HelloWorld | HelloWorld | @@ -411,32 +415,32 @@ resolveConstantWriteAccess | private.rb:82:1:94:3 | PrivateOverride1 | PrivateOverride1 | | private.rb:96:1:102:3 | PrivateOverride2 | PrivateOverride2 | enclosingModule -| calls.rb:1:1:3:3 | foo | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:2:5:2:14 | call to puts | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:2:5:2:14 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:2:10:2:14 | "foo" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:2:11:2:13 | foo | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:5:1:5:3 | call to foo | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:5:1:5:3 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:7:1:9:3 | bar | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:7:5:7:8 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:8:5:8:15 | call to puts | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:8:5:8:15 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:8:10:8:15 | "bar1" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:8:11:8:14 | bar1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:11:1:11:4 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:11:1:11:8 | call to bar | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:13:1:15:3 | bar | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:13:5:13:8 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:14:5:14:15 | call to puts | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:14:5:14:15 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:14:10:14:15 | "bar2" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:14:11:14:14 | bar2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:17:1:17:4 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:17:1:17:8 | call to bar | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:19:1:19:4 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:19:1:19:8 | call to foo | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:21:1:34:3 | M | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:1:1:3:3 | foo | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:2:5:2:14 | call to puts | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:2:5:2:14 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:2:10:2:14 | "foo" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:2:11:2:13 | foo | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:5:1:5:3 | call to foo | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:5:1:5:3 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:7:1:9:3 | bar | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:7:5:7:8 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:8:5:8:15 | call to puts | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:8:5:8:15 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:8:10:8:15 | "bar1" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:8:11:8:14 | bar1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:11:1:11:4 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:11:1:11:8 | call to bar | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:13:1:15:3 | bar | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:13:5:13:8 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:14:5:14:15 | call to puts | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:14:5:14:15 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:14:10:14:15 | "bar2" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:14:11:14:14 | bar2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:17:1:17:4 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:17:1:17:8 | call to bar | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:19:1:19:4 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:19:1:19:8 | call to foo | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:21:1:34:3 | M | calls.rb:1:1:550:40 | calls.rb | | calls.rb:22:5:24:7 | instance_m | calls.rb:21:1:34:3 | M | | calls.rb:23:9:23:19 | call to singleton_m | calls.rb:21:1:34:3 | M | | calls.rb:23:9:23:19 | self | calls.rb:21:1:34:3 | M | @@ -452,14 +456,14 @@ enclosingModule | calls.rb:32:5:32:15 | self | calls.rb:21:1:34:3 | M | | calls.rb:33:5:33:8 | self | calls.rb:21:1:34:3 | M | | calls.rb:33:5:33:20 | call to singleton_m | calls.rb:21:1:34:3 | M | -| calls.rb:36:1:36:1 | M | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:36:1:36:12 | call to instance_m | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:37:1:37:1 | M | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:37:1:37:13 | call to singleton_m | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:39:1:41:3 | call_instance_m | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:40:5:40:14 | call to instance_m | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:40:5:40:14 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:43:1:58:3 | C | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:36:1:36:1 | M | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:36:1:36:12 | call to instance_m | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:37:1:37:1 | M | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:37:1:37:13 | call to singleton_m | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:39:1:41:3 | call_instance_m | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:40:5:40:14 | call to instance_m | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:40:5:40:14 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:43:1:58:3 | C | calls.rb:1:1:550:40 | calls.rb | | calls.rb:44:5:44:13 | call to include | calls.rb:43:1:58:3 | C | | calls.rb:44:5:44:13 | self | calls.rb:43:1:58:3 | C | | calls.rb:44:13:44:13 | M | calls.rb:43:1:58:3 | C | @@ -480,66 +484,66 @@ enclosingModule | calls.rb:55:9:55:19 | self | calls.rb:43:1:58:3 | C | | calls.rb:56:9:56:12 | self | calls.rb:43:1:58:3 | C | | calls.rb:56:9:56:24 | call to singleton_m | calls.rb:43:1:58:3 | C | -| calls.rb:60:1:60:1 | c | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:60:1:60:9 | ... = ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:60:5:60:5 | C | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:60:5:60:9 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:61:1:61:1 | c | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:61:1:61:5 | call to baz | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:62:1:62:1 | c | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:62:1:62:13 | call to singleton_m | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:63:1:63:1 | c | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:63:1:63:12 | call to instance_m | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:65:1:69:3 | D | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:65:11:65:11 | C | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:60:1:60:1 | c | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:60:1:60:9 | ... = ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:60:5:60:5 | C | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:60:5:60:9 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:61:1:61:1 | c | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:61:1:61:5 | call to baz | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:62:1:62:1 | c | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:62:1:62:13 | call to singleton_m | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:63:1:63:1 | c | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:63:1:63:12 | call to instance_m | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:65:1:69:3 | D | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:65:11:65:11 | C | calls.rb:1:1:550:40 | calls.rb | | calls.rb:66:5:68:7 | baz | calls.rb:65:1:69:3 | D | | calls.rb:67:9:67:13 | call to super | calls.rb:65:1:69:3 | D | -| calls.rb:71:1:71:1 | d | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:71:1:71:9 | ... = ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:71:5:71:5 | D | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:71:5:71:9 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:72:1:72:1 | d | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:72:1:72:5 | call to baz | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:73:1:73:1 | d | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:73:1:73:13 | call to singleton_m | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:74:1:74:1 | d | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:74:1:74:12 | call to instance_m | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:76:1:79:3 | optional_arg | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:76:18:76:18 | a | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:76:18:76:18 | a | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:76:22:76:22 | 4 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:76:25:76:25 | b | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:76:25:76:25 | b | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:76:28:76:28 | 5 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:77:5:77:5 | a | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:77:5:77:16 | call to bit_length | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:78:5:78:5 | b | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:78:5:78:16 | call to bit_length | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:81:1:83:3 | call_block | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:82:5:82:11 | yield ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:82:11:82:11 | 1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:85:1:89:3 | foo | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:86:5:86:7 | var | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:86:5:86:18 | ... = ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:86:11:86:14 | Hash | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:86:11:86:18 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:87:5:87:7 | var | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:87:5:87:10 | ...[...] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:87:9:87:9 | 1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:88:5:88:29 | call to call_block | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:88:5:88:29 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:88:16:88:29 | { ... } | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:88:19:88:19 | x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:88:19:88:19 | x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:88:22:88:24 | var | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:88:22:88:27 | ...[...] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:88:26:88:26 | x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:91:1:94:3 | Integer | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:71:1:71:1 | d | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:71:1:71:9 | ... = ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:71:5:71:5 | D | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:71:5:71:9 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:72:1:72:1 | d | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:72:1:72:5 | call to baz | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:73:1:73:1 | d | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:73:1:73:13 | call to singleton_m | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:74:1:74:1 | d | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:74:1:74:12 | call to instance_m | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:76:1:79:3 | optional_arg | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:76:18:76:18 | a | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:76:18:76:18 | a | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:76:22:76:22 | 4 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:76:25:76:25 | b | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:76:25:76:25 | b | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:76:28:76:28 | 5 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:77:5:77:5 | a | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:77:5:77:16 | call to bit_length | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:78:5:78:5 | b | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:78:5:78:16 | call to bit_length | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:81:1:83:3 | call_block | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:82:5:82:11 | yield ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:82:11:82:11 | 1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:85:1:89:3 | foo | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:86:5:86:7 | var | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:86:5:86:18 | ... = ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:86:11:86:14 | Hash | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:86:11:86:18 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:87:5:87:7 | var | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:87:5:87:10 | ...[...] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:87:9:87:9 | 1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:88:5:88:29 | call to call_block | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:88:5:88:29 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:88:16:88:29 | { ... } | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:88:19:88:19 | x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:88:19:88:19 | x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:88:22:88:24 | var | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:88:22:88:27 | ...[...] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:88:26:88:26 | x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:91:1:94:3 | Integer | calls.rb:1:1:550:40 | calls.rb | | calls.rb:92:5:92:23 | bit_length | calls.rb:91:1:94:3 | Integer | | calls.rb:93:5:93:16 | abs | calls.rb:91:1:94:3 | Integer | -| calls.rb:96:1:98:3 | String | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:96:1:98:3 | String | calls.rb:1:1:550:40 | calls.rb | | calls.rb:97:5:97:23 | capitalize | calls.rb:96:1:98:3 | String | -| calls.rb:100:1:103:3 | Kernel | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:100:1:103:3 | Kernel | calls.rb:1:1:550:40 | calls.rb | | calls.rb:101:5:101:25 | alias ... | calls.rb:100:1:103:3 | Kernel | | calls.rb:101:11:101:19 | :old_puts | calls.rb:100:1:103:3 | Kernel | | calls.rb:101:11:101:19 | old_puts | calls.rb:100:1:103:3 | Kernel | @@ -551,7 +555,7 @@ enclosingModule | calls.rb:102:17:102:26 | call to old_puts | calls.rb:100:1:103:3 | Kernel | | calls.rb:102:17:102:26 | self | calls.rb:100:1:103:3 | Kernel | | calls.rb:102:26:102:26 | x | calls.rb:100:1:103:3 | Kernel | -| calls.rb:105:1:113:3 | Module | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:105:1:113:3 | Module | calls.rb:1:1:550:40 | calls.rb | | calls.rb:106:5:106:31 | alias ... | calls.rb:105:1:113:3 | Module | | calls.rb:106:11:106:22 | :old_include | calls.rb:105:1:113:3 | Module | | calls.rb:106:11:106:22 | old_include | calls.rb:105:1:113:3 | Module | @@ -566,13 +570,13 @@ enclosingModule | calls.rb:109:21:109:21 | x | calls.rb:105:1:113:3 | Module | | calls.rb:111:5:111:20 | prepend | calls.rb:105:1:113:3 | Module | | calls.rb:112:5:112:20 | private | calls.rb:105:1:113:3 | Module | -| calls.rb:115:1:118:3 | Object | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:115:16:115:21 | Module | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:115:1:118:3 | Object | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:115:16:115:21 | Module | calls.rb:1:1:550:40 | calls.rb | | calls.rb:116:5:116:18 | call to include | calls.rb:115:1:118:3 | Object | | calls.rb:116:5:116:18 | self | calls.rb:115:1:118:3 | Object | | calls.rb:116:13:116:18 | Kernel | calls.rb:115:1:118:3 | Object | | calls.rb:117:5:117:16 | new | calls.rb:115:1:118:3 | Object | -| calls.rb:120:1:123:3 | Hash | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:120:1:123:3 | Hash | calls.rb:1:1:550:40 | calls.rb | | calls.rb:121:5:121:25 | alias ... | calls.rb:120:1:123:3 | Hash | | calls.rb:121:11:121:21 | :old_lookup | calls.rb:120:1:123:3 | Hash | | calls.rb:121:11:121:21 | old_lookup | calls.rb:120:1:123:3 | Hash | @@ -584,7 +588,7 @@ enclosingModule | calls.rb:122:15:122:27 | call to old_lookup | calls.rb:120:1:123:3 | Hash | | calls.rb:122:15:122:27 | self | calls.rb:120:1:123:3 | Hash | | calls.rb:122:26:122:26 | x | calls.rb:120:1:123:3 | Hash | -| calls.rb:125:1:138:3 | Array | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:125:1:138:3 | Array | calls.rb:1:1:550:40 | calls.rb | | calls.rb:126:3:126:23 | alias ... | calls.rb:125:1:138:3 | Array | | calls.rb:126:9:126:19 | :old_lookup | calls.rb:125:1:138:3 | Array | | calls.rb:126:9:126:19 | old_lookup | calls.rb:125:1:138:3 | Array | @@ -620,130 +624,130 @@ enclosingModule | calls.rb:135:9:135:14 | ... = ... | calls.rb:125:1:138:3 | Array | | calls.rb:135:11:135:12 | ... + ... | calls.rb:125:1:138:3 | Array | | calls.rb:135:14:135:14 | 1 | calls.rb:125:1:138:3 | Array | -| calls.rb:140:1:142:3 | funny | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:141:5:141:20 | yield ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:141:11:141:20 | "prefix: " | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:141:12:141:19 | prefix: | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:144:1:144:30 | call to funny | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:144:1:144:30 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:144:7:144:30 | { ... } | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:144:10:144:10 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:144:10:144:10 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:144:13:144:29 | call to puts | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:144:13:144:29 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:144:18:144:18 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:144:18:144:29 | call to capitalize | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:146:1:146:3 | "a" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:146:1:146:14 | call to capitalize | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:146:2:146:2 | a | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:147:1:147:1 | 1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:147:1:147:12 | call to bit_length | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:148:1:148:1 | 1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:148:1:148:5 | call to abs | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:1:150:13 | Array | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:1:150:13 | [...] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:1:150:13 | call to [] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:1:150:62 | call to foreach | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:2:150:4 | "a" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:3:150:3 | a | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:6:150:8 | "b" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:7:150:7 | b | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:10:150:12 | "c" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:11:150:11 | c | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:23:150:62 | { ... } | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:26:150:26 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:26:150:26 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:29:150:29 | v | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:29:150:29 | v | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:32:150:61 | call to puts | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:32:150:61 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:37:150:61 | "#{...} -> #{...}" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:38:150:41 | #{...} | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:40:150:40 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:42:150:45 | -> | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:46:150:60 | #{...} | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:48:150:48 | v | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:150:48:150:59 | call to capitalize | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:152:1:152:7 | Array | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:152:1:152:7 | [...] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:152:1:152:7 | call to [] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:152:1:152:35 | call to foreach | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:152:2:152:2 | 1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:152:4:152:4 | 2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:152:6:152:6 | 3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:152:17:152:35 | { ... } | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:152:20:152:20 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:152:20:152:20 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:152:23:152:23 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:152:23:152:34 | call to bit_length | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:154:1:154:7 | Array | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:154:1:154:7 | [...] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:154:1:154:7 | call to [] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:154:1:154:40 | call to foreach | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:154:2:154:2 | 1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:154:4:154:4 | 2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:154:6:154:6 | 3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:154:17:154:40 | { ... } | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:154:20:154:20 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:154:20:154:20 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:154:23:154:39 | call to puts | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:154:23:154:39 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:154:28:154:28 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:154:28:154:39 | call to capitalize | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:1:156:8 | Array | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:1:156:8 | [...] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:1:156:8 | call to [] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:1:156:37 | call to foreach | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:2:156:2 | 1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:4:156:5 | - ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:5:156:5 | 2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:7:156:7 | 3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:18:156:37 | { ... } | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:21:156:21 | _ | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:21:156:21 | _ | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:24:156:24 | v | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:24:156:24 | v | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:27:156:36 | call to puts | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:27:156:36 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:32:156:32 | v | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:156:32:156:36 | call to abs | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:158:1:160:3 | indirect | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:158:14:158:15 | &b | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:158:15:158:15 | b | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:159:5:159:17 | call to call_block | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:159:5:159:17 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:159:16:159:17 | &... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:159:17:159:17 | b | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:162:1:162:28 | call to indirect | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:162:1:162:28 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:162:10:162:28 | { ... } | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:162:13:162:13 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:162:13:162:13 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:162:16:162:16 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:162:16:162:27 | call to bit_length | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:165:1:169:3 | S | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:140:1:142:3 | funny | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:141:5:141:20 | yield ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:141:11:141:20 | "prefix: " | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:141:12:141:19 | prefix: | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:144:1:144:30 | call to funny | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:144:1:144:30 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:144:7:144:30 | { ... } | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:144:10:144:10 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:144:10:144:10 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:144:13:144:29 | call to puts | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:144:13:144:29 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:144:18:144:18 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:144:18:144:29 | call to capitalize | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:146:1:146:3 | "a" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:146:1:146:14 | call to capitalize | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:146:2:146:2 | a | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:147:1:147:1 | 1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:147:1:147:12 | call to bit_length | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:148:1:148:1 | 1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:148:1:148:5 | call to abs | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:1:150:13 | Array | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:1:150:13 | [...] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:1:150:13 | call to [] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:1:150:62 | call to foreach | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:2:150:4 | "a" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:3:150:3 | a | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:6:150:8 | "b" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:7:150:7 | b | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:10:150:12 | "c" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:11:150:11 | c | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:23:150:62 | { ... } | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:26:150:26 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:26:150:26 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:29:150:29 | v | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:29:150:29 | v | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:32:150:61 | call to puts | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:32:150:61 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:37:150:61 | "#{...} -> #{...}" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:38:150:41 | #{...} | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:40:150:40 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:42:150:45 | -> | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:46:150:60 | #{...} | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:48:150:48 | v | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:150:48:150:59 | call to capitalize | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:152:1:152:7 | Array | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:152:1:152:7 | [...] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:152:1:152:7 | call to [] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:152:1:152:35 | call to foreach | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:152:2:152:2 | 1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:152:4:152:4 | 2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:152:6:152:6 | 3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:152:17:152:35 | { ... } | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:152:20:152:20 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:152:20:152:20 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:152:23:152:23 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:152:23:152:34 | call to bit_length | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:154:1:154:7 | Array | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:154:1:154:7 | [...] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:154:1:154:7 | call to [] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:154:1:154:40 | call to foreach | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:154:2:154:2 | 1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:154:4:154:4 | 2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:154:6:154:6 | 3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:154:17:154:40 | { ... } | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:154:20:154:20 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:154:20:154:20 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:154:23:154:39 | call to puts | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:154:23:154:39 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:154:28:154:28 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:154:28:154:39 | call to capitalize | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:1:156:8 | Array | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:1:156:8 | [...] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:1:156:8 | call to [] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:1:156:37 | call to foreach | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:2:156:2 | 1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:4:156:5 | - ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:5:156:5 | 2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:7:156:7 | 3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:18:156:37 | { ... } | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:21:156:21 | _ | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:21:156:21 | _ | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:24:156:24 | v | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:24:156:24 | v | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:27:156:36 | call to puts | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:27:156:36 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:32:156:32 | v | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:156:32:156:36 | call to abs | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:158:1:160:3 | indirect | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:158:14:158:15 | &b | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:158:15:158:15 | b | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:159:5:159:17 | call to call_block | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:159:5:159:17 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:159:16:159:17 | &... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:159:17:159:17 | b | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:162:1:162:28 | call to indirect | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:162:1:162:28 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:162:10:162:28 | { ... } | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:162:13:162:13 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:162:13:162:13 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:162:16:162:16 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:162:16:162:27 | call to bit_length | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:165:1:169:3 | S | calls.rb:1:1:550:40 | calls.rb | | calls.rb:166:5:168:7 | s_method | calls.rb:165:1:169:3 | S | | calls.rb:167:9:167:12 | self | calls.rb:165:1:169:3 | S | | calls.rb:167:9:167:17 | call to to_s | calls.rb:165:1:169:3 | S | -| calls.rb:171:1:174:3 | A | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:171:11:171:11 | S | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:171:1:174:3 | A | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:171:11:171:11 | S | calls.rb:1:1:550:40 | calls.rb | | calls.rb:172:5:173:7 | to_s | calls.rb:171:1:174:3 | A | -| calls.rb:176:1:179:3 | B | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:176:11:176:11 | S | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:176:1:179:3 | B | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:176:11:176:11 | S | calls.rb:1:1:550:40 | calls.rb | | calls.rb:177:5:178:7 | to_s | calls.rb:176:1:179:3 | B | -| calls.rb:181:1:181:1 | S | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:181:1:181:5 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:181:1:181:14 | call to s_method | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:182:1:182:1 | A | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:182:1:182:5 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:182:1:182:14 | call to s_method | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:183:1:183:1 | B | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:183:1:183:5 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:183:1:183:14 | call to s_method | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:185:1:186:3 | private_on_main | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:188:1:188:15 | call to private_on_main | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:188:1:188:15 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:190:1:226:3 | Singletons | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:181:1:181:1 | S | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:181:1:181:5 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:181:1:181:14 | call to s_method | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:182:1:182:1 | A | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:182:1:182:5 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:182:1:182:14 | call to s_method | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:183:1:183:1 | B | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:183:1:183:5 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:183:1:183:14 | call to s_method | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:185:1:186:3 | private_on_main | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:188:1:188:15 | call to private_on_main | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:188:1:188:15 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:190:1:226:3 | Singletons | calls.rb:1:1:550:40 | calls.rb | | calls.rb:191:5:194:7 | singleton_a | calls.rb:190:1:226:3 | Singletons | | calls.rb:191:9:191:12 | self | calls.rb:190:1:226:3 | Singletons | | calls.rb:192:9:192:26 | call to puts | calls.rb:190:1:226:3 | Singletons | @@ -793,126 +797,126 @@ enclosingModule | calls.rb:223:5:225:7 | call_singleton_g | calls.rb:190:1:226:3 | Singletons | | calls.rb:224:9:224:12 | self | calls.rb:190:1:226:3 | Singletons | | calls.rb:224:9:224:24 | call to singleton_g | calls.rb:190:1:226:3 | Singletons | -| calls.rb:228:1:228:10 | Singletons | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:228:1:228:22 | call to singleton_a | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:229:1:229:10 | Singletons | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:229:1:229:22 | call to singleton_f | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:231:1:231:2 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:231:1:231:19 | ... = ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:231:6:231:15 | Singletons | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:231:6:231:19 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:233:1:233:2 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:233:1:233:11 | call to instance | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:234:1:234:2 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:234:1:234:14 | call to singleton_e | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:236:1:238:3 | singleton_g | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:236:5:236:6 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:237:5:237:24 | call to puts | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:237:5:237:24 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:237:10:237:24 | "singleton_g_1" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:237:11:237:23 | singleton_g_1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:240:1:240:2 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:240:1:240:14 | call to singleton_g | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:241:1:241:2 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:241:1:241:19 | call to call_singleton_g | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:243:1:245:3 | singleton_g | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:243:5:243:6 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:244:5:244:24 | call to puts | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:244:5:244:24 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:244:10:244:24 | "singleton_g_2" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:244:11:244:23 | singleton_g_2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:247:1:247:2 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:247:1:247:14 | call to singleton_g | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:248:1:248:2 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:248:1:248:19 | call to call_singleton_g | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:250:1:254:3 | class << ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:250:10:250:11 | c1 | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:228:1:228:10 | Singletons | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:228:1:228:22 | call to singleton_a | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:229:1:229:10 | Singletons | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:229:1:229:22 | call to singleton_f | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:231:1:231:2 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:231:1:231:19 | ... = ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:231:6:231:15 | Singletons | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:231:6:231:19 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:233:1:233:2 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:233:1:233:11 | call to instance | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:234:1:234:2 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:234:1:234:14 | call to singleton_e | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:236:1:238:3 | singleton_g | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:236:5:236:6 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:237:5:237:24 | call to puts | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:237:5:237:24 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:237:10:237:24 | "singleton_g_1" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:237:11:237:23 | singleton_g_1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:240:1:240:2 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:240:1:240:14 | call to singleton_g | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:241:1:241:2 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:241:1:241:19 | call to call_singleton_g | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:243:1:245:3 | singleton_g | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:243:5:243:6 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:244:5:244:24 | call to puts | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:244:5:244:24 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:244:10:244:24 | "singleton_g_2" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:244:11:244:23 | singleton_g_2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:247:1:247:2 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:247:1:247:14 | call to singleton_g | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:248:1:248:2 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:248:1:248:19 | call to call_singleton_g | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:250:1:254:3 | class << ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:250:10:250:11 | c1 | calls.rb:1:1:550:40 | calls.rb | | calls.rb:251:5:253:7 | singleton_g | calls.rb:250:1:254:3 | class << ... | | calls.rb:252:9:252:28 | call to puts | calls.rb:250:1:254:3 | class << ... | | calls.rb:252:9:252:28 | self | calls.rb:250:1:254:3 | class << ... | | calls.rb:252:14:252:28 | "singleton_g_3" | calls.rb:250:1:254:3 | class << ... | | calls.rb:252:15:252:27 | singleton_g_3 | calls.rb:250:1:254:3 | class << ... | -| calls.rb:256:1:256:2 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:256:1:256:14 | call to singleton_g | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:257:1:257:2 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:257:1:257:19 | call to call_singleton_g | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:259:1:259:2 | c2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:259:1:259:19 | ... = ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:259:6:259:15 | Singletons | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:259:6:259:19 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:260:1:260:2 | c2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:260:1:260:14 | call to singleton_e | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:261:1:261:2 | c2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:261:1:261:14 | call to singleton_g | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:263:1:263:4 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:263:1:263:8 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:265:1:265:16 | call to puts | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:265:1:265:16 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:265:6:265:16 | "top-level" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:265:7:265:15 | top-level | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:267:1:269:3 | singleton_g | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:267:5:267:14 | Singletons | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:268:5:268:22 | call to puts | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:268:5:268:22 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:268:10:268:22 | "singleton_g" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:268:11:268:21 | singleton_g | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:271:1:271:10 | Singletons | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:271:1:271:22 | call to singleton_g | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:272:1:272:2 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:272:1:272:14 | call to singleton_g | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:273:1:273:2 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:273:1:273:19 | call to call_singleton_g | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:274:1:274:2 | c2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:274:1:274:14 | call to singleton_g | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:275:1:275:2 | c3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:275:1:275:19 | ... = ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:275:6:275:15 | Singletons | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:275:6:275:19 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:276:1:276:2 | c3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:276:1:276:14 | call to singleton_g | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:278:1:286:3 | create | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:278:12:278:15 | type | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:278:12:278:15 | type | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:279:5:279:8 | type | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:279:5:279:12 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:279:5:279:21 | call to instance | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:281:5:283:7 | singleton_h | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:281:9:281:12 | type | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:282:9:282:26 | call to puts | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:282:9:282:26 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:282:14:282:26 | "singleton_h" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:282:15:282:25 | singleton_h | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:285:5:285:8 | type | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:285:5:285:20 | call to singleton_h | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:288:1:288:17 | call to create | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:288:1:288:17 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:288:8:288:17 | Singletons | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:289:1:289:10 | Singletons | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:289:1:289:22 | call to singleton_h | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:291:1:291:1 | x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:291:1:291:14 | ... = ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:291:5:291:14 | Singletons | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:293:1:297:3 | class << ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:293:10:293:10 | x | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:256:1:256:2 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:256:1:256:14 | call to singleton_g | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:257:1:257:2 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:257:1:257:19 | call to call_singleton_g | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:259:1:259:2 | c2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:259:1:259:19 | ... = ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:259:6:259:15 | Singletons | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:259:6:259:19 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:260:1:260:2 | c2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:260:1:260:14 | call to singleton_e | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:261:1:261:2 | c2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:261:1:261:14 | call to singleton_g | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:263:1:263:4 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:263:1:263:8 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:265:1:265:16 | call to puts | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:265:1:265:16 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:265:6:265:16 | "top-level" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:265:7:265:15 | top-level | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:267:1:269:3 | singleton_g | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:267:5:267:14 | Singletons | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:268:5:268:22 | call to puts | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:268:5:268:22 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:268:10:268:22 | "singleton_g" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:268:11:268:21 | singleton_g | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:271:1:271:10 | Singletons | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:271:1:271:22 | call to singleton_g | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:272:1:272:2 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:272:1:272:14 | call to singleton_g | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:273:1:273:2 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:273:1:273:19 | call to call_singleton_g | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:274:1:274:2 | c2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:274:1:274:14 | call to singleton_g | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:275:1:275:2 | c3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:275:1:275:19 | ... = ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:275:6:275:15 | Singletons | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:275:6:275:19 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:276:1:276:2 | c3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:276:1:276:14 | call to singleton_g | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:278:1:286:3 | create | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:278:12:278:15 | type | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:278:12:278:15 | type | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:279:5:279:8 | type | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:279:5:279:12 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:279:5:279:21 | call to instance | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:281:5:283:7 | singleton_h | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:281:9:281:12 | type | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:282:9:282:26 | call to puts | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:282:9:282:26 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:282:14:282:26 | "singleton_h" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:282:15:282:25 | singleton_h | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:285:5:285:8 | type | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:285:5:285:20 | call to singleton_h | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:288:1:288:17 | call to create | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:288:1:288:17 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:288:8:288:17 | Singletons | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:289:1:289:10 | Singletons | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:289:1:289:22 | call to singleton_h | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:291:1:291:1 | x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:291:1:291:14 | ... = ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:291:5:291:14 | Singletons | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:293:1:297:3 | class << ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:293:10:293:10 | x | calls.rb:1:1:550:40 | calls.rb | | calls.rb:294:5:296:7 | singleton_i | calls.rb:293:1:297:3 | class << ... | | calls.rb:295:9:295:26 | call to puts | calls.rb:293:1:297:3 | class << ... | | calls.rb:295:9:295:26 | self | calls.rb:293:1:297:3 | class << ... | | calls.rb:295:14:295:26 | "singleton_i" | calls.rb:293:1:297:3 | class << ... | | calls.rb:295:15:295:25 | singleton_i | calls.rb:293:1:297:3 | class << ... | -| calls.rb:299:1:299:1 | x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:299:1:299:13 | call to singleton_i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:300:1:300:10 | Singletons | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:300:1:300:22 | call to singleton_i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:302:1:306:3 | class << ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:302:10:302:19 | Singletons | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:299:1:299:1 | x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:299:1:299:13 | call to singleton_i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:300:1:300:10 | Singletons | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:300:1:300:22 | call to singleton_i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:302:1:306:3 | class << ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:302:10:302:19 | Singletons | calls.rb:1:1:550:40 | calls.rb | | calls.rb:303:5:305:7 | singleton_j | calls.rb:302:1:306:3 | class << ... | | calls.rb:304:9:304:26 | call to puts | calls.rb:302:1:306:3 | class << ... | | calls.rb:304:9:304:26 | self | calls.rb:302:1:306:3 | class << ... | | calls.rb:304:14:304:26 | "singleton_j" | calls.rb:302:1:306:3 | class << ... | | calls.rb:304:15:304:25 | singleton_j | calls.rb:302:1:306:3 | class << ... | -| calls.rb:308:1:308:10 | Singletons | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:308:1:308:22 | call to singleton_j | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:310:1:321:3 | SelfNew | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:308:1:308:10 | Singletons | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:308:1:308:22 | call to singleton_j | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:310:1:321:3 | SelfNew | calls.rb:1:1:550:40 | calls.rb | | calls.rb:311:5:314:7 | instance | calls.rb:310:1:321:3 | SelfNew | | calls.rb:312:9:312:31 | call to puts | calls.rb:310:1:321:3 | SelfNew | | calls.rb:312:9:312:31 | self | calls.rb:310:1:321:3 | SelfNew | @@ -929,110 +933,110 @@ enclosingModule | calls.rb:320:5:320:7 | call to new | calls.rb:310:1:321:3 | SelfNew | | calls.rb:320:5:320:7 | self | calls.rb:310:1:321:3 | SelfNew | | calls.rb:320:5:320:16 | call to instance | calls.rb:310:1:321:3 | SelfNew | -| calls.rb:323:1:323:7 | SelfNew | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:323:1:323:17 | call to singleton | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:325:1:329:3 | C1 | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:323:1:323:7 | SelfNew | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:323:1:323:17 | call to singleton | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:325:1:329:3 | C1 | calls.rb:1:1:550:40 | calls.rb | | calls.rb:326:5:328:7 | instance | calls.rb:325:1:329:3 | C1 | | calls.rb:327:9:327:26 | call to puts | calls.rb:325:1:329:3 | C1 | | calls.rb:327:9:327:26 | self | calls.rb:325:1:329:3 | C1 | | calls.rb:327:14:327:26 | "C1#instance" | calls.rb:325:1:329:3 | C1 | | calls.rb:327:15:327:25 | C1#instance | calls.rb:325:1:329:3 | C1 | -| calls.rb:331:1:335:3 | C2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:331:12:331:13 | C1 | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:331:1:335:3 | C2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:331:12:331:13 | C1 | calls.rb:1:1:550:40 | calls.rb | | calls.rb:332:5:334:7 | instance | calls.rb:331:1:335:3 | C2 | | calls.rb:333:9:333:26 | call to puts | calls.rb:331:1:335:3 | C2 | | calls.rb:333:9:333:26 | self | calls.rb:331:1:335:3 | C2 | | calls.rb:333:14:333:26 | "C2#instance" | calls.rb:331:1:335:3 | C2 | | calls.rb:333:15:333:25 | C2#instance | calls.rb:331:1:335:3 | C2 | -| calls.rb:337:1:341:3 | C3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:337:12:337:13 | C2 | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:337:1:341:3 | C3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:337:12:337:13 | C2 | calls.rb:1:1:550:40 | calls.rb | | calls.rb:338:5:340:7 | instance | calls.rb:337:1:341:3 | C3 | | calls.rb:339:9:339:26 | call to puts | calls.rb:337:1:341:3 | C3 | | calls.rb:339:9:339:26 | self | calls.rb:337:1:341:3 | C3 | | calls.rb:339:14:339:26 | "C3#instance" | calls.rb:337:1:341:3 | C3 | | calls.rb:339:15:339:25 | C3#instance | calls.rb:337:1:341:3 | C3 | -| calls.rb:343:1:359:3 | pattern_dispatch | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:343:22:343:22 | x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:343:22:343:22 | x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:344:5:352:7 | case ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:344:10:344:10 | x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:345:5:346:18 | when ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:345:10:345:11 | C3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:345:12:346:18 | then ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:346:9:346:9 | x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:346:9:346:18 | call to instance | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:347:5:348:18 | when ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:347:10:347:11 | C2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:347:12:348:18 | then ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:348:9:348:9 | x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:348:9:348:18 | call to instance | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:349:5:350:18 | when ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:349:10:349:11 | C1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:349:12:350:18 | then ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:350:9:350:9 | x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:350:9:350:18 | call to instance | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:351:5:351:8 | else ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:354:5:358:7 | case ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:354:10:354:10 | x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:355:9:355:29 | in ... then ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:355:12:355:13 | C3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:355:15:355:29 | then ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:355:20:355:20 | x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:355:20:355:29 | call to instance | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:356:9:356:36 | in ... then ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:356:12:356:13 | C2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:356:12:356:19 | ... => ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:356:18:356:19 | c2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:356:21:356:36 | then ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:356:26:356:27 | c2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:356:26:356:36 | call to instance | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:357:9:357:36 | in ... then ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:357:12:357:13 | C1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:357:12:357:19 | ... => ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:357:18:357:19 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:357:21:357:36 | then ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:357:26:357:27 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:357:26:357:36 | call to instance | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:361:1:361:2 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:361:1:361:11 | ... = ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:361:6:361:7 | C1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:361:6:361:11 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:362:1:362:2 | c1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:362:1:362:11 | call to instance | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:363:1:363:25 | call to pattern_dispatch | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:363:1:363:25 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:363:18:363:25 | ( ... ) | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:363:19:363:20 | C1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:363:19:363:24 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:364:1:364:25 | call to pattern_dispatch | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:364:1:364:25 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:364:18:364:25 | ( ... ) | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:364:19:364:20 | C2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:364:19:364:24 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:365:1:365:25 | call to pattern_dispatch | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:365:1:365:25 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:365:18:365:25 | ( ... ) | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:365:19:365:20 | C3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:365:19:365:24 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:367:1:371:3 | add_singleton | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:367:19:367:19 | x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:367:19:367:19 | x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:368:5:370:7 | instance | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:368:9:368:9 | x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:369:9:369:28 | call to puts | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:369:9:369:28 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:369:14:369:28 | "instance_on x" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:369:15:369:27 | instance_on x | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:373:1:373:2 | c3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:373:1:373:11 | ... = ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:373:6:373:7 | C1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:373:6:373:11 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:374:1:374:16 | call to add_singleton | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:374:1:374:16 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:374:15:374:16 | c3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:375:1:375:2 | c3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:375:1:375:11 | call to instance | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:377:1:397:3 | SingletonOverride1 | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:343:1:359:3 | pattern_dispatch | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:343:22:343:22 | x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:343:22:343:22 | x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:344:5:352:7 | case ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:344:10:344:10 | x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:345:5:346:18 | when ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:345:10:345:11 | C3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:345:12:346:18 | then ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:346:9:346:9 | x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:346:9:346:18 | call to instance | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:347:5:348:18 | when ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:347:10:347:11 | C2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:347:12:348:18 | then ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:348:9:348:9 | x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:348:9:348:18 | call to instance | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:349:5:350:18 | when ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:349:10:349:11 | C1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:349:12:350:18 | then ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:350:9:350:9 | x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:350:9:350:18 | call to instance | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:351:5:351:8 | else ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:354:5:358:7 | case ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:354:10:354:10 | x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:355:9:355:29 | in ... then ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:355:12:355:13 | C3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:355:15:355:29 | then ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:355:20:355:20 | x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:355:20:355:29 | call to instance | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:356:9:356:36 | in ... then ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:356:12:356:13 | C2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:356:12:356:19 | ... => ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:356:18:356:19 | c2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:356:21:356:36 | then ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:356:26:356:27 | c2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:356:26:356:36 | call to instance | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:357:9:357:36 | in ... then ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:357:12:357:13 | C1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:357:12:357:19 | ... => ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:357:18:357:19 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:357:21:357:36 | then ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:357:26:357:27 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:357:26:357:36 | call to instance | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:361:1:361:2 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:361:1:361:11 | ... = ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:361:6:361:7 | C1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:361:6:361:11 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:362:1:362:2 | c1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:362:1:362:11 | call to instance | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:363:1:363:25 | call to pattern_dispatch | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:363:1:363:25 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:363:18:363:25 | ( ... ) | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:363:19:363:20 | C1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:363:19:363:24 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:364:1:364:25 | call to pattern_dispatch | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:364:1:364:25 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:364:18:364:25 | ( ... ) | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:364:19:364:20 | C2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:364:19:364:24 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:365:1:365:25 | call to pattern_dispatch | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:365:1:365:25 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:365:18:365:25 | ( ... ) | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:365:19:365:20 | C3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:365:19:365:24 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:367:1:371:3 | add_singleton | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:367:19:367:19 | x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:367:19:367:19 | x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:368:5:370:7 | instance | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:368:9:368:9 | x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:369:9:369:28 | call to puts | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:369:9:369:28 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:369:14:369:28 | "instance_on x" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:369:15:369:27 | instance_on x | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:373:1:373:2 | c3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:373:1:373:11 | ... = ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:373:6:373:7 | C1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:373:6:373:11 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:374:1:374:16 | call to add_singleton | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:374:1:374:16 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:374:15:374:16 | c3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:375:1:375:2 | c3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:375:1:375:11 | call to instance | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:377:1:397:3 | SingletonOverride1 | calls.rb:1:1:550:40 | calls.rb | | calls.rb:378:5:386:7 | class << ... | calls.rb:377:1:397:3 | SingletonOverride1 | | calls.rb:378:14:378:17 | self | calls.rb:377:1:397:3 | SingletonOverride1 | | calls.rb:379:9:381:11 | singleton1 | calls.rb:378:5:386:7 | class << ... | @@ -1055,274 +1059,282 @@ enclosingModule | calls.rb:393:9:393:18 | self | calls.rb:377:1:397:3 | SingletonOverride1 | | calls.rb:396:5:396:14 | call to singleton2 | calls.rb:377:1:397:3 | SingletonOverride1 | | calls.rb:396:5:396:14 | self | calls.rb:377:1:397:3 | SingletonOverride1 | -| calls.rb:399:1:399:18 | SingletonOverride1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:399:1:399:34 | call to call_singleton1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:400:1:400:18 | SingletonOverride1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:400:1:400:34 | call to call_singleton2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:402:1:412:3 | SingletonOverride2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:402:28:402:45 | SingletonOverride1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:403:5:407:7 | class << ... | calls.rb:402:1:412:3 | SingletonOverride2 | -| calls.rb:403:14:403:17 | self | calls.rb:402:1:412:3 | SingletonOverride2 | -| calls.rb:404:9:406:11 | singleton1 | calls.rb:403:5:407:7 | class << ... | -| calls.rb:405:13:405:48 | call to puts | calls.rb:403:5:407:7 | class << ... | -| calls.rb:405:13:405:48 | self | calls.rb:403:5:407:7 | class << ... | -| calls.rb:405:18:405:48 | "SingletonOverride2#singleton1" | calls.rb:403:5:407:7 | class << ... | -| calls.rb:405:19:405:47 | SingletonOverride2#singleton1 | calls.rb:403:5:407:7 | class << ... | -| calls.rb:409:5:411:7 | singleton2 | calls.rb:402:1:412:3 | SingletonOverride2 | -| calls.rb:409:9:409:12 | self | calls.rb:402:1:412:3 | SingletonOverride2 | -| calls.rb:410:9:410:44 | call to puts | calls.rb:402:1:412:3 | SingletonOverride2 | -| calls.rb:410:9:410:44 | self | calls.rb:402:1:412:3 | SingletonOverride2 | -| calls.rb:410:14:410:44 | "SingletonOverride2#singleton2" | calls.rb:402:1:412:3 | SingletonOverride2 | -| calls.rb:410:15:410:43 | SingletonOverride2#singleton2 | calls.rb:402:1:412:3 | SingletonOverride2 | -| calls.rb:414:1:414:18 | SingletonOverride2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:414:1:414:34 | call to call_singleton1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:415:1:415:18 | SingletonOverride2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:415:1:415:34 | call to call_singleton2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:417:1:445:3 | ConditionalInstanceMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:418:5:422:7 | if ... | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:418:8:418:13 | call to rand | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:418:8:418:13 | self | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:418:8:418:17 | ... > ... | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:418:17:418:17 | 0 | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:418:19:421:11 | then ... | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:419:9:421:11 | m1 | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:420:13:420:48 | call to puts | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:420:13:420:48 | self | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:420:18:420:48 | "ConditionalInstanceMethods#m1" | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:420:19:420:47 | ConditionalInstanceMethods#m1 | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:424:5:436:7 | m2 | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:425:9:425:44 | call to puts | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:425:9:425:44 | self | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:425:14:425:44 | "ConditionalInstanceMethods#m2" | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:425:15:425:43 | ConditionalInstanceMethods#m2 | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:427:9:433:11 | m3 | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:428:13:428:48 | call to puts | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:428:13:428:48 | self | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:428:18:428:48 | "ConditionalInstanceMethods#m3" | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:428:19:428:47 | ConditionalInstanceMethods#m3 | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:430:13:432:15 | m4 | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:431:17:431:52 | call to puts | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:431:17:431:52 | self | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:431:22:431:52 | "ConditionalInstanceMethods#m4" | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:431:23:431:51 | ConditionalInstanceMethods#m4 | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:435:9:435:10 | call to m3 | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:435:9:435:10 | self | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:438:5:444:7 | if ... | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:438:8:438:13 | call to rand | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:438:8:438:13 | self | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:438:8:438:17 | ... > ... | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:438:17:438:17 | 0 | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:438:19:443:18 | then ... | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:439:9:439:13 | Class | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:439:9:443:11 | call to new | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:439:9:443:15 | call to new | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:439:9:443:18 | call to m5 | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:439:19:443:11 | do ... end | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:440:13:442:15 | m5 | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:441:17:441:40 | call to puts | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:441:17:441:40 | self | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:441:22:441:40 | "AnonymousClass#m5" | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:441:23:441:39 | AnonymousClass#m5 | calls.rb:417:1:445:3 | ConditionalInstanceMethods | -| calls.rb:447:1:447:26 | ConditionalInstanceMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:447:1:447:30 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:447:1:447:33 | call to m1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:448:1:448:26 | ConditionalInstanceMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:448:1:448:30 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:448:1:448:33 | call to m3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:449:1:449:26 | ConditionalInstanceMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:449:1:449:30 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:449:1:449:33 | call to m2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:450:1:450:26 | ConditionalInstanceMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:450:1:450:30 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:450:1:450:33 | call to m3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:451:1:451:26 | ConditionalInstanceMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:451:1:451:30 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:451:1:451:33 | call to m4 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:452:1:452:26 | ConditionalInstanceMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:452:1:452:30 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:452:1:452:33 | call to m5 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:454:1:454:23 | EsotericInstanceMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:454:1:472:3 | ... = ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:454:27:454:31 | Class | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:454:27:472:3 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:454:37:472:3 | do ... end | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:455:5:455:11 | Array | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:455:5:455:11 | [...] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:455:5:455:11 | call to [] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:455:5:459:7 | call to each | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:455:6:455:6 | 0 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:455:8:455:8 | 1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:455:10:455:10 | 2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:455:18:459:7 | do ... end | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:456:9:458:11 | foo | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:457:13:457:22 | call to puts | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:457:13:457:22 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:457:18:457:22 | "foo" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:457:19:457:21 | foo | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:461:5:461:9 | Class | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:461:5:465:7 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:461:5:465:11 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:461:5:465:15 | call to bar | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:461:15:465:7 | do ... end | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:462:9:464:11 | bar | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:463:13:463:22 | call to puts | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:463:13:463:22 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:463:18:463:22 | "bar" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:463:19:463:21 | bar | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:467:5:467:11 | Array | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:467:5:467:11 | [...] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:467:5:467:11 | call to [] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:467:5:471:7 | call to each | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:467:6:467:6 | 0 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:467:8:467:8 | 1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:467:10:467:10 | 2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:467:18:471:7 | do ... end | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:467:22:467:22 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:467:22:467:22 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:468:9:470:11 | call to define_method | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:468:9:470:11 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:468:23:468:32 | "baz_#{...}" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:468:24:468:27 | baz_ | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:468:28:468:31 | #{...} | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:468:30:468:30 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:468:35:470:11 | do ... end | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:469:13:469:27 | call to puts | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:469:13:469:27 | self | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:469:18:469:27 | "baz_#{...}" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:469:19:469:22 | baz_ | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:469:23:469:26 | #{...} | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:469:25:469:25 | i | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:474:1:474:23 | EsotericInstanceMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:474:1:474:27 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:474:1:474:31 | call to foo | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:475:1:475:23 | EsotericInstanceMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:475:1:475:27 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:475:1:475:31 | call to bar | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:476:1:476:23 | EsotericInstanceMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:476:1:476:27 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:476:1:476:33 | call to baz_0 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:477:1:477:23 | EsotericInstanceMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:477:1:477:27 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:477:1:477:33 | call to baz_1 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:478:1:478:23 | EsotericInstanceMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:478:1:478:27 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:478:1:478:33 | call to baz_2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:480:1:486:3 | ExtendSingletonMethod | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:481:5:483:7 | singleton | calls.rb:480:1:486:3 | ExtendSingletonMethod | -| calls.rb:482:9:482:46 | call to puts | calls.rb:480:1:486:3 | ExtendSingletonMethod | -| calls.rb:482:9:482:46 | self | calls.rb:480:1:486:3 | ExtendSingletonMethod | -| calls.rb:482:14:482:46 | "ExtendSingletonMethod#singleton" | calls.rb:480:1:486:3 | ExtendSingletonMethod | -| calls.rb:482:15:482:45 | ExtendSingletonMethod#singleton | calls.rb:480:1:486:3 | ExtendSingletonMethod | -| calls.rb:485:5:485:15 | call to extend | calls.rb:480:1:486:3 | ExtendSingletonMethod | -| calls.rb:485:5:485:15 | self | calls.rb:480:1:486:3 | ExtendSingletonMethod | -| calls.rb:485:12:485:15 | self | calls.rb:480:1:486:3 | ExtendSingletonMethod | -| calls.rb:488:1:488:21 | ExtendSingletonMethod | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:488:1:488:31 | call to singleton | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:490:1:492:3 | ExtendSingletonMethod2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:491:5:491:32 | call to extend | calls.rb:490:1:492:3 | ExtendSingletonMethod2 | -| calls.rb:491:5:491:32 | self | calls.rb:490:1:492:3 | ExtendSingletonMethod2 | -| calls.rb:491:12:491:32 | ExtendSingletonMethod | calls.rb:490:1:492:3 | ExtendSingletonMethod2 | -| calls.rb:494:1:494:22 | ExtendSingletonMethod2 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:494:1:494:32 | call to singleton | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:496:1:497:3 | ExtendSingletonMethod3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:499:1:499:22 | ExtendSingletonMethod3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:499:1:499:51 | call to extend | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:499:31:499:51 | ExtendSingletonMethod | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:501:1:501:22 | ExtendSingletonMethod3 | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:501:1:501:32 | call to singleton | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:503:1:503:3 | foo | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:503:1:503:13 | ... = ... | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:503:7:503:13 | "hello" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:503:8:503:12 | hello | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:504:1:504:3 | foo | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:504:1:504:13 | call to singleton | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:505:1:505:3 | foo | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:505:1:505:32 | call to extend | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:505:12:505:32 | ExtendSingletonMethod | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:507:1:507:3 | foo | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:507:1:507:13 | call to singleton | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:509:1:513:3 | ProtectedMethodInModule | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:510:5:512:7 | call to protected | calls.rb:509:1:513:3 | ProtectedMethodInModule | -| calls.rb:510:5:512:7 | self | calls.rb:509:1:513:3 | ProtectedMethodInModule | -| calls.rb:510:15:512:7 | foo | calls.rb:509:1:513:3 | ProtectedMethodInModule | -| calls.rb:511:9:511:42 | call to puts | calls.rb:509:1:513:3 | ProtectedMethodInModule | -| calls.rb:511:9:511:42 | self | calls.rb:509:1:513:3 | ProtectedMethodInModule | -| calls.rb:511:14:511:42 | "ProtectedMethodInModule#foo" | calls.rb:509:1:513:3 | ProtectedMethodInModule | -| calls.rb:511:15:511:41 | ProtectedMethodInModule#foo | calls.rb:509:1:513:3 | ProtectedMethodInModule | -| calls.rb:515:1:528:3 | ProtectedMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:516:5:516:35 | call to include | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:516:5:516:35 | self | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:516:13:516:35 | ProtectedMethodInModule | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:518:5:520:7 | call to protected | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:518:5:520:7 | self | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:518:15:520:7 | bar | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:519:9:519:35 | call to puts | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:519:9:519:35 | self | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:519:14:519:35 | "ProtectedMethods#bar" | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:519:15:519:34 | ProtectedMethods#bar | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:522:5:527:7 | baz | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:523:9:523:11 | call to foo | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:523:9:523:11 | self | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:524:9:524:11 | call to bar | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:524:9:524:11 | self | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:525:9:525:24 | ProtectedMethods | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:525:9:525:28 | call to new | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:525:9:525:32 | call to foo | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:526:9:526:24 | ProtectedMethods | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:526:9:526:28 | call to new | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:526:9:526:32 | call to bar | calls.rb:515:1:528:3 | ProtectedMethods | -| calls.rb:530:1:530:16 | ProtectedMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:530:1:530:20 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:530:1:530:24 | call to foo | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:531:1:531:16 | ProtectedMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:531:1:531:20 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:531:1:531:24 | call to bar | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:532:1:532:16 | ProtectedMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:532:1:532:20 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:532:1:532:24 | call to baz | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:534:1:539:3 | ProtectedMethodsSub | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:534:29:534:44 | ProtectedMethods | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:535:5:538:7 | baz | calls.rb:534:1:539:3 | ProtectedMethodsSub | -| calls.rb:536:9:536:11 | call to foo | calls.rb:534:1:539:3 | ProtectedMethodsSub | -| calls.rb:536:9:536:11 | self | calls.rb:534:1:539:3 | ProtectedMethodsSub | -| calls.rb:537:9:537:27 | ProtectedMethodsSub | calls.rb:534:1:539:3 | ProtectedMethodsSub | -| calls.rb:537:9:537:31 | call to new | calls.rb:534:1:539:3 | ProtectedMethodsSub | -| calls.rb:537:9:537:35 | call to foo | calls.rb:534:1:539:3 | ProtectedMethodsSub | -| calls.rb:541:1:541:19 | ProtectedMethodsSub | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:541:1:541:23 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:541:1:541:27 | call to foo | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:542:1:542:19 | ProtectedMethodsSub | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:542:1:542:23 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:542:1:542:27 | call to bar | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:543:1:543:19 | ProtectedMethodsSub | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:543:1:543:23 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:543:1:543:27 | call to baz | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:545:1:545:7 | Array | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:545:1:545:7 | [...] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:545:1:545:7 | call to [] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:545:1:545:26 | call to each | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:545:2:545:2 | C | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:545:2:545:6 | call to new | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:545:14:545:26 | { ... } | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:545:17:545:17 | c | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:545:17:545:17 | c | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:545:20:545:20 | c | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:545:20:545:24 | call to baz | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:546:1:546:13 | Array | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:546:1:546:13 | [...] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:546:1:546:13 | call to [] | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:546:1:546:39 | call to each | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:546:2:546:4 | "a" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:546:3:546:3 | a | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:546:6:546:8 | "b" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:546:7:546:7 | b | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:546:10:546:12 | "c" | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:546:11:546:11 | c | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:546:20:546:39 | { ... } | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:546:23:546:23 | s | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:546:23:546:23 | s | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:546:26:546:26 | s | calls.rb:1:1:546:40 | calls.rb | -| calls.rb:546:26:546:37 | call to capitalize | calls.rb:1:1:546:40 | calls.rb | +| calls.rb:399:1:399:18 | SingletonOverride1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:399:1:399:29 | call to singleton1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:400:1:400:18 | SingletonOverride1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:400:1:400:29 | call to singleton2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:401:1:401:18 | SingletonOverride1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:401:1:401:34 | call to call_singleton1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:402:1:402:18 | SingletonOverride1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:402:1:402:34 | call to call_singleton2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:404:1:414:3 | SingletonOverride2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:404:28:404:45 | SingletonOverride1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:405:5:409:7 | class << ... | calls.rb:404:1:414:3 | SingletonOverride2 | +| calls.rb:405:14:405:17 | self | calls.rb:404:1:414:3 | SingletonOverride2 | +| calls.rb:406:9:408:11 | singleton1 | calls.rb:405:5:409:7 | class << ... | +| calls.rb:407:13:407:48 | call to puts | calls.rb:405:5:409:7 | class << ... | +| calls.rb:407:13:407:48 | self | calls.rb:405:5:409:7 | class << ... | +| calls.rb:407:18:407:48 | "SingletonOverride2#singleton1" | calls.rb:405:5:409:7 | class << ... | +| calls.rb:407:19:407:47 | SingletonOverride2#singleton1 | calls.rb:405:5:409:7 | class << ... | +| calls.rb:411:5:413:7 | singleton2 | calls.rb:404:1:414:3 | SingletonOverride2 | +| calls.rb:411:9:411:12 | self | calls.rb:404:1:414:3 | SingletonOverride2 | +| calls.rb:412:9:412:44 | call to puts | calls.rb:404:1:414:3 | SingletonOverride2 | +| calls.rb:412:9:412:44 | self | calls.rb:404:1:414:3 | SingletonOverride2 | +| calls.rb:412:14:412:44 | "SingletonOverride2#singleton2" | calls.rb:404:1:414:3 | SingletonOverride2 | +| calls.rb:412:15:412:43 | SingletonOverride2#singleton2 | calls.rb:404:1:414:3 | SingletonOverride2 | +| calls.rb:416:1:416:18 | SingletonOverride2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:416:1:416:29 | call to singleton1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:417:1:417:18 | SingletonOverride2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:417:1:417:29 | call to singleton2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:418:1:418:18 | SingletonOverride2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:418:1:418:34 | call to call_singleton1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:419:1:419:18 | SingletonOverride2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:419:1:419:34 | call to call_singleton2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:421:1:449:3 | ConditionalInstanceMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:422:5:426:7 | if ... | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:422:8:422:13 | call to rand | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:422:8:422:13 | self | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:422:8:422:17 | ... > ... | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:422:17:422:17 | 0 | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:422:19:425:11 | then ... | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:423:9:425:11 | m1 | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:424:13:424:48 | call to puts | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:424:13:424:48 | self | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:424:18:424:48 | "ConditionalInstanceMethods#m1" | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:424:19:424:47 | ConditionalInstanceMethods#m1 | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:428:5:440:7 | m2 | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:429:9:429:44 | call to puts | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:429:9:429:44 | self | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:429:14:429:44 | "ConditionalInstanceMethods#m2" | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:429:15:429:43 | ConditionalInstanceMethods#m2 | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:431:9:437:11 | m3 | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:432:13:432:48 | call to puts | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:432:13:432:48 | self | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:432:18:432:48 | "ConditionalInstanceMethods#m3" | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:432:19:432:47 | ConditionalInstanceMethods#m3 | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:434:13:436:15 | m4 | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:435:17:435:52 | call to puts | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:435:17:435:52 | self | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:435:22:435:52 | "ConditionalInstanceMethods#m4" | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:435:23:435:51 | ConditionalInstanceMethods#m4 | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:439:9:439:10 | call to m3 | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:439:9:439:10 | self | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:442:5:448:7 | if ... | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:442:8:442:13 | call to rand | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:442:8:442:13 | self | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:442:8:442:17 | ... > ... | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:442:17:442:17 | 0 | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:442:19:447:18 | then ... | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:443:9:443:13 | Class | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:443:9:447:11 | call to new | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:443:9:447:15 | call to new | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:443:9:447:18 | call to m5 | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:443:19:447:11 | do ... end | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:444:13:446:15 | m5 | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:445:17:445:40 | call to puts | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:445:17:445:40 | self | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:445:22:445:40 | "AnonymousClass#m5" | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:445:23:445:39 | AnonymousClass#m5 | calls.rb:421:1:449:3 | ConditionalInstanceMethods | +| calls.rb:451:1:451:26 | ConditionalInstanceMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:451:1:451:30 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:451:1:451:33 | call to m1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:452:1:452:26 | ConditionalInstanceMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:452:1:452:30 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:452:1:452:33 | call to m3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:453:1:453:26 | ConditionalInstanceMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:453:1:453:30 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:453:1:453:33 | call to m2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:454:1:454:26 | ConditionalInstanceMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:454:1:454:30 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:454:1:454:33 | call to m3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:455:1:455:26 | ConditionalInstanceMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:455:1:455:30 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:455:1:455:33 | call to m4 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:456:1:456:26 | ConditionalInstanceMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:456:1:456:30 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:456:1:456:33 | call to m5 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:458:1:458:23 | EsotericInstanceMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:458:1:476:3 | ... = ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:458:27:458:31 | Class | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:458:27:476:3 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:458:37:476:3 | do ... end | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:459:5:459:11 | Array | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:459:5:459:11 | [...] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:459:5:459:11 | call to [] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:459:5:463:7 | call to each | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:459:6:459:6 | 0 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:459:8:459:8 | 1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:459:10:459:10 | 2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:459:18:463:7 | do ... end | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:460:9:462:11 | foo | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:461:13:461:22 | call to puts | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:461:13:461:22 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:461:18:461:22 | "foo" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:461:19:461:21 | foo | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:465:5:465:9 | Class | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:465:5:469:7 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:465:5:469:11 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:465:5:469:15 | call to bar | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:465:15:469:7 | do ... end | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:466:9:468:11 | bar | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:467:13:467:22 | call to puts | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:467:13:467:22 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:467:18:467:22 | "bar" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:467:19:467:21 | bar | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:471:5:471:11 | Array | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:471:5:471:11 | [...] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:471:5:471:11 | call to [] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:471:5:475:7 | call to each | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:471:6:471:6 | 0 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:471:8:471:8 | 1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:471:10:471:10 | 2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:471:18:475:7 | do ... end | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:471:22:471:22 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:471:22:471:22 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:472:9:474:11 | call to define_method | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:472:9:474:11 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:472:23:472:32 | "baz_#{...}" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:472:24:472:27 | baz_ | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:472:28:472:31 | #{...} | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:472:30:472:30 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:472:35:474:11 | do ... end | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:473:13:473:27 | call to puts | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:473:13:473:27 | self | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:473:18:473:27 | "baz_#{...}" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:473:19:473:22 | baz_ | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:473:23:473:26 | #{...} | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:473:25:473:25 | i | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:478:1:478:23 | EsotericInstanceMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:478:1:478:27 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:478:1:478:31 | call to foo | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:479:1:479:23 | EsotericInstanceMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:479:1:479:27 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:479:1:479:31 | call to bar | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:480:1:480:23 | EsotericInstanceMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:480:1:480:27 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:480:1:480:33 | call to baz_0 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:481:1:481:23 | EsotericInstanceMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:481:1:481:27 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:481:1:481:33 | call to baz_1 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:482:1:482:23 | EsotericInstanceMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:482:1:482:27 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:482:1:482:33 | call to baz_2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:484:1:490:3 | ExtendSingletonMethod | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:485:5:487:7 | singleton | calls.rb:484:1:490:3 | ExtendSingletonMethod | +| calls.rb:486:9:486:46 | call to puts | calls.rb:484:1:490:3 | ExtendSingletonMethod | +| calls.rb:486:9:486:46 | self | calls.rb:484:1:490:3 | ExtendSingletonMethod | +| calls.rb:486:14:486:46 | "ExtendSingletonMethod#singleton" | calls.rb:484:1:490:3 | ExtendSingletonMethod | +| calls.rb:486:15:486:45 | ExtendSingletonMethod#singleton | calls.rb:484:1:490:3 | ExtendSingletonMethod | +| calls.rb:489:5:489:15 | call to extend | calls.rb:484:1:490:3 | ExtendSingletonMethod | +| calls.rb:489:5:489:15 | self | calls.rb:484:1:490:3 | ExtendSingletonMethod | +| calls.rb:489:12:489:15 | self | calls.rb:484:1:490:3 | ExtendSingletonMethod | +| calls.rb:492:1:492:21 | ExtendSingletonMethod | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:492:1:492:31 | call to singleton | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:494:1:496:3 | ExtendSingletonMethod2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:495:5:495:32 | call to extend | calls.rb:494:1:496:3 | ExtendSingletonMethod2 | +| calls.rb:495:5:495:32 | self | calls.rb:494:1:496:3 | ExtendSingletonMethod2 | +| calls.rb:495:12:495:32 | ExtendSingletonMethod | calls.rb:494:1:496:3 | ExtendSingletonMethod2 | +| calls.rb:498:1:498:22 | ExtendSingletonMethod2 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:498:1:498:32 | call to singleton | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:500:1:501:3 | ExtendSingletonMethod3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:503:1:503:22 | ExtendSingletonMethod3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:503:1:503:51 | call to extend | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:503:31:503:51 | ExtendSingletonMethod | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:505:1:505:22 | ExtendSingletonMethod3 | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:505:1:505:32 | call to singleton | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:507:1:507:3 | foo | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:507:1:507:13 | ... = ... | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:507:7:507:13 | "hello" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:507:8:507:12 | hello | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:508:1:508:3 | foo | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:508:1:508:13 | call to singleton | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:509:1:509:3 | foo | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:509:1:509:32 | call to extend | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:509:12:509:32 | ExtendSingletonMethod | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:511:1:511:3 | foo | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:511:1:511:13 | call to singleton | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:513:1:517:3 | ProtectedMethodInModule | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:514:5:516:7 | call to protected | calls.rb:513:1:517:3 | ProtectedMethodInModule | +| calls.rb:514:5:516:7 | self | calls.rb:513:1:517:3 | ProtectedMethodInModule | +| calls.rb:514:15:516:7 | foo | calls.rb:513:1:517:3 | ProtectedMethodInModule | +| calls.rb:515:9:515:42 | call to puts | calls.rb:513:1:517:3 | ProtectedMethodInModule | +| calls.rb:515:9:515:42 | self | calls.rb:513:1:517:3 | ProtectedMethodInModule | +| calls.rb:515:14:515:42 | "ProtectedMethodInModule#foo" | calls.rb:513:1:517:3 | ProtectedMethodInModule | +| calls.rb:515:15:515:41 | ProtectedMethodInModule#foo | calls.rb:513:1:517:3 | ProtectedMethodInModule | +| calls.rb:519:1:532:3 | ProtectedMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:520:5:520:35 | call to include | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:520:5:520:35 | self | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:520:13:520:35 | ProtectedMethodInModule | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:522:5:524:7 | call to protected | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:522:5:524:7 | self | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:522:15:524:7 | bar | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:523:9:523:35 | call to puts | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:523:9:523:35 | self | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:523:14:523:35 | "ProtectedMethods#bar" | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:523:15:523:34 | ProtectedMethods#bar | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:526:5:531:7 | baz | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:527:9:527:11 | call to foo | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:527:9:527:11 | self | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:528:9:528:11 | call to bar | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:528:9:528:11 | self | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:529:9:529:24 | ProtectedMethods | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:529:9:529:28 | call to new | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:529:9:529:32 | call to foo | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:530:9:530:24 | ProtectedMethods | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:530:9:530:28 | call to new | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:530:9:530:32 | call to bar | calls.rb:519:1:532:3 | ProtectedMethods | +| calls.rb:534:1:534:16 | ProtectedMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:534:1:534:20 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:534:1:534:24 | call to foo | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:535:1:535:16 | ProtectedMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:535:1:535:20 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:535:1:535:24 | call to bar | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:536:1:536:16 | ProtectedMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:536:1:536:20 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:536:1:536:24 | call to baz | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:538:1:543:3 | ProtectedMethodsSub | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:538:29:538:44 | ProtectedMethods | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:539:5:542:7 | baz | calls.rb:538:1:543:3 | ProtectedMethodsSub | +| calls.rb:540:9:540:11 | call to foo | calls.rb:538:1:543:3 | ProtectedMethodsSub | +| calls.rb:540:9:540:11 | self | calls.rb:538:1:543:3 | ProtectedMethodsSub | +| calls.rb:541:9:541:27 | ProtectedMethodsSub | calls.rb:538:1:543:3 | ProtectedMethodsSub | +| calls.rb:541:9:541:31 | call to new | calls.rb:538:1:543:3 | ProtectedMethodsSub | +| calls.rb:541:9:541:35 | call to foo | calls.rb:538:1:543:3 | ProtectedMethodsSub | +| calls.rb:545:1:545:19 | ProtectedMethodsSub | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:545:1:545:23 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:545:1:545:27 | call to foo | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:546:1:546:19 | ProtectedMethodsSub | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:546:1:546:23 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:546:1:546:27 | call to bar | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:547:1:547:19 | ProtectedMethodsSub | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:547:1:547:23 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:547:1:547:27 | call to baz | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:549:1:549:7 | Array | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:549:1:549:7 | [...] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:549:1:549:7 | call to [] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:549:1:549:26 | call to each | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:549:2:549:2 | C | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:549:2:549:6 | call to new | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:549:14:549:26 | { ... } | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:549:17:549:17 | c | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:549:17:549:17 | c | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:549:20:549:20 | c | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:549:20:549:24 | call to baz | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:550:1:550:13 | Array | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:550:1:550:13 | [...] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:550:1:550:13 | call to [] | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:550:1:550:39 | call to each | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:550:2:550:4 | "a" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:550:3:550:3 | a | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:550:6:550:8 | "b" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:550:7:550:7 | b | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:550:10:550:12 | "c" | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:550:11:550:11 | c | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:550:20:550:39 | { ... } | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:550:23:550:23 | s | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:550:23:550:23 | s | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:550:26:550:26 | s | calls.rb:1:1:550:40 | calls.rb | +| calls.rb:550:26:550:37 | call to capitalize | calls.rb:1:1:550:40 | calls.rb | | hello.rb:1:1:8:3 | EnglishWords | hello.rb:1:1:22:3 | hello.rb | | hello.rb:2:5:4:7 | hello | hello.rb:1:1:8:3 | EnglishWords | | hello.rb:3:9:3:22 | return | hello.rb:1:1:8:3 | EnglishWords | diff --git a/ruby/ql/test/library-tests/modules/superclasses.expected b/ruby/ql/test/library-tests/modules/superclasses.expected index 1a6504c1a79..f73f7962731 100644 --- a/ruby/ql/test/library-tests/modules/superclasses.expected +++ b/ruby/ql/test/library-tests/modules/superclasses.expected @@ -85,24 +85,24 @@ calls.rb: # 377| SingletonOverride1 #-----| -> Object -# 402| SingletonOverride2 +# 404| SingletonOverride2 #-----| -> SingletonOverride1 -# 417| ConditionalInstanceMethods +# 421| ConditionalInstanceMethods #-----| -> Object -# 480| ExtendSingletonMethod +# 484| ExtendSingletonMethod -# 490| ExtendSingletonMethod2 +# 494| ExtendSingletonMethod2 -# 496| ExtendSingletonMethod3 +# 500| ExtendSingletonMethod3 -# 509| ProtectedMethodInModule +# 513| ProtectedMethodInModule -# 515| ProtectedMethods +# 519| ProtectedMethods #-----| -> Object -# 534| ProtectedMethodsSub +# 538| ProtectedMethodsSub #-----| -> ProtectedMethods hello.rb: diff --git a/shared/ssa/CHANGELOG.md b/shared/ssa/CHANGELOG.md index 2c547c365ec..9f2cb351ed0 100644 --- a/shared/ssa/CHANGELOG.md +++ b/shared/ssa/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.2 + +No user-facing changes. + ## 0.0.1 * Initial release. Extracted common SSA code into a library pack to share code between languages. diff --git a/shared/ssa/change-notes/released/0.0.2.md b/shared/ssa/change-notes/released/0.0.2.md new file mode 100644 index 00000000000..5ab250998ed --- /dev/null +++ b/shared/ssa/change-notes/released/0.0.2.md @@ -0,0 +1,3 @@ +## 0.0.2 + +No user-facing changes. diff --git a/shared/ssa/codeql-pack.release.yml b/shared/ssa/codeql-pack.release.yml index c6933410b71..55dc06fbd76 100644 --- a/shared/ssa/codeql-pack.release.yml +++ b/shared/ssa/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.0.1 +lastReleaseVersion: 0.0.2 diff --git a/shared/ssa/qlpack.yml b/shared/ssa/qlpack.yml index ef21714c8b8..3fc606ae5ed 100644 --- a/shared/ssa/qlpack.yml +++ b/shared/ssa/qlpack.yml @@ -1,4 +1,4 @@ name: codeql/ssa -version: 0.0.2-dev +version: 0.0.3-dev groups: shared library: true diff --git a/shared/typos/CHANGELOG.md b/shared/typos/CHANGELOG.md index 95a5c570ac0..82994494b53 100644 --- a/shared/typos/CHANGELOG.md +++ b/shared/typos/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.2 + +No user-facing changes. + ## 0.0.1 * Initial release. Share the database of common typographical errors between languages. diff --git a/shared/typos/change-notes/released/0.0.2.md b/shared/typos/change-notes/released/0.0.2.md new file mode 100644 index 00000000000..5ab250998ed --- /dev/null +++ b/shared/typos/change-notes/released/0.0.2.md @@ -0,0 +1,3 @@ +## 0.0.2 + +No user-facing changes. diff --git a/shared/typos/codeql-pack.release.yml b/shared/typos/codeql-pack.release.yml index c6933410b71..55dc06fbd76 100644 --- a/shared/typos/codeql-pack.release.yml +++ b/shared/typos/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.0.1 +lastReleaseVersion: 0.0.2 diff --git a/shared/typos/qlpack.yml b/shared/typos/qlpack.yml index 587537220ec..a8adea7ab70 100644 --- a/shared/typos/qlpack.yml +++ b/shared/typos/qlpack.yml @@ -1,4 +1,4 @@ name: codeql/typos -version: 0.0.2-dev +version: 0.0.3-dev groups: shared library: true diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll index 67e93ea7f6f..c8d9d66e1b9 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll @@ -163,7 +163,9 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) } + predicate hasFlowTo(Node sink) { + sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() + } /** * Holds if data may flow from some source to `sink` for this configuration.