diff --git a/MODULE.bazel b/MODULE.bazel index d5c2c8784e2..16b4a4691f8 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -27,7 +27,7 @@ bazel_dep(name = "abseil-cpp", version = "20260107.1", repo_name = "absl") bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json") bazel_dep(name = "fmt", version = "12.1.0-codeql.1") bazel_dep(name = "rules_kotlin", version = "2.2.2-codeql.1") -bazel_dep(name = "gazelle", version = "0.47.0") +bazel_dep(name = "gazelle", version = "0.50.0") bazel_dep(name = "rules_dotnet", version = "0.21.5-codeql.1") bazel_dep(name = "googletest", version = "1.17.0.bcr.2") bazel_dep(name = "rules_rust", version = "0.69.0") diff --git a/actions/ql/src/Security/CWE-829/ArtifactPoisoningCritical.ql b/actions/ql/src/Security/CWE-829/ArtifactPoisoningCritical.ql index 24ecb4b0339..be49de830c3 100644 --- a/actions/ql/src/Security/CWE-829/ArtifactPoisoningCritical.ql +++ b/actions/ql/src/Security/CWE-829/ArtifactPoisoningCritical.ql @@ -20,6 +20,6 @@ from ArtifactPoisoningFlow::PathNode source, ArtifactPoisoningFlow::PathNode sin where ArtifactPoisoningFlow::flowPath(source, sink) and event = getRelevantEventInPrivilegedContext(sink.getNode()) -select sink.getNode(), source, sink, - "Potential artifact poisoning in $@, which may be controlled by an external user ($@).", sink, - sink.getNode().toString(), event, event.getName() +select source.getNode(), source, sink, + "Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@).", + event, event.getName() diff --git a/actions/ql/src/Security/CWE-829/ArtifactPoisoningMedium.ql b/actions/ql/src/Security/CWE-829/ArtifactPoisoningMedium.ql index d2aff7da95f..49dc856e566 100644 --- a/actions/ql/src/Security/CWE-829/ArtifactPoisoningMedium.ql +++ b/actions/ql/src/Security/CWE-829/ArtifactPoisoningMedium.ql @@ -20,6 +20,5 @@ from ArtifactPoisoningFlow::PathNode source, ArtifactPoisoningFlow::PathNode sin where ArtifactPoisoningFlow::flowPath(source, sink) and inNonPrivilegedContext(sink.getNode().asExpr()) -select sink.getNode(), source, sink, - "Potential artifact poisoning in $@, which may be controlled by an external user.", sink, - sink.getNode().toString() +select source.getNode(), source, sink, + "Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user." diff --git a/actions/ql/src/change-notes/2026-04-02-alert-msg-poisoning.md b/actions/ql/src/change-notes/2026-04-02-alert-msg-poisoning.md new file mode 100644 index 00000000000..e2340f446a7 --- /dev/null +++ b/actions/ql/src/change-notes/2026-04-02-alert-msg-poisoning.md @@ -0,0 +1,4 @@ +--- +category: majorAnalysis +--- +* Fixed alert messages in `actions/artifact-poisoning/critical` and `actions/artifact-poisoning/medium` as they previously included a redundant placeholder in the alert message that would on occasion contain a long block of yml that makes the alert difficult to understand. Also clarify the wording to make it clear that it is not the artifact that is being poisoned, but instead a potentially untrusted artifact that is consumed. Also change the alert location to be the source, to align more with other queries reporting an artifact (e.g. zipslip) which is more useful. \ No newline at end of file diff --git a/actions/ql/test/query-tests/Security/CWE-829/ArtifactPoisoningCritical.expected b/actions/ql/test/query-tests/Security/CWE-829/ArtifactPoisoningCritical.expected index 2d29cd9b79b..3c5f6bf93e9 100644 --- a/actions/ql/test/query-tests/Security/CWE-829/ArtifactPoisoningCritical.expected +++ b/actions/ql/test/query-tests/Security/CWE-829/ArtifactPoisoningCritical.expected @@ -55,21 +55,21 @@ nodes | .github/workflows/test25.yml:39:14:40:45 | ./gradlew buildScanPublishPrevious\n | semmle.label | ./gradlew buildScanPublishPrevious\n | subpaths #select -| .github/workflows/artifactpoisoning11.yml:38:11:38:77 | ./sonarcloud-data/x.py build -j$(nproc) --compiler gcc --skip-build | .github/workflows/artifactpoisoning11.yml:13:9:32:6 | Uses Step | .github/workflows/artifactpoisoning11.yml:38:11:38:77 | ./sonarcloud-data/x.py build -j$(nproc) --compiler gcc --skip-build | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning11.yml:38:11:38:77 | ./sonarcloud-data/x.py build -j$(nproc) --compiler gcc --skip-build | ./sonarcloud-data/x.py build -j$(nproc) --compiler gcc --skip-build | .github/workflows/artifactpoisoning11.yml:4:3:4:14 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning12.yml:38:11:38:25 | python foo/x.py | .github/workflows/artifactpoisoning12.yml:13:9:32:6 | Uses Step | .github/workflows/artifactpoisoning12.yml:38:11:38:25 | python foo/x.py | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning12.yml:38:11:38:25 | python foo/x.py | python foo/x.py | .github/workflows/artifactpoisoning12.yml:4:3:4:14 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning21.yml:19:14:20:21 | sh foo/cmd\n | .github/workflows/artifactpoisoning21.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning21.yml:19:14:20:21 | sh foo/cmd\n | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning21.yml:19:14:20:21 | sh foo/cmd\n | sh foo/cmd\n | .github/workflows/artifactpoisoning21.yml:4:3:4:14 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning22.yml:18:14:18:19 | sh cmd | .github/workflows/artifactpoisoning22.yml:13:9:17:6 | Uses Step | .github/workflows/artifactpoisoning22.yml:18:14:18:19 | sh cmd | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning22.yml:18:14:18:19 | sh cmd | sh cmd | .github/workflows/artifactpoisoning22.yml:4:3:4:14 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning31.yml:19:14:19:22 | ./foo/cmd | .github/workflows/artifactpoisoning31.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning31.yml:19:14:19:22 | ./foo/cmd | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning31.yml:19:14:19:22 | ./foo/cmd | ./foo/cmd | .github/workflows/artifactpoisoning31.yml:4:3:4:14 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning32.yml:17:14:18:20 | ./bar/cmd\n | .github/workflows/artifactpoisoning32.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning32.yml:17:14:18:20 | ./bar/cmd\n | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning32.yml:17:14:18:20 | ./bar/cmd\n | ./bar/cmd\n | .github/workflows/artifactpoisoning32.yml:4:3:4:14 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning33.yml:17:14:18:20 | ./bar/cmd\n | .github/workflows/artifactpoisoning33.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning33.yml:17:14:18:20 | ./bar/cmd\n | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning33.yml:17:14:18:20 | ./bar/cmd\n | ./bar/cmd\n | .github/workflows/artifactpoisoning33.yml:4:3:4:14 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning34.yml:20:14:22:23 | npm install\nnpm run lint\n | .github/workflows/artifactpoisoning34.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning34.yml:20:14:22:23 | npm install\nnpm run lint\n | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning34.yml:20:14:22:23 | npm install\nnpm run lint\n | npm install\nnpm run lint\n | .github/workflows/artifactpoisoning34.yml:4:3:4:14 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning41.yml:22:14:22:22 | ./foo/cmd | .github/workflows/artifactpoisoning41.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning41.yml:22:14:22:22 | ./foo/cmd | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning41.yml:22:14:22:22 | ./foo/cmd | ./foo/cmd | .github/workflows/artifactpoisoning41.yml:4:3:4:14 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning42.yml:22:14:22:18 | ./cmd | .github/workflows/artifactpoisoning42.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning42.yml:22:14:22:18 | ./cmd | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning42.yml:22:14:22:18 | ./cmd | ./cmd | .github/workflows/artifactpoisoning42.yml:4:3:4:14 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning71.yml:17:14:18:40 | sed -f config foo.md > bar.md\n | .github/workflows/artifactpoisoning71.yml:9:9:16:6 | Uses Step | .github/workflows/artifactpoisoning71.yml:17:14:18:40 | sed -f config foo.md > bar.md\n | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning71.yml:17:14:18:40 | sed -f config foo.md > bar.md\n | sed -f config foo.md > bar.md\n | .github/workflows/artifactpoisoning71.yml:4:5:4:16 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | .github/workflows/artifactpoisoning81.yml:28:9:31:6 | Uses Step | .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | python test.py | .github/workflows/artifactpoisoning81.yml:3:5:3:23 | pull_request_target | pull_request_target | -| .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | Uses Step | .github/workflows/artifactpoisoning92.yml:3:3:3:14 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | make snapshot | .github/workflows/artifactpoisoning92.yml:3:3:3:14 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning96.yml:18:14:18:24 | npm install | .github/workflows/artifactpoisoning96.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning96.yml:18:14:18:24 | npm install | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning96.yml:18:14:18:24 | npm install | npm install | .github/workflows/artifactpoisoning96.yml:2:3:2:14 | workflow_run | workflow_run | -| .github/workflows/artifactpoisoning101.yml:17:14:19:59 | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | .github/workflows/artifactpoisoning101.yml:10:9:16:6 | Uses Step | .github/workflows/artifactpoisoning101.yml:17:14:19:59 | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/artifactpoisoning101.yml:17:14:19:59 | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | .github/workflows/artifactpoisoning101.yml:4:3:4:21 | pull_request_target | pull_request_target | -| .github/workflows/test18.yml:36:15:40:58 | Uses Step | .github/workflows/test18.yml:12:15:33:12 | Uses Step | .github/workflows/test18.yml:36:15:40:58 | Uses Step | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/test18.yml:36:15:40:58 | Uses Step | Uses Step | .github/workflows/test18.yml:3:5:3:16 | workflow_run | workflow_run | -| .github/workflows/test25.yml:39:14:40:45 | ./gradlew buildScanPublishPrevious\n | .github/workflows/test25.yml:22:9:32:6 | Uses Step: downloadBuildScan | .github/workflows/test25.yml:39:14:40:45 | ./gradlew buildScanPublishPrevious\n | Potential artifact poisoning in $@, which may be controlled by an external user ($@). | .github/workflows/test25.yml:39:14:40:45 | ./gradlew buildScanPublishPrevious\n | ./gradlew buildScanPublishPrevious\n | .github/workflows/test25.yml:2:3:2:14 | workflow_run | workflow_run | +| .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:28:9:29:6 | Uses Step | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning92.yml:3:3:3:14 | workflow_run | workflow_run | +| .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/actions/download-artifact-2/action.yaml:6:7:25:4 | Uses Step | .github/workflows/artifactpoisoning92.yml:29:14:29:26 | make snapshot | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning92.yml:3:3:3:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning11.yml:13:9:32:6 | Uses Step | .github/workflows/artifactpoisoning11.yml:13:9:32:6 | Uses Step | .github/workflows/artifactpoisoning11.yml:38:11:38:77 | ./sonarcloud-data/x.py build -j$(nproc) --compiler gcc --skip-build | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning11.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning12.yml:13:9:32:6 | Uses Step | .github/workflows/artifactpoisoning12.yml:13:9:32:6 | Uses Step | .github/workflows/artifactpoisoning12.yml:38:11:38:25 | python foo/x.py | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning12.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning21.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning21.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning21.yml:19:14:20:21 | sh foo/cmd\n | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning21.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning22.yml:13:9:17:6 | Uses Step | .github/workflows/artifactpoisoning22.yml:13:9:17:6 | Uses Step | .github/workflows/artifactpoisoning22.yml:18:14:18:19 | sh cmd | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning22.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning31.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning31.yml:13:9:15:6 | Run Step | .github/workflows/artifactpoisoning31.yml:19:14:19:22 | ./foo/cmd | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning31.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning32.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning32.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning32.yml:17:14:18:20 | ./bar/cmd\n | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning32.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning33.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning33.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning33.yml:17:14:18:20 | ./bar/cmd\n | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning33.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning34.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning34.yml:13:9:16:6 | Run Step | .github/workflows/artifactpoisoning34.yml:20:14:22:23 | npm install\nnpm run lint\n | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning34.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning41.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning41.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning41.yml:22:14:22:22 | ./foo/cmd | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning41.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning42.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning42.yml:13:9:21:6 | Run Step | .github/workflows/artifactpoisoning42.yml:22:14:22:18 | ./cmd | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning42.yml:4:3:4:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning71.yml:9:9:16:6 | Uses Step | .github/workflows/artifactpoisoning71.yml:9:9:16:6 | Uses Step | .github/workflows/artifactpoisoning71.yml:17:14:18:40 | sed -f config foo.md > bar.md\n | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning71.yml:4:5:4:16 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning81.yml:28:9:31:6 | Uses Step | .github/workflows/artifactpoisoning81.yml:28:9:31:6 | Uses Step | .github/workflows/artifactpoisoning81.yml:31:14:31:27 | python test.py | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning81.yml:3:5:3:23 | pull_request_target | pull_request_target | +| .github/workflows/artifactpoisoning96.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning96.yml:13:9:18:6 | Uses Step | .github/workflows/artifactpoisoning96.yml:18:14:18:24 | npm install | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning96.yml:2:3:2:14 | workflow_run | workflow_run | +| .github/workflows/artifactpoisoning101.yml:10:9:16:6 | Uses Step | .github/workflows/artifactpoisoning101.yml:10:9:16:6 | Uses Step | .github/workflows/artifactpoisoning101.yml:17:14:19:59 | PR_NUMBER=$(./get_pull_request_number.sh pr_number.txt)\necho "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT \n | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/artifactpoisoning101.yml:4:3:4:21 | pull_request_target | pull_request_target | +| .github/workflows/test18.yml:12:15:33:12 | Uses Step | .github/workflows/test18.yml:12:15:33:12 | Uses Step | .github/workflows/test18.yml:36:15:40:58 | Uses Step | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/test18.yml:3:5:3:16 | workflow_run | workflow_run | +| .github/workflows/test25.yml:22:9:32:6 | Uses Step: downloadBuildScan | .github/workflows/test25.yml:22:9:32:6 | Uses Step: downloadBuildScan | .github/workflows/test25.yml:39:14:40:45 | ./gradlew buildScanPublishPrevious\n | Potential artifact poisoning; the artifact being consumed has contents that may be controlled by an external user ($@). | .github/workflows/test25.yml:2:3:2:14 | workflow_run | workflow_run | diff --git a/cpp/ql/lib/change-notes/2026-04-07-autoconf.md b/cpp/ql/lib/change-notes/2026-04-07-autoconf.md new file mode 100644 index 00000000000..9f04417b8e2 --- /dev/null +++ b/cpp/ql/lib/change-notes/2026-04-07-autoconf.md @@ -0,0 +1,4 @@ +--- +category: feature +--- +* Added a subclass `AutoconfConfigureTestFile` of `ConfigurationTestFile` that represents files created by GNU autoconf configure scripts to test the build configuration. diff --git a/cpp/ql/lib/semmle/code/cpp/ConfigurationTestFile.qll b/cpp/ql/lib/semmle/code/cpp/ConfigurationTestFile.qll index b39c1009f07..ae90caa0e63 100644 --- a/cpp/ql/lib/semmle/code/cpp/ConfigurationTestFile.qll +++ b/cpp/ql/lib/semmle/code/cpp/ConfigurationTestFile.qll @@ -42,3 +42,10 @@ class MesonPrivateTestFile extends ConfigurationTestFile { ) } } + +/** + * A file created by a GNU autoconf configure script to test the system configuration. + */ +class AutoconfConfigureTestFile extends ConfigurationTestFile { + AutoconfConfigureTestFile() { this.getBaseName().regexpMatch("conftest[0-9]*\\.c(pp)?") } +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/ExprHasNoEffect.expected b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/ExprHasNoEffect.expected new file mode 100644 index 00000000000..a87d2ddbd1b --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/ExprHasNoEffect.expected @@ -0,0 +1,2 @@ +| conftest.c.c:4:3:4:8 | call to strlen | This expression has no effect (because $@ has no external side effects). | conftest.h:3:8:3:13 | strlen | strlen | +| conftest_abc.c:4:3:4:8 | call to strlen | This expression has no effect (because $@ has no external side effects). | conftest.h:3:8:3:13 | strlen | strlen | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/ExprHasNoEffect.qlref b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/ExprHasNoEffect.qlref new file mode 100644 index 00000000000..82a90f5413a --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/ExprHasNoEffect.qlref @@ -0,0 +1 @@ +Likely Bugs/Likely Typos/ExprHasNoEffect.ql diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.c b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.c new file mode 100644 index 00000000000..2e067f5c433 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.c @@ -0,0 +1,6 @@ +#include "conftest.h" + +int main2() { + strlen(""); // GOOD: conftest files are ignored + return 0; +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.c.c b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.c.c new file mode 100644 index 00000000000..4ff7c225335 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.c.c @@ -0,0 +1,6 @@ +#include "conftest.h" + +int main3() { + strlen(""); // BAD: not a `conftest` file, as `conftest` is not directly followed by the extension or a sequence of numbers. + return 0; +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.cpp b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.cpp new file mode 100644 index 00000000000..7b8edf64261 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.cpp @@ -0,0 +1,6 @@ +#include "conftest.h" + +int main4() { + strlen(""); // GOOD: conftest files are ignored + return 0; +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.h b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.h new file mode 100644 index 00000000000..9cf6f7e0d9f --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest.h @@ -0,0 +1,3 @@ +typedef long long size_t; + +size_t strlen(const char *s); diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest123.c b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest123.c new file mode 100644 index 00000000000..b227d53ad2a --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest123.c @@ -0,0 +1,6 @@ +#include "conftest.h" + +int main5() { + strlen(""); // GOOD: conftest files are ignored + return 0; +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest_abc.c b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest_abc.c new file mode 100644 index 00000000000..88215d7434c --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Likely Typos/ExprHasNoEffect/autoconf/conftest_abc.c @@ -0,0 +1,6 @@ +#include "conftest.h" + +int main1() { + strlen(""); // BAD: not a `conftest` file, as `conftest` is not directly followed by the extension or a sequence of numbers. + return 0; +} diff --git a/csharp/ql/lib/Linq/Helpers.qll b/csharp/ql/lib/Linq/Helpers.qll index d490868f453..912b12b9457 100644 --- a/csharp/ql/lib/Linq/Helpers.qll +++ b/csharp/ql/lib/Linq/Helpers.qll @@ -77,7 +77,7 @@ predicate missedAllOpportunity(ForeachStmtGenericEnumerable fes) { // The then case of the if assigns false to something and breaks out of the loop. exists(Assignment a, BoolLiteral bl | a = is.getThen().getAChild*() and - bl = a.getRValue() and + bl = a.getRightOperand() and bl.toString() = "false" ) and is.getThen().getAChild*() instanceof BreakStmt diff --git a/csharp/ql/lib/change-notes/2026-04-01-getlrvalue.md b/csharp/ql/lib/change-notes/2026-04-01-getlrvalue.md new file mode 100644 index 00000000000..da1a3d62148 --- /dev/null +++ b/csharp/ql/lib/change-notes/2026-04-01-getlrvalue.md @@ -0,0 +1,4 @@ +--- +category: deprecated +--- +* The predicates `get[L|R]Value` in the class `Assignment` have been deprecated. Use `get[Left|Right]Operand` instead. diff --git a/csharp/ql/lib/definitions.qll b/csharp/ql/lib/definitions.qll index 4feaf20629c..d4f2540bbef 100644 --- a/csharp/ql/lib/definitions.qll +++ b/csharp/ql/lib/definitions.qll @@ -96,7 +96,7 @@ private class MethodUse extends Use, QualifiableExpr { private class AccessUse extends Access, Use { AccessUse() { not this.getTarget().(Parameter).getCallable() instanceof Accessor and - not this = any(LocalVariableDeclAndInitExpr d).getLValue() and + not this = any(LocalVariableDeclAndInitExpr d).getLeftOperand() and not this.isImplicit() and not this instanceof MethodAccess and // handled by `MethodUse` not this instanceof TypeAccess and // handled by `TypeMentionUse` diff --git a/csharp/ql/lib/semmle/code/csharp/Assignable.qll b/csharp/ql/lib/semmle/code/csharp/Assignable.qll index a0e575218ad..7075626aa3b 100644 --- a/csharp/ql/lib/semmle/code/csharp/Assignable.qll +++ b/csharp/ql/lib/semmle/code/csharp/Assignable.qll @@ -235,7 +235,7 @@ private class RefArg extends AssignableAccess { module AssignableInternal { private predicate tupleAssignmentDefinition(AssignExpr ae, Expr leaf) { exists(TupleExpr te | - ae.getLValue() = te and + ae.getLeftOperand() = te and te.getAnArgument+() = leaf and // `leaf` is either an assignable access or a local variable declaration not leaf instanceof TupleExpr @@ -249,8 +249,8 @@ module AssignableInternal { */ private predicate tupleAssignmentPair(AssignExpr ae, Expr left, Expr right) { tupleAssignmentDefinition(ae, _) and - left = ae.getLValue() and - right = ae.getRValue() + left = ae.getLeftOperand() and + right = ae.getRightOperand() or exists(TupleExpr l, TupleExpr r, int i | tupleAssignmentPair(ae, l, r) | left = l.getArgument(i) and @@ -291,7 +291,7 @@ module AssignableInternal { cached newtype TAssignableDefinition = TAssignmentDefinition(Assignment a) { - not a.getLValue() instanceof TupleExpr and + not a.getLeftOperand() instanceof TupleExpr and not a instanceof AssignCallOperation and not a instanceof AssignCoalesceExpr } or @@ -358,7 +358,7 @@ module AssignableInternal { // Not defined by dispatch in order to avoid too conservative negative recursion error cached AssignableAccess getTargetAccess(AssignableDefinition def) { - def = TAssignmentDefinition(any(Assignment a | a.getLValue() = result)) + def = TAssignmentDefinition(any(Assignment a | a.getLeftOperand() = result)) or def = TTupleAssignmentDefinition(_, result) or @@ -381,8 +381,8 @@ module AssignableInternal { tupleAssignmentPair(ae, ac, result) ) or - exists(Assignment ass | ac = ass.getLValue() | - result = ass.getRValue() and + exists(Assignment ass | ac = ass.getLeftOperand() | + result = ass.getRightOperand() and not ass instanceof AssignOperation ) or @@ -527,7 +527,7 @@ module AssignableDefinitions { Assignment getAssignment() { result = a } override Expr getSource() { - result = a.getRValue() and + result = a.getRightOperand() and not a instanceof AddOrRemoveEventExpr } diff --git a/csharp/ql/lib/semmle/code/csharp/Conversion.qll b/csharp/ql/lib/semmle/code/csharp/Conversion.qll index ec7ef9cac95..fd2c680e9c7 100644 --- a/csharp/ql/lib/semmle/code/csharp/Conversion.qll +++ b/csharp/ql/lib/semmle/code/csharp/Conversion.qll @@ -232,14 +232,9 @@ private module Identity { */ pragma[nomagic] private predicate convTypeArguments(Type fromTypeArgument, Type toTypeArgument, int i) { - exists(int j | - fromTypeArgument = getTypeArgumentRanked(_, _, i) and - toTypeArgument = getTypeArgumentRanked(_, _, j) and - i <= j and - j <= i - | - convIdentity(fromTypeArgument, toTypeArgument) - ) + fromTypeArgument = getTypeArgumentRanked(_, _, pragma[only_bind_into](i)) and + toTypeArgument = getTypeArgumentRanked(_, _, pragma[only_bind_into](i)) and + convIdentity(fromTypeArgument, toTypeArgument) } pragma[nomagic] @@ -929,19 +924,16 @@ private module Variance { private predicate convTypeArguments( TypeArgument fromTypeArgument, TypeArgument toTypeArgument, int i, TVariance v ) { - exists(int j | - fromTypeArgument = getTypeArgumentRanked(_, _, i, _) and - toTypeArgument = getTypeArgumentRanked(_, _, j, _) and - i <= j and - j <= i - | + fromTypeArgument = getTypeArgumentRanked(_, _, pragma[only_bind_into](i), _) and + toTypeArgument = getTypeArgumentRanked(_, _, pragma[only_bind_into](i), _) and + ( convIdentity(fromTypeArgument, toTypeArgument) and v = TNone() or - convRefTypeTypeArgumentOut(fromTypeArgument, toTypeArgument, j) and + convRefTypeTypeArgumentOut(fromTypeArgument, toTypeArgument, i) and v = TOut() or - convRefTypeTypeArgumentIn(toTypeArgument, fromTypeArgument, j) and + convRefTypeTypeArgumentIn(toTypeArgument, fromTypeArgument, i) and v = TIn() ) } diff --git a/csharp/ql/lib/semmle/code/csharp/PrintAst.qll b/csharp/ql/lib/semmle/code/csharp/PrintAst.qll index 1ac96c85e78..1fab6b0f8c4 100644 --- a/csharp/ql/lib/semmle/code/csharp/PrintAst.qll +++ b/csharp/ql/lib/semmle/code/csharp/PrintAst.qll @@ -343,10 +343,10 @@ final class AssignmentNode extends ControlFlowElementNode { result.(TypeMentionNode).getTarget() = controlFlowElement or childIndex = 0 and - result.(ElementNode).getElement() = assignment.getLValue() + result.(ElementNode).getElement() = assignment.getLeftOperand() or childIndex = 1 and - result.(ElementNode).getElement() = assignment.getRValue() + result.(ElementNode).getElement() = assignment.getRightOperand() } } diff --git a/csharp/ql/lib/semmle/code/csharp/Property.qll b/csharp/ql/lib/semmle/code/csharp/Property.qll index bbd4fdd9d8e..c9a338d0359 100644 --- a/csharp/ql/lib/semmle/code/csharp/Property.qll +++ b/csharp/ql/lib/semmle/code/csharp/Property.qll @@ -535,8 +535,8 @@ class Setter extends Accessor, @setter { exists(AssignExpr assign | this.getStatementBody().getNumberOfStmts() = 1 and assign.getParent() = this.getStatementBody().getAChild() and - assign.getLValue() = result.getAnAccess() and - assign.getRValue() = accessToValue() + assign.getLeftOperand() = result.getAnAccess() and + assign.getRightOperand() = accessToValue() ) } diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll index 03a5aa7e2b7..6c1eb8c06eb 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll @@ -136,7 +136,7 @@ private module GuardsInput implements IdExpr() { this instanceof AssignExpr or this instanceof CastExpr } Expr getEqualChildExpr() { - result = this.(AssignExpr).getRValue() + result = this.(AssignExpr).getRightOperand() or result = this.(CastExpr).getExpr() } @@ -836,7 +836,7 @@ module Internal { /** Holds if expression `e2` is a `null` value whenever `e1` is. */ predicate nullValueImpliedUnary(Expr e1, Expr e2) { - e1 = e2.(AssignExpr).getRValue() + e1 = e2.(AssignExpr).getRightOperand() or e1 = e2.(Cast).getExpr() or @@ -923,7 +923,7 @@ module Internal { /** Holds if expression `e2` is a non-`null` value whenever `e1` is. */ predicate nonNullValueImpliedUnary(Expr e1, Expr e2) { e1 = e2.(CastExpr).getExpr() or - e1 = e2.(AssignExpr).getRValue() or + e1 = e2.(AssignExpr).getRightOperand() or e1 = e2.(NullCoalescingOperation).getAnOperand() } diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index e29e92d26eb..dc2c7477a35 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -521,7 +521,7 @@ module Expressions { // ``` // need special treatment, because the accesses `[0]`, `[1]`, and `[2]` // have no qualifier. - this = any(MemberInitializer mi).getLValue() + this = any(MemberInitializer mi).getLeftOperand() ) and not exists(AssignableDefinitions::OutRefDefinition def | def.getTargetAccess() = this) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/Nullness.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/Nullness.qll index a82779eaa5d..3d690ee1ac4 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/Nullness.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/Nullness.qll @@ -31,7 +31,7 @@ private Expr maybeNullExpr(Expr reason) { or result instanceof AsExpr and reason = result or - result.(AssignExpr).getRValue() = maybeNullExpr(reason) + result.(AssignExpr).getRightOperand() = maybeNullExpr(reason) or result.(CastExpr).getExpr() = maybeNullExpr(reason) or diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplSpecific.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplSpecific.qll index af104d777b8..ab1e75b3d0f 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplSpecific.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplSpecific.qll @@ -29,4 +29,8 @@ module CsharpDataFlow implements InputSig { predicate neverSkipInPathGraph(Node n) { exists(n.(AssignableDefinitionNode).getDefinition().getTargetAccess()) } + + DataFlowType getSourceContextParameterNodeType(Node p) { + exists(p) and result.isSourceContextParameterType() + } } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 109c27de67b..ae530b2d451 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -528,7 +528,7 @@ module LocalFlow { e2 = any(AssignExpr ae | ae.getParent() = any(ControlFlowElement cfe | not cfe instanceof ExprStmt) and - e1 = ae.getRValue() + e1 = ae.getRightOperand() ) or e1 = e2.(ObjectCreation).getInitializer() @@ -554,7 +554,7 @@ module LocalFlow { e2 = we ) or - exists(AssignExpr ae | ae.getLValue().(TupleExpr) = e2 and ae.getRValue() = e1) + exists(AssignExpr ae | ae.getLeftOperand().(TupleExpr) = e2 and ae.getRightOperand() = e1) or exists(ControlFlowElement cfe | cfe = e2.(TupleExpr).(PatternExpr).getPatternMatch() | cfe.(IsExpr).getExpr() = e1 @@ -795,7 +795,7 @@ private predicate fieldOrPropertyStore(ContentSet c, Expr src, Expr q, boolean p q = we and mi = we.getInitializer().getAMemberInitializer() and f = mi.getInitializedMember() and - src = mi.getRValue() and + src = mi.getRightOperand() and postUpdate = false ) or @@ -804,7 +804,7 @@ private predicate fieldOrPropertyStore(ContentSet c, Expr src, Expr q, boolean p mi = q.(ObjectInitializer).getAMemberInitializer() and q.getParent() instanceof ObjectCreation and f = mi.getInitializedMember() and - src = mi.getRValue() and + src = mi.getRightOperand() and postUpdate = false ) or @@ -879,8 +879,8 @@ private predicate arrayStore(Expr src, Expr a, boolean postUpdate) { // Member initializer, `new C { Array = { [i] = src } }` exists(MemberInitializer mi | mi = a.(ObjectInitializer).getAMemberInitializer() and - mi.getLValue() instanceof ArrayAccess and - mi.getRValue() = src and + mi.getLeftOperand() instanceof ArrayAccess and + mi.getRightOperand() = src and postUpdate = false ) } @@ -1179,7 +1179,8 @@ private module Cached { cached newtype TDataFlowType = TGvnDataFlowType(Gvn::GvnType t) or - TDelegateDataFlowType(Callable lambda) { lambdaCreationExpr(_, lambda) } + TDelegateDataFlowType(Callable lambda) { lambdaCreationExpr(_, lambda) } or + TSourceContextParameterType() } import Cached @@ -2394,6 +2395,8 @@ class DataFlowType extends TDataFlowType { Callable asDelegate() { this = TDelegateDataFlowType(result) } + predicate isSourceContextParameterType() { this = TSourceContextParameterType() } + /** * Gets an expression that creates a delegate of this type. * @@ -2412,6 +2415,9 @@ class DataFlowType extends TDataFlowType { result = this.asGvnType().toString() or result = this.asDelegate().toString() + or + this.isSourceContextParameterType() and + result = "" } } @@ -2469,6 +2475,11 @@ private predicate compatibleTypesDelegateLeft(DataFlowType dt1, DataFlowType dt2 ) } +pragma[nomagic] +private predicate compatibleTypesSourceContextParameterTypeLeft(DataFlowType dt1, DataFlowType dt2) { + dt1.isSourceContextParameterType() and not exists(dt2.asDelegate()) +} + /** * Holds if `t1` and `t2` are compatible, that is, whether data can flow from * a node of type `t1` to a node of type `t2`. @@ -2499,6 +2510,10 @@ predicate compatibleTypes(DataFlowType dt1, DataFlowType dt2) { compatibleTypesDelegateLeft(dt2, dt1) or dt1.asDelegate() = dt2.asDelegate() + or + compatibleTypesSourceContextParameterTypeLeft(dt1, dt2) + or + compatibleTypesSourceContextParameterTypeLeft(dt2, dt1) } pragma[nomagic] @@ -2511,6 +2526,8 @@ predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { uselessTypebound(t2) or compatibleTypesDelegateLeft(t1, t2) + or + compatibleTypesSourceContextParameterTypeLeft(t1, t2) } /** @@ -2582,7 +2599,7 @@ module PostUpdateNodes { call.getExpr() = init.(CollectionInitializer).getAnElementInitializer() or // E.g. `new Dictionary() { [0] = "a", [1] = "b" }` - call.getExpr() = init.(ObjectInitializer).getAMemberInitializer().getLValue() + call.getExpr() = init.(ObjectInitializer).getAMemberInitializer().getLeftOperand() ) } @@ -2795,7 +2812,7 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves preservesValue = true or exists(AddEventExpr aee | - nodeFrom.asExpr() = aee.getRValue() and + nodeFrom.asExpr() = aee.getRightOperand() and nodeTo.asExpr().(EventRead).getTarget() = aee.getTarget() and preservesValue = false ) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImpl.qll index 2809f8187b9..83593a5df36 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/SsaImpl.qll @@ -337,7 +337,7 @@ private module CallGraph { pred = succ.(DelegateCreation).getArgument() or exists(AddEventExpr ae | succ.(EventAccess).getTarget() = ae.getTarget() | - pred = ae.getRValue() + pred = ae.getRightOperand() ) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll index 46153f18dae..171f2d2f59e 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/RangeUtils.qll @@ -21,7 +21,7 @@ private module Impl { /** Holds if SSA definition `def` equals `e + delta`. */ predicate ssaUpdateStep(ExplicitDefinition def, ExprNode e, int delta) { exists(ControlFlow::Node cfn | cfn = def.getControlFlowNode() | - e = cfn.(ExprNode::Assignment).getRValue() and + e = cfn.(ExprNode::Assignment).getRightOperand() and delta = 0 and not cfn instanceof ExprNode::AssignOperation or @@ -39,7 +39,7 @@ private module Impl { /** Holds if `e1 + delta` equals `e2`. */ predicate valueFlowStep(ExprNode e2, ExprNode e1, int delta) { - e2.(ExprNode::AssignExpr).getRValue() = e1 and delta = 0 + e2.(ExprNode::AssignExpr).getRightOperand() = e1 and delta = 0 or e2.(ExprNode::UnaryPlusExpr).getOperand() = e1 and delta = 0 or @@ -207,13 +207,13 @@ module ExprNode { override CS::Assignment e; /** Gets the left operand of this assignment. */ - ExprNode getLValue() { - result = unique(ExprNode res | hasChild(e, e.getLValue(), this, res) | res) + ExprNode getLeftOperand() { + result = unique(ExprNode res | hasChild(e, e.getLeftOperand(), this, res) | res) } /** Gets the right operand of this assignment. */ - ExprNode getRValue() { - result = unique(ExprNode res | hasChild(e, e.getRValue(), this, res) | res) + ExprNode getRightOperand() { + result = unique(ExprNode res | hasChild(e, e.getRightOperand(), this, res) | res) } } @@ -225,6 +225,10 @@ module ExprNode { /** A compound assignment operation. */ class AssignOperation extends Assignment, BinaryOperation { override CS::AssignOperation e; + + override ExprNode getLeftOperand() { result = Assignment.super.getLeftOperand() } + + override ExprNode getRightOperand() { result = Assignment.super.getRightOperand() } } /** A unary operation. */ diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll index d59d7958765..f64eceda134 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SignAnalysisSpecific.qll @@ -168,7 +168,7 @@ private module Impl { /** Returned an expression that is assigned to `f`. */ ExprNode getAssignedValueToField(Field f) { result.getExpr() in [ - f.getAnAssignedValue(), any(AssignOperation a | a.getLValue() = f.getAnAccess()) + f.getAnAssignedValue(), any(AssignOperation a | a.getLeftOperand() = f.getAnAccess()) ] } @@ -231,7 +231,7 @@ private module Impl { /** Returns a sub expression of `e` for expression types where the sign depends on the child. */ ExprNode getASubExprWithSameSign(ExprNode e) { exists(Expr e_, Expr child | hasChild(e_, child, e, result) | - child = e_.(AssignExpr).getRValue() or + child = e_.(AssignExpr).getRightOperand() or child = e_.(UnaryPlusExpr).getOperand() or child = e_.(PostIncrExpr).getOperand() or child = e_.(PostDecrExpr).getOperand() or diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaUtils.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaUtils.qll index 89117d90ba7..cf4b44239e9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaUtils.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaUtils.qll @@ -55,5 +55,5 @@ ExprNode ssaRead(Definition v, int delta) { or v.(ExplicitDefinition).getControlFlowNode().(ExprNode::Assignment) = result and delta = 0 or - result.(ExprNode::AssignExpr).getRValue() = ssaRead(v, delta) + result.(ExprNode::AssignExpr).getRightOperand() = ssaRead(v, delta) } diff --git a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll index f7f6c7a50be..770fab65f54 100644 --- a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll +++ b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll @@ -1348,7 +1348,7 @@ private module Internal { any(DynamicMemberAccess dma | this = TDispatchDynamicEventAccess(_, dma, _)).getQualifier() } - override Expr getArgument(int i) { i = 0 and result = this.getCall().getRValue() } + override Expr getArgument(int i) { i = 0 and result = this.getCall().getRightOperand() } } /** A call to a constructor using dynamic types. */ diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Access.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Access.qll index 84375bc7013..d9fb16f0974 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Access.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Access.qll @@ -112,7 +112,7 @@ class BaseAccess extends Access, @base_access_expr { class MemberAccess extends Access, QualifiableExpr, @member_access_expr { override predicate hasImplicitThisQualifier() { QualifiableExpr.super.hasImplicitThisQualifier() and - not exists(MemberInitializer mi | mi.getLValue() = this) + not exists(MemberInitializer mi | mi.getLeftOperand() = this) } override Member getQualifiedDeclaration() { result = this.getTarget() } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll index 467149011d2..8c7dd80da24 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll @@ -20,14 +20,22 @@ class Assignment extends BinaryOperation, @assign_expr { expr_parent(_, 1, this) } - /** Gets the left operand of this assignment. */ - Expr getLValue() { result = this.getLeftOperand() } + /** + * DEPRECATED: Use `getLeftOperand` instead. + * + * Gets the left operand of this assignment. + */ + deprecated Expr getLValue() { result = this.getLeftOperand() } - /** Gets the right operand of this assignment. */ - Expr getRValue() { result = this.getRightOperand() } + /** + * DEPRECATED: Use `getRightOperand` instead. + * + * Gets the right operand of this assignment. + */ + deprecated Expr getRValue() { result = this.getRightOperand() } /** Gets the variable being assigned to, if any. */ - Variable getTargetVariable() { result.getAnAccess() = this.getLValue() } + Variable getTargetVariable() { result.getAnAccess() = this.getLeftOperand() } override string getOperator() { none() } } @@ -40,7 +48,12 @@ class LocalVariableDeclAndInitExpr extends LocalVariableDeclExpr, Assignment { override LocalVariable getTargetVariable() { result = this.getVariable() } - override LocalVariableAccess getLValue() { result = Assignment.super.getLValue() } + /** + * DEPRECATED: Use `getLeftOperand` instead. + */ + deprecated override LocalVariableAccess getLValue() { result = this.getLeftOperand() } + + override LocalVariableAccess getLeftOperand() { result = Assignment.super.getLeftOperand() } override string toString() { result = LocalVariableDeclExpr.super.toString() + " = ..." } @@ -223,9 +236,12 @@ deprecated class AssignUnsighedRightShiftExpr = AssignUnsignedRightShiftExpr; */ class AddOrRemoveEventExpr extends AssignOperation, @assign_event_expr { /** Gets the event targeted by this event assignment. */ - Event getTarget() { result = this.getLValue().getTarget() } + Event getTarget() { result = this.getLeftOperand().getTarget() } - override EventAccess getLValue() { result = this.getChild(0) } + /** + * DEPRECATED: Use `getLeftOperand` instead. + */ + deprecated override EventAccess getLValue() { result = this.getLeftOperand() } override EventAccess getLeftOperand() { result = this.getChild(0) } } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Call.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Call.qll index 0d9e414a5c4..272a8e0caae 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Call.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Call.qll @@ -773,7 +773,7 @@ class EventCall extends AccessorCall, EventAccessExpr { override EventAccessor getTarget() { exists(Event e, AddOrRemoveEventExpr aoree | e = this.getEvent() and - aoree.getLValue() = this + aoree.getLeftOperand() = this | aoree instanceof AddEventExpr and result = e.getAddEventAccessor() or @@ -784,8 +784,8 @@ class EventCall extends AccessorCall, EventAccessExpr { override Expr getArgument(int i) { i = 0 and exists(AddOrRemoveEventExpr aoree | - aoree.getLValue() = this and - result = aoree.getRValue() + aoree.getLeftOperand() = this and + result = aoree.getRightOperand() ) } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Creation.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Creation.qll index 0e16e0da9c3..19ff9fac53b 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Creation.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Creation.qll @@ -95,7 +95,7 @@ class MemberInitializer extends AssignExpr { MemberInitializer() { this.getParent() instanceof ObjectInitializer } /** Gets the initialized member. */ - Member getInitializedMember() { result.getAnAccess() = this.getLValue() } + Member getInitializedMember() { result.getAnAccess() = this.getLeftOperand() } override string getAPrimaryQlClass() { result = "MemberInitializer" } } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll index 66764d06479..36eda82531c 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll @@ -1099,7 +1099,7 @@ class QualifiableExpr extends Expr, @qualifiable_expr { } private Expr getAnAssignOrForeachChild() { - result = any(AssignExpr e).getLValue() + result = any(AssignExpr e).getLeftOperand() or result = any(ForeachStmt fs).getVariableDeclTuple() or diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Moq.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Moq.qll index 9ab9a026fd2..0beec9a84b2 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Moq.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Moq.qll @@ -41,6 +41,6 @@ class ReturnedByMockObject extends ObjectCreation { * Gets a value used to initialize a member of this object creation. */ Expr getAMemberInitializationValue() { - result = this.getInitializer().(ObjectInitializer).getAMemberInitializer().getRValue() + result = this.getInitializer().(ObjectInitializer).getAMemberInitializer().getRightOperand() } } diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Sql.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Sql.qll index 6b1eb7b67fb..58d6d68bf0e 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Sql.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Sql.qll @@ -17,14 +17,14 @@ abstract class SqlExpr extends Expr { class CommandTextAssignmentSqlExpr extends SqlExpr, AssignExpr { CommandTextAssignmentSqlExpr() { exists(Property p, SystemDataIDbCommandInterface i, Property text | - p = this.getLValue().(PropertyAccess).getTarget() and + p = this.getLeftOperand().(PropertyAccess).getTarget() and text = i.getCommandTextProperty() | p.overridesOrImplementsOrEquals(text) ) } - override Expr getSql() { result = this.getRValue() } + override Expr getSql() { result = this.getRightOperand() } } /** A construction of an unknown `IDbCommand` object. */ diff --git a/csharp/ql/lib/semmle/code/csharp/security/auth/SecureCookies.qll b/csharp/ql/lib/semmle/code/csharp/security/auth/SecureCookies.qll index 56b6294949b..e7cb6d8e308 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/auth/SecureCookies.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/auth/SecureCookies.qll @@ -100,20 +100,20 @@ Expr getAValueForCookiePolicyProp(string prop) { Expr getAValueForProp(ObjectCreation create, Assignment a, string prop) { // values set in object init exists(MemberInitializer init, Expr src, PropertyAccess pa | - a.getLValue() = pa and + a.getLeftOperand() = pa and pa.getTarget().hasName(prop) and init = create.getInitializer().(ObjectInitializer).getAMemberInitializer() and - init.getLValue() = pa and - DataFlow::localExprFlow(src, init.getRValue()) and + init.getLeftOperand() = pa and + DataFlow::localExprFlow(src, init.getRightOperand()) and result = src ) or // values set on var that create is assigned to exists(Expr src, PropertyAccess pa | - a.getLValue() = pa and + a.getLeftOperand() = pa and pa.getTarget().hasName(prop) and DataFlow::localExprFlow(create, pa.getQualifier()) and - DataFlow::localExprFlow(src, a.getRValue()) and + DataFlow::localExprFlow(src, a.getRightOperand()) and result = src ) } @@ -138,15 +138,15 @@ private module OnAppendCookieTrackingConfig impl exists(PropertyWrite pw, Assignment delegateAssign, Callable c | pw.getProperty().getName() = "OnAppendCookie" and pw.getProperty().getDeclaringType() instanceof MicrosoftAspNetCoreBuilderCookiePolicyOptions and - delegateAssign.getLValue() = pw and + delegateAssign.getLeftOperand() = pw and ( exists(LambdaExpr lambda | - delegateAssign.getRValue() = lambda and + delegateAssign.getRightOperand() = lambda and lambda = c ) or exists(DelegateCreation delegate | - delegateAssign.getRValue() = delegate and + delegateAssign.getRightOperand() = delegate and delegate.getArgument().(CallableAccess).getTarget() = c ) ) and @@ -159,9 +159,9 @@ private module OnAppendCookieTrackingConfig impl exists(PropertyWrite pw, Assignment a | pw.getProperty().getDeclaringType() instanceof MicrosoftAspNetCoreHttpCookieOptions and pw.getProperty().getName() = getPropertyName() and - a.getLValue() = pw and + a.getLeftOperand() = pw and exists(Expr val | - DataFlow::localExprFlow(val, a.getRValue()) and + DataFlow::localExprFlow(val, a.getRightOperand()) and val.getValue() = "true" ) and sink.asExpr() = pw.getQualifier() diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll index 5b2bd407a5c..3c8911ef807 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll @@ -126,16 +126,16 @@ private module TypeNameTrackingConfig implements DataFlow::ConfigSig { or node1.getType() instanceof TypeNameHandlingEnum and exists(PropertyWrite pw, Property p, Assignment a | - a.getLValue() = pw and + a.getLeftOperand() = pw and pw.getProperty() = p and p.getDeclaringType() instanceof JsonSerializerSettingsClass and p.hasName("TypeNameHandling") and ( - node1.asExpr() = a.getRValue() and + node1.asExpr() = a.getRightOperand() and node2.asExpr() = pw.getQualifier() or exists(ObjectInitializer oi | - node1.asExpr() = oi.getAMemberInitializer().getRValue() and + node1.asExpr() = oi.getAMemberInitializer().getRightOperand() and node2.asExpr() = oi ) ) diff --git a/csharp/ql/lib/semmle/code/csharp/security/xml/InsecureXMLQuery.qll b/csharp/ql/lib/semmle/code/csharp/security/xml/InsecureXMLQuery.qll index 1abeaf797b0..765dc2adf54 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/xml/InsecureXMLQuery.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/xml/InsecureXMLQuery.qll @@ -84,15 +84,15 @@ private Expr getAValueForProp(ObjectCreation create, string prop) { // values set in object init exists(MemberInitializer init | init = create.getInitializer().(ObjectInitializer).getAMemberInitializer() and - init.getLValue().(PropertyAccess).getTarget().hasName(prop) and - result = init.getRValue() + init.getLeftOperand().(PropertyAccess).getTarget().hasName(prop) and + result = init.getRightOperand() ) or // values set on var that create is assigned to exists(Assignment propAssign | - DataFlow::localExprFlow(create, propAssign.getLValue().(PropertyAccess).getQualifier()) and - propAssign.getLValue().(PropertyAccess).getTarget().hasName(prop) and - result = propAssign.getRValue() + DataFlow::localExprFlow(create, propAssign.getLeftOperand().(PropertyAccess).getQualifier()) and + propAssign.getLeftOperand().(PropertyAccess).getTarget().hasName(prop) and + result = propAssign.getRightOperand() ) } diff --git a/csharp/ql/src/Dead Code/NonAssignedFields.ql b/csharp/ql/src/Dead Code/NonAssignedFields.ql index 83aa889b77c..b9e86809749 100644 --- a/csharp/ql/src/Dead Code/NonAssignedFields.ql +++ b/csharp/ql/src/Dead Code/NonAssignedFields.ql @@ -84,9 +84,9 @@ where not f.getDeclaringType() instanceof Enum and not f.getType() instanceof Struct and not exists(Assignment ae, Field g | - ae.getLValue().(FieldAccess).getTarget() = g and + ae.getLeftOperand().(FieldAccess).getTarget() = g and g.getUnboundDeclaration() = f and - not ae.getRValue() instanceof NullLiteral + not ae.getRightOperand() instanceof NullLiteral ) and not exists(MethodCall mc, int i, Field g | exists(Parameter p | mc.getTarget().getParameter(i) = p | p.isOut() or p.isRef()) and @@ -101,7 +101,7 @@ where not init instanceof NullLiteral ) and not exists(AssignOperation ua, Field g | - ua.getLValue().(FieldAccess).getTarget() = g and + ua.getLeftOperand().(FieldAccess).getTarget() = g and g.getUnboundDeclaration() = f ) and not exists(MutatorOperation op | diff --git a/csharp/ql/src/Language Abuse/ForeachCapture.ql b/csharp/ql/src/Language Abuse/ForeachCapture.ql index 03f1f99a044..2ed24b42eba 100644 --- a/csharp/ql/src/Language Abuse/ForeachCapture.ql +++ b/csharp/ql/src/Language Abuse/ForeachCapture.ql @@ -60,16 +60,16 @@ module LambdaDataFlow { } Element getAssignmentTarget(Expr e) { - exists(Assignment a | a.getRValue() = e | - result = a.getLValue().(PropertyAccess).getTarget() or - result = a.getLValue().(FieldAccess).getTarget() or - result = a.getLValue().(LocalVariableAccess).getTarget() or - result = a.getLValue().(EventAccess).getTarget() + exists(Assignment a | a.getRightOperand() = e | + result = a.getLeftOperand().(PropertyAccess).getTarget() or + result = a.getLeftOperand().(FieldAccess).getTarget() or + result = a.getLeftOperand().(LocalVariableAccess).getTarget() or + result = a.getLeftOperand().(EventAccess).getTarget() ) or exists(AddEventExpr aee | - e = aee.getRValue() and - result = aee.getLValue().getTarget() + e = aee.getRightOperand() and + result = aee.getLeftOperand().getTarget() ) or result = getCollectionAssignmentTarget(e) @@ -97,8 +97,8 @@ Element getCollectionAssignmentTarget(Expr e) { // Store values using indexer exists(IndexerAccess ia, AssignExpr ae | ia.getQualifier() = result.(Variable).getAnAccess() and - ia = ae.getLValue() and - e = ae.getRValue() + ia = ae.getLeftOperand() and + e = ae.getRightOperand() ) } diff --git a/csharp/ql/src/Language Abuse/MissedTernaryOpportunity.ql b/csharp/ql/src/Language Abuse/MissedTernaryOpportunity.ql index bd7492b8583..01d6baa9573 100644 --- a/csharp/ql/src/Language Abuse/MissedTernaryOpportunity.ql +++ b/csharp/ql/src/Language Abuse/MissedTernaryOpportunity.ql @@ -15,7 +15,7 @@ import csharp import semmle.code.csharp.commons.StructuralComparison private Expr getAssignedExpr(Stmt stmt) { - result = stmt.stripSingletonBlocks().(ExprStmt).getExpr().(AssignExpr).getLValue() + result = stmt.stripSingletonBlocks().(ExprStmt).getExpr().(AssignExpr).getLeftOperand() } from IfStmt is, string what diff --git a/csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql b/csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql index 5fcb140e679..046099213cc 100644 --- a/csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql +++ b/csharp/ql/src/Likely Bugs/Collections/WriteOnlyContainer.ql @@ -23,9 +23,10 @@ where ) and forex(Access a | a = v.getAnAccess() | a = any(ModifierMethodCall m).getQualifier() or - a = any(AssignExpr ass | ass.getRValue() instanceof ObjectCreation).getLValue() or + a = any(AssignExpr ass | ass.getRightOperand() instanceof ObjectCreation).getLeftOperand() or a = - any(LocalVariableDeclAndInitExpr ass | ass.getRValue() instanceof ObjectCreation).getLValue() + any(LocalVariableDeclAndInitExpr ass | ass.getRightOperand() instanceof ObjectCreation) + .getLeftOperand() ) and not v = any(ForeachStmt fs).getVariable() and not v = any(BindingPatternExpr vpe).getVariableDeclExpr().getVariable() and diff --git a/csharp/ql/src/Likely Bugs/SelfAssignment.ql b/csharp/ql/src/Likely Bugs/SelfAssignment.ql index f01a1378242..6e51b87a779 100644 --- a/csharp/ql/src/Likely Bugs/SelfAssignment.ql +++ b/csharp/ql/src/Likely Bugs/SelfAssignment.ql @@ -19,7 +19,7 @@ private predicate candidate(AssignExpr ae) { not ae instanceof MemberInitializer and // Enum field initializers are never self assignments. `enum E { A = 42 }` not ae.getParent().(Field).getDeclaringType() instanceof Enum and - forall(Expr e | e = ae.getLValue().getAChildExpr*() | + forall(Expr e | e = ae.getLeftOperand().getAChildExpr*() | // Non-trivial property accesses may have side-effects, // so these are not considered e instanceof PropertyAccess implies e instanceof TrivialPropertyAccess @@ -28,7 +28,7 @@ private predicate candidate(AssignExpr ae) { private predicate selfAssignExpr(AssignExpr ae) { candidate(ae) and - sameGvn(ae.getLValue(), ae.getRValue()) + sameGvn(ae.getLeftOperand(), ae.getRightOperand()) } private Declaration getDeclaration(Expr e) { @@ -40,5 +40,5 @@ private Declaration getDeclaration(Expr e) { } from AssignExpr ae, Declaration target -where selfAssignExpr(ae) and target = getDeclaration(ae.getLValue()) +where selfAssignExpr(ae) and target = getDeclaration(ae.getLeftOperand()) select ae, "This assignment assigns $@ to itself.", target, target.getName() diff --git a/csharp/ql/src/Linq/BadMultipleIteration.ql b/csharp/ql/src/Linq/BadMultipleIteration.ql index 8146bbf167d..0f9e335e225 100644 --- a/csharp/ql/src/Linq/BadMultipleIteration.ql +++ b/csharp/ql/src/Linq/BadMultipleIteration.ql @@ -50,7 +50,7 @@ predicate potentiallyConsumingAccess(VariableAccess va) { Expr sequenceSource(IEnumerableSequence seq) { result = seq.getInitializer() or - exists(Assignment a | a.getLValue() = seq.getAnAccess() and result = a.getRValue()) + exists(Assignment a | a.getLeftOperand() = seq.getAnAccess() and result = a.getRightOperand()) } from IEnumerableSequence seq, VariableAccess va diff --git a/csharp/ql/src/Performance/StringConcatenationInLoop.ql b/csharp/ql/src/Performance/StringConcatenationInLoop.ql index 3b3228588a4..d27b99e7bdd 100644 --- a/csharp/ql/src/Performance/StringConcatenationInLoop.ql +++ b/csharp/ql/src/Performance/StringConcatenationInLoop.ql @@ -24,7 +24,7 @@ class StringCat extends AddExpr { */ predicate isSelfConcatAssignExpr(AssignExpr e, Variable v) { exists(VariableAccess use | - stringCatContains(e.getRValue(), use) and + stringCatContains(e.getRightOperand(), use) and use.getTarget() = e.getTargetVariable() and v = use.getTarget() ) @@ -41,7 +41,7 @@ predicate stringCatContains(StringCat expr, Expr child) { * where `v` is a simple variable (and not, for example, a property). */ predicate isConcatExpr(AssignAddExpr e, Variable v) { - e.getLValue().getType() instanceof StringType and + e.getLeftOperand().getType() instanceof StringType and v = e.getTargetVariable() } diff --git a/csharp/ql/src/Security Features/CWE-1004/CookieWithoutHttpOnly.ql b/csharp/ql/src/Security Features/CWE-1004/CookieWithoutHttpOnly.ql index dcc520540bb..f72de01b5db 100644 --- a/csharp/ql/src/Security Features/CWE-1004/CookieWithoutHttpOnly.ql +++ b/csharp/ql/src/Security Features/CWE-1004/CookieWithoutHttpOnly.ql @@ -27,8 +27,8 @@ predicate cookieAppendHttpOnlyByDefault() { predicate httpOnlyFalse(ObjectCreation oc) { exists(Assignment a | - getAValueForProp(oc, a, "HttpOnly") = a.getRValue() and - a.getRValue().getValue() = "false" + getAValueForProp(oc, a, "HttpOnly") = a.getRightOperand() and + a.getRightOperand().getValue() = "false" ) } @@ -100,8 +100,8 @@ predicate nonHttpOnlyCookieBuilderAssignment(Assignment a, Expr val) { MicrosoftAspNetCoreAuthenticationCookiesCookieAuthenticationOptions ) and pw.getProperty().getName() = "HttpOnly" and - a.getLValue() = pw and - DataFlow::localExprFlow(val, a.getRValue()) + a.getLeftOperand() = pw and + DataFlow::localExprFlow(val, a.getRightOperand()) ) } @@ -111,7 +111,7 @@ where nonHttpOnlyCookieCall(httpOnlySink) or exists(Assignment a | - httpOnlySink = a.getRValue() and + httpOnlySink = a.getRightOperand() and nonHttpOnlyCookieBuilderAssignment(a, _) ) ) diff --git a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql index 330ad1c1c32..a1dd249faba 100644 --- a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql +++ b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql @@ -35,8 +35,8 @@ module InsecureSqlConnectionConfig implements DataFlow::ConfigSig { ) and not exists(MemberInitializer mi | mi = oc.getInitializer().(ObjectInitializer).getAMemberInitializer() and - mi.getLValue().(PropertyAccess).getTarget().getName() = "Encrypt" and - mi.getRValue().(BoolLiteral).getValue() = "true" + mi.getLeftOperand().(PropertyAccess).getTarget().getName() = "Encrypt" and + mi.getRightOperand().(BoolLiteral).getValue() = "true" ) ) } diff --git a/csharp/ql/src/Security Features/CWE-614/CookieWithoutSecure.ql b/csharp/ql/src/Security Features/CWE-614/CookieWithoutSecure.ql index ce1f75d627c..1149b4bcad2 100644 --- a/csharp/ql/src/Security Features/CWE-614/CookieWithoutSecure.ql +++ b/csharp/ql/src/Security Features/CWE-614/CookieWithoutSecure.ql @@ -31,8 +31,8 @@ predicate cookieAppendSecureByDefault() { predicate secureFalse(ObjectCreation oc) { exists(Assignment a | - getAValueForProp(oc, a, "Secure") = a.getRValue() and - a.getRValue().getValue() = "false" + getAValueForProp(oc, a, "Secure") = a.getRightOperand() and + a.getRightOperand().getValue() = "false" ) } @@ -96,8 +96,8 @@ predicate insecureSecurePolicyAssignment(Assignment a, Expr val) { MicrosoftAspNetCoreAuthenticationCookiesCookieAuthenticationOptions ) and pw.getProperty().getName() = "SecurePolicy" and - a.getLValue() = pw and - DataFlow::localExprFlow(val, a.getRValue()) and + a.getLeftOperand() = pw and + DataFlow::localExprFlow(val, a.getRightOperand()) and val.getValue() = "2" // None ) } @@ -107,7 +107,7 @@ where insecureCookieCall(secureSink) or exists(Assignment a | - secureSink = a.getRValue() and + secureSink = a.getRightOperand() and insecureSecurePolicyAssignment(a, _) ) select secureSink, "Cookie attribute 'Secure' is not set to true." diff --git a/csharp/ql/src/Security Features/CookieWithOverlyBroadDomain.ql b/csharp/ql/src/Security Features/CookieWithOverlyBroadDomain.ql index 9c6e6935186..59a6340104a 100644 --- a/csharp/ql/src/Security Features/CookieWithOverlyBroadDomain.ql +++ b/csharp/ql/src/Security Features/CookieWithOverlyBroadDomain.ql @@ -14,11 +14,11 @@ import csharp from Assignment a, PropertyAccess pa where - a.getLValue() = pa and + a.getLeftOperand() = pa and pa.getTarget().hasName("Domain") and pa.getTarget().getDeclaringType().hasFullyQualifiedName("System.Web", "HttpCookie") and ( - a.getRValue().getValue().regexpReplaceAll("[^.]", "").length() < 2 or - a.getRValue().getValue().matches(".%") + a.getRightOperand().getValue().regexpReplaceAll("[^.]", "").length() < 2 or + a.getRightOperand().getValue().matches(".%") ) select a, "Overly broad domain for cookie." diff --git a/csharp/ql/src/Security Features/CookieWithOverlyBroadPath.ql b/csharp/ql/src/Security Features/CookieWithOverlyBroadPath.ql index 6690cac47d2..d659f7c8dc5 100644 --- a/csharp/ql/src/Security Features/CookieWithOverlyBroadPath.ql +++ b/csharp/ql/src/Security Features/CookieWithOverlyBroadPath.ql @@ -14,8 +14,8 @@ import csharp from Assignment a, PropertyAccess pa where - a.getLValue() = pa and + a.getLeftOperand() = pa and pa.getTarget().hasName("Path") and pa.getTarget().getDeclaringType().hasFullyQualifiedName("System.Web", "HttpCookie") and - a.getRValue().getValue() = "/" + a.getRightOperand().getValue() = "/" select a, "Overly broad path for cookie." diff --git a/csharp/ql/src/Security Features/HeaderCheckingDisabled.ql b/csharp/ql/src/Security Features/HeaderCheckingDisabled.ql index 7a3a5fdc4f2..bc9bf289c2d 100644 --- a/csharp/ql/src/Security Features/HeaderCheckingDisabled.ql +++ b/csharp/ql/src/Security Features/HeaderCheckingDisabled.ql @@ -17,12 +17,12 @@ from Element l where // header checking is disabled programmatically in the code exists(Assignment a, PropertyAccess pa | - a.getLValue() = pa and + a.getLeftOperand() = pa and pa.getTarget().hasName("EnableHeaderChecking") and pa.getTarget() .getDeclaringType() .hasFullyQualifiedName("System.Web.Configuration", "HttpRuntimeSection") and - a.getRValue().getValue() = "false" and + a.getRightOperand().getValue() = "false" and a = l ) or diff --git a/csharp/ql/src/Security Features/InsecureRandomness.ql b/csharp/ql/src/Security Features/InsecureRandomness.ql index 8237afdff13..649969a2778 100644 --- a/csharp/ql/src/Security Features/InsecureRandomness.ql +++ b/csharp/ql/src/Security Features/InsecureRandomness.ql @@ -89,10 +89,10 @@ module Random { e = any(SensitiveLibraryParameter v).getAnAssignedArgument() or // Assignment operation, e.g. += or similar - exists(AssignOperation ao | ao.getRValue() = e | - ao.getLValue() = any(SensitiveVariable v).getAnAccess() or - ao.getLValue() = any(SensitiveProperty v).getAnAccess() or - ao.getLValue() = any(SensitiveLibraryParameter v).getAnAccess() + exists(AssignOperation ao | ao.getRightOperand() = e | + ao.getLeftOperand() = any(SensitiveVariable v).getAnAccess() or + ao.getLeftOperand() = any(SensitiveProperty v).getAnAccess() or + ao.getLeftOperand() = any(SensitiveLibraryParameter v).getAnAccess() ) ) } diff --git a/csharp/ql/src/Security Features/InsufficientKeySize.ql b/csharp/ql/src/Security Features/InsufficientKeySize.ql index 94ae6b9286f..02be9125835 100644 --- a/csharp/ql/src/Security Features/InsufficientKeySize.ql +++ b/csharp/ql/src/Security Features/InsufficientKeySize.ql @@ -20,7 +20,7 @@ predicate incorrectUseOfRC2(Assignment e, string msg) { .getDeclaringType() .hasFullyQualifiedName("System.Security.Cryptography", "RC2CryptoServiceProvider") ) and - e.getRValue().getValue().toInt() < 128 and + e.getRightOperand().getValue().toInt() < 128 and msg = "Key size should be at least 128 bits for RC2 encryption." } diff --git a/csharp/ql/src/Security Features/PersistentCookie.ql b/csharp/ql/src/Security Features/PersistentCookie.ql index 7f9861213fc..edc97b464e5 100644 --- a/csharp/ql/src/Security Features/PersistentCookie.ql +++ b/csharp/ql/src/Security Features/PersistentCookie.ql @@ -52,8 +52,8 @@ class FutureDateExpr extends MethodCall { from Assignment a, PropertyAccess pa, FutureDateExpr fde where - a.getLValue() = pa and - a.getRValue() = fde and + a.getLeftOperand() = pa and + a.getRightOperand() = fde and pa.getTarget().hasName("Expires") and pa.getTarget().getDeclaringType().hasFullyQualifiedName("System.Web", "HttpCookie") and (fde.timeIsNotClear() or fde.getTimeInSecond() > 300) // 5 minutes max diff --git a/csharp/ql/src/Telemetry/DatabaseQuality.qll b/csharp/ql/src/Telemetry/DatabaseQuality.qll index ca2ab3e7e16..ad7ac682bf5 100644 --- a/csharp/ql/src/Telemetry/DatabaseQuality.qll +++ b/csharp/ql/src/Telemetry/DatabaseQuality.qll @@ -27,7 +27,7 @@ module CallTargetStats implements StatsSig { p = c.getProperty() and not p.getAnAccessor() instanceof Setter and assign = c.getParent() and - assign.getLValue() = c and + assign.getLeftOperand() = c and assign.getParent() instanceof Property ) } @@ -36,7 +36,7 @@ module CallTargetStats implements StatsSig { exists(Property p, AssignExpr assign | p = c.getProperty() and assign = c.getParent() and - assign.getLValue() = c and + assign.getLeftOperand() = c and assign.getParent() instanceof ObjectInitializer and assign.getParent().getParent() instanceof AnonymousObjectCreation ) @@ -46,8 +46,8 @@ module CallTargetStats implements StatsSig { exists(Property p, AssignExpr assign | p = c.getProperty() and assign = c.getParent() and - assign.getLValue() = c and - assign.getRValue() instanceof ObjectOrCollectionInitializer + assign.getLeftOperand() = c and + assign.getRightOperand() instanceof ObjectOrCollectionInitializer ) } diff --git a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql index d43050c2deb..0dc8fc362d6 100644 --- a/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql +++ b/csharp/ql/src/experimental/Security Features/CWE-759/HashWithoutSalt.ql @@ -187,10 +187,10 @@ module HashWithoutSaltConfig implements DataFlow::ConfigSig { or // a salt or key is included in subclasses of `KeyedHashAlgorithm` exists(MethodCall mc, Assignment a, ObjectCreation oc | - a.getRValue() = oc and + a.getRightOperand() = oc and oc.getObjectType().getABaseType+() instanceof KeyedHashAlgorithm and mc.getTarget() instanceof HashMethod and - a.getLValue() = mc.getQualifier().(VariableAccess).getTarget().getAnAccess() and + a.getLeftOperand() = mc.getQualifier().(VariableAccess).getTarget().getAnAccess() and mc.getArgument(0) = node.asExpr() ) } diff --git a/csharp/ql/test/library-tests/assignments/AssignOperation.ql b/csharp/ql/test/library-tests/assignments/AssignOperation.ql index 2ca3b11a831..2fa23ed0a9f 100644 --- a/csharp/ql/test/library-tests/assignments/AssignOperation.ql +++ b/csharp/ql/test/library-tests/assignments/AssignOperation.ql @@ -1,4 +1,4 @@ import csharp from AssignOperation ao -select ao, ao.getLValue(), ao.getRValue() +select ao, ao.getLeftOperand(), ao.getRightOperand() diff --git a/csharp/ql/test/library-tests/conversion/pointer/Pointer.ql b/csharp/ql/test/library-tests/conversion/pointer/Pointer.ql index 69e7db8c1cf..450ed9940a8 100644 --- a/csharp/ql/test/library-tests/conversion/pointer/Pointer.ql +++ b/csharp/ql/test/library-tests/conversion/pointer/Pointer.ql @@ -1,5 +1,5 @@ import csharp from Assignment a -select a.getLocation(), a.getLValue().getType().toString(), a.getRValue().getType().toString(), - a.getRValue().toString() +select a.getLocation(), a.getLeftOperand().getType().toString(), + a.getRightOperand().getType().toString(), a.getRightOperand().toString() diff --git a/csharp/ql/test/library-tests/csharp10/lambda.ql b/csharp/ql/test/library-tests/csharp10/lambda.ql index 3cfec302b52..55c7faac049 100644 --- a/csharp/ql/test/library-tests/csharp10/lambda.ql +++ b/csharp/ql/test/library-tests/csharp10/lambda.ql @@ -3,7 +3,7 @@ import csharp private predicate getLambda( LocalVariableDeclAndInitExpr e, string type, LocalVariable v, LambdaExpr lexp ) { - lexp = e.getRValue() and + lexp = e.getRightOperand() and v = e.getTargetVariable() and type = e.getType().toStringWithTypes() } diff --git a/csharp/ql/test/library-tests/csharp11/operators.ql b/csharp/ql/test/library-tests/csharp11/operators.ql index 607efac0c26..f1543e2d744 100644 --- a/csharp/ql/test/library-tests/csharp11/operators.ql +++ b/csharp/ql/test/library-tests/csharp11/operators.ql @@ -14,8 +14,8 @@ query predicate assignbitwise( AssignBitwiseOperation op, Expr left, Expr right, string name, string qlclass ) { op.getFile().getStem() = "Operators" and - left = op.getLValue() and - right = op.getRValue() and + left = op.getLeftOperand() and + right = op.getRightOperand() and name = op.getOperator() and qlclass = op.getAPrimaryQlClass() } diff --git a/csharp/ql/test/library-tests/csharp6/MemberInitializer.ql b/csharp/ql/test/library-tests/csharp6/MemberInitializer.ql index f3ef63fe225..1895792f07c 100644 --- a/csharp/ql/test/library-tests/csharp6/MemberInitializer.ql +++ b/csharp/ql/test/library-tests/csharp6/MemberInitializer.ql @@ -12,7 +12,7 @@ query predicate indexerCalls(IndexerCall indexer, int arg, Expr value) { query predicate elementAssignments( ElementWrite write, Assignment assignment, int index, Expr indexer ) { - write = assignment.getLValue() and indexer = write.getIndex(index) + write = assignment.getLeftOperand() and indexer = write.getIndex(index) } query predicate arrayQualifiers(ElementAccess access, Expr qualifier) { diff --git a/csharp/ql/test/library-tests/enums/Enums11.ql b/csharp/ql/test/library-tests/enums/Enums11.ql index 36b2c005a21..f6133517f7d 100644 --- a/csharp/ql/test/library-tests/enums/Enums11.ql +++ b/csharp/ql/test/library-tests/enums/Enums11.ql @@ -6,7 +6,7 @@ import csharp from Expr e where - exists(Assignment a | a.getRValue() = e | + exists(Assignment a | a.getRightOperand() = e | a.getParent().(Field).getDeclaringType() instanceof Enum ) select e, e.getValue() diff --git a/csharp/ql/test/library-tests/expressions/AddEventExpr1.ql b/csharp/ql/test/library-tests/expressions/AddEventExpr1.ql index 48f6b41e19d..e3c1530fb1a 100644 --- a/csharp/ql/test/library-tests/expressions/AddEventExpr1.ql +++ b/csharp/ql/test/library-tests/expressions/AddEventExpr1.ql @@ -9,5 +9,5 @@ where c.hasName("LoginDialog") and e.getEnclosingCallable() = c and e.getTarget().hasName("Click") and - e.getLValue().getQualifier().(FieldAccess).getTarget().hasName("OkButton") + e.getLeftOperand().getQualifier().(FieldAccess).getTarget().hasName("OkButton") select c, e diff --git a/csharp/ql/test/library-tests/expressions/AnonymousMethod1.ql b/csharp/ql/test/library-tests/expressions/AnonymousMethod1.ql index 2c8268e87e1..74e9d3cb1ff 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousMethod1.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousMethod1.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, AnonymousMethodExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f7") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f7") and e.getParent+() = assign and e.getNumberOfParameters() = 1 and e.getParameter(0).getType() instanceof IntType and diff --git a/csharp/ql/test/library-tests/expressions/AnonymousMethod2.ql b/csharp/ql/test/library-tests/expressions/AnonymousMethod2.ql index e9fbbf01a10..8f0390b0f82 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousMethod2.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousMethod2.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, AnonymousMethodExpr e, Parameter p, ParameterAccess pa where - assign.getLValue().(VariableAccess).getTarget().hasName("f7") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f7") and e.getParent+() = assign and e.getNumberOfParameters() = 1 and p = e.getParameter(0) and diff --git a/csharp/ql/test/library-tests/expressions/AnonymousMethod3.ql b/csharp/ql/test/library-tests/expressions/AnonymousMethod3.ql index e4c2e9ae9ba..46d8907319d 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousMethod3.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousMethod3.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, AnonymousMethodExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f7") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f7") and e.getParent+() = assign and e.getNumberOfParameters() = 1 and e.getType().(DelegateType).getReturnType() instanceof IntType diff --git a/csharp/ql/test/library-tests/expressions/AnonymousMethod4.ql b/csharp/ql/test/library-tests/expressions/AnonymousMethod4.ql index 4d424b65b84..cca81c6b04e 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousMethod4.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousMethod4.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, AnonymousMethodExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f8") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f8") and e.getParent+() = assign and e.hasNoParameters() select e, e diff --git a/csharp/ql/test/library-tests/expressions/AnonymousMethod5.ql b/csharp/ql/test/library-tests/expressions/AnonymousMethod5.ql index cbc6ac82ca7..577d810dfad 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousMethod5.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousMethod5.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, AnonymousMethodExpr e, LocalVariableAccess va where - assign.getLValue().(VariableAccess).getTarget().hasName("f8") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f8") and e.getParent+() = assign and e.hasNoParameters() and va.getEnclosingStmt().getParent+() = e.getBody() and diff --git a/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation1.ql b/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation1.ql index 74d8cd27a94..c717aa260e0 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation1.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation1.ql @@ -6,11 +6,11 @@ import csharp from Assignment assign, AnonymousObjectCreation o, Assignment a, Property p where - assign.getLValue().(VariableAccess).getTarget().hasName("list2") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("list2") and o.getParent+() = assign and o.getInitializer().getMemberInitializer(0) = a and - a.getRValue().getValue() = "2" and - p = a.getLValue().(PropertyAccess).getTarget() and + a.getRightOperand().getValue() = "2" and + p = a.getLeftOperand().(PropertyAccess).getTarget() and p.hasName("i") and p.getDeclaringType() = o.getObjectType() select o diff --git a/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation2.ql b/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation2.ql index 5f9e16564b4..d55bf89d606 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation2.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation2.ql @@ -6,11 +6,11 @@ import csharp from Assignment assign, AnonymousObjectCreation o, Assignment a, Property p where - assign.getLValue().(VariableAccess).getTarget().hasName("contacts2") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("contacts2") and o.getParent+() = assign and o.getInitializer().getMemberInitializer(0) = a and - a.getRValue().getValue() = "Chris Smith" and - p = a.getLValue().(PropertyAccess).getTarget() and + a.getRightOperand().getValue() = "Chris Smith" and + p = a.getLeftOperand().(PropertyAccess).getTarget() and p.hasName("Name") and p.getDeclaringType() = o.getObjectType() select o, p.getType().toString() diff --git a/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation3.ql b/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation3.ql index afa9ca0d3b2..6033bfed38a 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation3.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation3.ql @@ -6,11 +6,11 @@ import csharp from Assignment assign, AnonymousObjectCreation o, Assignment a, Property p where - assign.getLValue().(VariableAccess).getTarget().hasName("contacts2") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("contacts2") and o.getParent+() = assign and o.getInitializer().getMemberInitializer(1) = a and - a.getRValue() instanceof ArrayCreation and - p = a.getLValue().(PropertyAccess).getTarget() and + a.getRightOperand() instanceof ArrayCreation and + p = a.getLeftOperand().(PropertyAccess).getTarget() and p.hasName("PhoneNumbers") and p.getDeclaringType() = o.getObjectType() select o, p.getType().getName() diff --git a/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation4.ql b/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation4.ql index b6354d1f493..a52278839f2 100644 --- a/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation4.ql +++ b/csharp/ql/test/library-tests/expressions/AnonymousObjectCreation4.ql @@ -8,7 +8,7 @@ from Assignment assign, AnonymousObjectCreation o, Assignment a, AnonymousObjectCreation p, Assignment b where - assign.getLValue().(VariableAccess).getTarget().hasName("contacts2") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("contacts2") and o.getParent+() = assign and o.getInitializer().getMemberInitializer(1) = a and p.getParent+() = assign and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation1.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation1.ql index fba7a403615..6f728347bff 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation1.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation1.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e, ArrayInitializer i where - a.getLValue().(VariableAccess).getTarget().hasName("is1") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("is1") and + e = a.getRightOperand() and not e.isImplicitlyTyped() and i = e.getInitializer() and e.isImplicitlySized() and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation10.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation10.ql index d8a1df12867..951ca22c0c2 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation10.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation10.ql @@ -6,9 +6,9 @@ import csharp from Assignment a, ArrayCreation e, CastExpr cast where - a.getLValue().(VariableAccess).getTarget().hasName("os") and + a.getLeftOperand().(VariableAccess).getTarget().hasName("os") and e.getEnclosingCallable().hasName("MainElementAccess") and - e = a.getRValue() and + e = a.getRightOperand() and not e.isImplicitlyTyped() and e.isImplicitlySized() and e.getArrayType().getDimension() = 1 and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation2.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation2.ql index ae56d579839..88ce79bc91e 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation2.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation2.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e, ArrayInitializer i where - a.getLValue().(VariableAccess).getTarget().hasName("is2") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("is2") and + e = a.getRightOperand() and not e.isImplicitlyTyped() and i = e.getInitializer() and e.getNumberOfLengthArguments() = 2 and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation3.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation3.ql index efe626dab08..0da55f86479 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation3.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation3.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e where - a.getLValue().(VariableAccess).getTarget().hasName("is3") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("is3") and + e = a.getRightOperand() and not e.isImplicitlyTyped() and not e.hasInitializer() and e.getNumberOfLengthArguments() = 1 and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation4.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation4.ql index 2a0dd531283..b79ec3f7bd6 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation4.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation4.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e where - a.getLValue().(VariableAccess).getTarget().hasName("is4") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("is4") and + e = a.getRightOperand() and not e.isImplicitlyTyped() and not e.hasInitializer() and e.getNumberOfLengthArguments() = 2 and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation5.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation5.ql index 04c29cafba8..88df5bef175 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation5.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation5.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e, int i where - a.getLValue().(VariableAccess).getTarget().hasName("is5") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("is5") and + e = a.getRightOperand() and e.isImplicitlyTyped() and e.isImplicitlySized() and e.getArrayType().getDimension() = 1 and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation6.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation6.ql index 7ca6bbe9668..237900bbe7c 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation6.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation6.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e where - a.getLValue().(VariableAccess).getTarget().hasName("is6") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("is6") and + e = a.getRightOperand() and e.isImplicitlyTyped() and e.isImplicitlySized() and e.getArrayType().getDimension() = 1 and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation7.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation7.ql index e34253a4f02..a466195a0b1 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation7.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation7.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e where - a.getLValue().(VariableAccess).getTarget().hasName("is7") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("is7") and + e = a.getRightOperand() and e.isImplicitlyTyped() and e.isImplicitlySized() and e.getArrayType().getDimension() = 1 and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation8.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation8.ql index cc1fd366db1..8eb810247c0 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation8.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation8.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e where - a.getLValue().(VariableAccess).getTarget().hasName("contacts2") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("contacts2") and + e = a.getRightOperand() and e.isImplicitlyTyped() and e.isImplicitlySized() and e.getArrayType().getDimension() = 1 and diff --git a/csharp/ql/test/library-tests/expressions/ArrayCreation9.ql b/csharp/ql/test/library-tests/expressions/ArrayCreation9.ql index fc4b561c170..55ba1d1edb1 100644 --- a/csharp/ql/test/library-tests/expressions/ArrayCreation9.ql +++ b/csharp/ql/test/library-tests/expressions/ArrayCreation9.ql @@ -6,8 +6,8 @@ import csharp from Assignment a, ArrayCreation e where - a.getLValue().(VariableAccess).getTarget().hasName("t") and - e = a.getRValue() and + a.getLeftOperand().(VariableAccess).getTarget().hasName("t") and + e = a.getRightOperand() and e.isImplicitlyTyped() and e.isImplicitlySized() and e.getArrayType().getDimension() = 1 and diff --git a/csharp/ql/test/library-tests/expressions/Lambda1.ql b/csharp/ql/test/library-tests/expressions/Lambda1.ql index f4787c584f3..4e4d17b9d24 100644 --- a/csharp/ql/test/library-tests/expressions/Lambda1.ql +++ b/csharp/ql/test/library-tests/expressions/Lambda1.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, LambdaExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f1") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f1") and e.getParent+() = assign and e.getNumberOfParameters() = 1 and e.getParameter(0).getType() instanceof ShortType and diff --git a/csharp/ql/test/library-tests/expressions/Lambda2.ql b/csharp/ql/test/library-tests/expressions/Lambda2.ql index 5fff4bd2cf6..ff5c06ec670 100644 --- a/csharp/ql/test/library-tests/expressions/Lambda2.ql +++ b/csharp/ql/test/library-tests/expressions/Lambda2.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, LambdaExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f2") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f2") and e.getParent+() = assign and e.getNumberOfParameters() = 1 and e.getParameter(0).getType() instanceof IntType and diff --git a/csharp/ql/test/library-tests/expressions/Lambda3.ql b/csharp/ql/test/library-tests/expressions/Lambda3.ql index 32aa919cd20..46d3a411b36 100644 --- a/csharp/ql/test/library-tests/expressions/Lambda3.ql +++ b/csharp/ql/test/library-tests/expressions/Lambda3.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, LambdaExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f3") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f3") and e.getParent+() = assign and e.getNumberOfParameters() = 1 and e.getParameter(0).getType() instanceof IntType and diff --git a/csharp/ql/test/library-tests/expressions/Lambda4.ql b/csharp/ql/test/library-tests/expressions/Lambda4.ql index ca7eb7a4207..69ac40ad932 100644 --- a/csharp/ql/test/library-tests/expressions/Lambda4.ql +++ b/csharp/ql/test/library-tests/expressions/Lambda4.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, LambdaExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f4") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f4") and e.getParent+() = assign and e.getNumberOfParameters() = 1 and e.getParameter(0).getType() instanceof IntType and diff --git a/csharp/ql/test/library-tests/expressions/Lambda5.ql b/csharp/ql/test/library-tests/expressions/Lambda5.ql index cc577aa85cb..3836ca4effd 100644 --- a/csharp/ql/test/library-tests/expressions/Lambda5.ql +++ b/csharp/ql/test/library-tests/expressions/Lambda5.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, LambdaExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f5") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f5") and e.getParent+() = assign and e.getNumberOfParameters() = 2 and e.getParameter(0).getType() instanceof IntType and diff --git a/csharp/ql/test/library-tests/expressions/Lambda6.ql b/csharp/ql/test/library-tests/expressions/Lambda6.ql index c584e4f6c09..4a6ee312834 100644 --- a/csharp/ql/test/library-tests/expressions/Lambda6.ql +++ b/csharp/ql/test/library-tests/expressions/Lambda6.ql @@ -6,7 +6,7 @@ import csharp from Assignment assign, LambdaExpr e where - assign.getLValue().(VariableAccess).getTarget().hasName("f6") and + assign.getLeftOperand().(VariableAccess).getTarget().hasName("f6") and e.getParent+() = assign and e.getNumberOfParameters() = 0 and e.getType().(DelegateType).hasName("Unit") and diff --git a/csharp/ql/test/library-tests/expressions/ObjectCreation10.ql b/csharp/ql/test/library-tests/expressions/ObjectCreation10.ql index abd4a9d6ec6..971654a95b3 100644 --- a/csharp/ql/test/library-tests/expressions/ObjectCreation10.ql +++ b/csharp/ql/test/library-tests/expressions/ObjectCreation10.ql @@ -6,7 +6,7 @@ import csharp from Assignment a, CollectionInitializer i where - a.getLValue().(VariableAccess).getTarget().hasName("list1") and + a.getLeftOperand().(VariableAccess).getTarget().hasName("list1") and i.getParent+() = a and i.getElementInitializer(0).getArgument(0) instanceof AssignExpr select i.getAChild+() diff --git a/csharp/ql/test/library-tests/expressions/ObjectCreation11.ql b/csharp/ql/test/library-tests/expressions/ObjectCreation11.ql index c874735c300..0265579ff67 100644 --- a/csharp/ql/test/library-tests/expressions/ObjectCreation11.ql +++ b/csharp/ql/test/library-tests/expressions/ObjectCreation11.ql @@ -6,7 +6,7 @@ import csharp from Assignment a, CollectionInitializer i, AnonymousObjectCreation o where - a.getLValue().(VariableAccess).getTarget().hasName("list2") and + a.getLeftOperand().(VariableAccess).getTarget().hasName("list2") and i.getParent+() = a and i.getElementInitializer(0).getArgument(0) = o select i, o diff --git a/csharp/ql/test/library-tests/expressions/ObjectCreation4.ql b/csharp/ql/test/library-tests/expressions/ObjectCreation4.ql index 5812397b11b..6ec3e2ec327 100644 --- a/csharp/ql/test/library-tests/expressions/ObjectCreation4.ql +++ b/csharp/ql/test/library-tests/expressions/ObjectCreation4.ql @@ -15,9 +15,9 @@ where cc.hasName("Point") and i = e.getInitializer() and a = i.getMemberInitializer(0) and - a.getLValue().(PropertyAccess).getTarget().hasName("X") and - a.getRValue().getValue() = "0" and + a.getLeftOperand().(PropertyAccess).getTarget().hasName("X") and + a.getRightOperand().getValue() = "0" and b = i.getMemberInitializer(1) and - b.getLValue().(PropertyAccess).getTarget().hasName("Y") and - b.getRValue().getValue() = "1" + b.getLeftOperand().(PropertyAccess).getTarget().hasName("Y") and + b.getRightOperand().getValue() = "1" select e, i, a, b diff --git a/csharp/ql/test/library-tests/expressions/ObjectCreation5.ql b/csharp/ql/test/library-tests/expressions/ObjectCreation5.ql index cf31f518ec7..e130da484d7 100644 --- a/csharp/ql/test/library-tests/expressions/ObjectCreation5.ql +++ b/csharp/ql/test/library-tests/expressions/ObjectCreation5.ql @@ -15,10 +15,10 @@ where cc.hasName("Point") and i = e.getInitializer() and a = i.getMemberInitializer(0) and - a.getLValue().(PropertyAccess).getTarget().hasName("X") and - a.getRValue().getValue() = "2" and + a.getLeftOperand().(PropertyAccess).getTarget().hasName("X") and + a.getRightOperand().getValue() = "2" and b = i.getMemberInitializer(1) and - b.getLValue().(PropertyAccess).getTarget().hasName("Y") and - b.getRValue().getValue() = "3" and + b.getLeftOperand().(PropertyAccess).getTarget().hasName("Y") and + b.getRightOperand().getValue() = "3" and i.getNumberOfMemberInitializers() = 2 select i, a, b diff --git a/csharp/ql/test/library-tests/expressions/ObjectCreation6.ql b/csharp/ql/test/library-tests/expressions/ObjectCreation6.ql index 11e771890ca..529607c8d4b 100644 --- a/csharp/ql/test/library-tests/expressions/ObjectCreation6.ql +++ b/csharp/ql/test/library-tests/expressions/ObjectCreation6.ql @@ -15,10 +15,10 @@ where cc.hasName("Rectangle") and i = e.getInitializer() and a = i.getMemberInitializer(0) and - a.getLValue().(PropertyAccess).getTarget().hasName("P1") and - a.getRValue() instanceof ObjectCreation and + a.getLeftOperand().(PropertyAccess).getTarget().hasName("P1") and + a.getRightOperand() instanceof ObjectCreation and b = i.getMemberInitializer(1) and - b.getLValue().(PropertyAccess).getTarget().hasName("P2") and - b.getRValue() instanceof ObjectCreation and + b.getLeftOperand().(PropertyAccess).getTarget().hasName("P2") and + b.getRightOperand() instanceof ObjectCreation and i.getNumberOfMemberInitializers() = 2 select i, a, b diff --git a/csharp/ql/test/library-tests/expressions/ObjectCreation7.ql b/csharp/ql/test/library-tests/expressions/ObjectCreation7.ql index ccb17515525..404011f1896 100644 --- a/csharp/ql/test/library-tests/expressions/ObjectCreation7.ql +++ b/csharp/ql/test/library-tests/expressions/ObjectCreation7.ql @@ -15,10 +15,10 @@ where cc.hasName("Rectangle2") and i = e.getInitializer() and a = i.getMemberInitializer(0) and - a.getLValue().(PropertyAccess).getTarget().hasName("P1") and - a.getRValue() instanceof ObjectInitializer and + a.getLeftOperand().(PropertyAccess).getTarget().hasName("P1") and + a.getRightOperand() instanceof ObjectInitializer and b = i.getMemberInitializer(1) and - b.getLValue().(PropertyAccess).getTarget().hasName("P2") and - b.getRValue() instanceof ObjectInitializer and + b.getLeftOperand().(PropertyAccess).getTarget().hasName("P2") and + b.getRightOperand() instanceof ObjectInitializer and i.getNumberOfMemberInitializers() = 2 select m, e diff --git a/csharp/ql/test/library-tests/expressions/RemoveEventExpr1.ql b/csharp/ql/test/library-tests/expressions/RemoveEventExpr1.ql index 95b223ed6f4..991fdd6e492 100644 --- a/csharp/ql/test/library-tests/expressions/RemoveEventExpr1.ql +++ b/csharp/ql/test/library-tests/expressions/RemoveEventExpr1.ql @@ -9,5 +9,5 @@ where c.hasName("LoginDialog") and e.getEnclosingCallable() = c and e.getTarget().hasName("Click") and - e.getLValue().getQualifier().(FieldAccess).getTarget().hasName("CancelButton") + e.getLeftOperand().getQualifier().(FieldAccess).getTarget().hasName("CancelButton") select c, e diff --git a/csharp/ql/test/utils/modelgenerator/dataflow/Summaries.cs b/csharp/ql/test/utils/modelgenerator/dataflow/Summaries.cs index b59513504d9..4c85b397ac1 100644 --- a/csharp/ql/test/utils/modelgenerator/dataflow/Summaries.cs +++ b/csharp/ql/test/utils/modelgenerator/dataflow/Summaries.cs @@ -536,6 +536,12 @@ public class HigherOrderParameters { a(o); } + + private void CallApply() + { + // Test that this call to `Apply` does not interfere with the flow summaries generated for `Apply` + Apply(x => x, null); + } } public static class HigherOrderExtensionMethods diff --git a/docs/codeql/reusables/supported-versions-compilers.rst b/docs/codeql/reusables/supported-versions-compilers.rst index ddda7065cf1..3891332f457 100644 --- a/docs/codeql/reusables/supported-versions-compilers.rst +++ b/docs/codeql/reusables/supported-versions-compilers.rst @@ -11,23 +11,23 @@ Microsoft extensions (up to VS 2022), Arm Compiler 5 [5]_","``.cpp``, ``.c++``, ``.cxx``, ``.hpp``, ``.hh``, ``.h++``, ``.hxx``, ``.c``, ``.cc``, ``.h``" - C#,C# up to 13,"Microsoft Visual Studio up to 2019 with .NET up to 4.8, + C#,C# up to 14 [6]_,"Microsoft Visual Studio up to 2019 with .NET up to 4.8, .NET Core up to 3.1 - .NET 5, .NET 6, .NET 7, .NET 8, .NET 9","``.sln``, ``.slnx``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" + .NET 5, .NET 6, .NET 7, .NET 8, .NET 9, .NET 10 [6]_","``.sln``, ``.slnx``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" GitHub Actions,"Not applicable",Not applicable,"``.github/workflows/*.yml``, ``.github/workflows/*.yaml``, ``**/action.yml``, ``**/action.yaml``" Go (aka Golang), "Go up to 1.26", "Go 1.11 or more recent", ``.go`` - Java,"Java 7 to 26 [6]_","javac (OpenJDK and Oracle JDK), + Java,"Java 7 to 26 [7]_","javac (OpenJDK and Oracle JDK), - Eclipse compiler for Java (ECJ) [7]_",``.java`` + Eclipse compiler for Java (ECJ) [8]_",``.java`` Kotlin,"Kotlin 1.8.0 to 2.3.2\ *x*","kotlinc",``.kt`` - JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [8]_" - Python [9]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13",Not applicable,``.py`` - Ruby [10]_,"up to 3.3",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``" - Rust [11]_,"Rust editions 2021 and 2024","Rust compiler","``.rs``, ``Cargo.toml``" - Swift [12]_ [13]_,"Swift 5.4-6.2","Swift compiler","``.swift``" - TypeScript [14]_,"2.6-5.9",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``" + JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [9]_" + Python [10]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13",Not applicable,``.py`` + Ruby [11]_,"up to 3.3",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``" + Rust [12]_,"Rust editions 2021 and 2024","Rust compiler","``.rs``, ``Cargo.toml``" + Swift [13]_ [14]_,"Swift 5.4-6.2","Swift compiler","``.swift``" + TypeScript [15]_,"2.6-5.9",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``" .. container:: footnote-group @@ -36,12 +36,13 @@ .. [3] Objective-C, Objective-C++, C++/CLI, and C++/CX are not supported. .. [4] Support for the clang-cl compiler is preliminary. .. [5] Support for the Arm Compiler (armcc) is preliminary. - .. [6] Builds that execute on Java 7 to 26 can be analyzed. The analysis understands standard language features in Java 8 to 26; "preview" and "incubator" features are not supported. Source code using Java language versions older than Java 8 are analyzed as Java 8 code. - .. [7] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin. - .. [8] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files. - .. [9] The extractor requires Python 3 to run. To analyze Python 2.7 you should install both versions of Python. - .. [10] Requires glibc 2.17. - .. [11] Requires ``rustup`` and ``cargo`` to be installed. Features from nightly toolchains are not supported. - .. [12] Support for the analysis of Swift requires macOS. - .. [13] Embedded Swift is not supported. - .. [14] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default. + .. [6] Support for .NET 10 is preliminary and code that uses language features new to C# 14 is not yet fully supported for extraction and analysis. + .. [7] Builds that execute on Java 7 to 26 can be analyzed. The analysis understands standard language features in Java 8 to 26; "preview" and "incubator" features are not supported. Source code using Java language versions older than Java 8 are analyzed as Java 8 code. + .. [8] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin. + .. [9] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files. + .. [10] The extractor requires Python 3 to run. To analyze Python 2.7 you should install both versions of Python. + .. [11] Requires glibc 2.17. + .. [12] Requires ``rustup`` and ``cargo`` to be installed. Features from nightly toolchains are not supported. + .. [13] Support for the analysis of Swift requires macOS. + .. [14] Embedded Swift is not supported. + .. [15] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default. diff --git a/go/extractor/registries/registryproxy_test.go b/go/extractor/registries/registryproxy_test.go index c564040ff1b..2f0b34bcb03 100644 --- a/go/extractor/registries/registryproxy_test.go +++ b/go/extractor/registries/registryproxy_test.go @@ -75,3 +75,59 @@ func TestParseRegistryConfigsMultiple(t *testing.T) { t.Fatalf("Expected `URL` to be `https://proxy.example.com/mod`, but got `%s`", second.URL) } } + +func TestParseRegistryConfigsMultipleGitSources(t *testing.T) { + multiple := parseRegistryConfigsSuccess(t, "[{ \"type\": \"git_source\", \"url\": \"https://github.com/github\" }, { \"type\": \"git_source\", \"url\": \"https://go.googlesource.com/go\" }]") + + if len(multiple) != 2 { + t.Fatalf("Expected `parseRegistryConfigs` to return two configurations, but got %d.", len(multiple)) + } + + first := multiple[0] + + if first.Type != "git_source" { + t.Fatalf("Expected `Type` to be `git_source`, but got `%s`", first.Type) + } + + if first.URL != "https://github.com/github" { + t.Fatalf("Expected `URL` to be `https://github.com/github`, but got `%s`", first.URL) + } + + second := multiple[1] + + if second.Type != "git_source" { + t.Fatalf("Expected `Type` to be `git_source`, but got `%s`", second.Type) + } + + if second.URL != "https://go.googlesource.com/go" { + t.Fatalf("Expected `URL` to be `https://go.googlesource.com/go`, but got `%s`", second.URL) + } +} + +func TestParseRegistryConfigsMultipleGoProxyServers(t *testing.T) { + multiple := parseRegistryConfigsSuccess(t, "[{ \"type\": \"goproxy_server\", \"url\": \"https://proxy.example.com/mod\" }, { \"type\": \"goproxy_server\", \"url\": \"https://goproxy.io\" }]") + + if len(multiple) != 2 { + t.Fatalf("Expected `parseRegistryConfigs` to return two configurations, but got %d.", len(multiple)) + } + + first := multiple[0] + + if first.Type != "goproxy_server" { + t.Fatalf("Expected `Type` to be `goproxy_server`, but got `%s`", first.Type) + } + + if first.URL != "https://proxy.example.com/mod" { + t.Fatalf("Expected `URL` to be `https://proxy.example.com/mod`, but got `%s`", first.URL) + } + + second := multiple[1] + + if second.Type != "goproxy_server" { + t.Fatalf("Expected `Type` to be `goproxy_server`, but got `%s`", second.Type) + } + + if second.URL != "https://goproxy.io" { + t.Fatalf("Expected `URL` to be `https://goproxy.io`, but got `%s`", second.URL) + } +} diff --git a/java/ql/test-kotlin1/library-tests/java-kotlin-collection-type-generic-methods/test.expected b/java/ql/test-kotlin1/library-tests/java-kotlin-collection-type-generic-methods/test.expected index a56980d10ac..a55e73e283f 100644 --- a/java/ql/test-kotlin1/library-tests/java-kotlin-collection-type-generic-methods/test.expected +++ b/java/ql/test-kotlin1/library-tests/java-kotlin-collection-type-generic-methods/test.expected @@ -196,6 +196,8 @@ methodWithDuplicate | List | listIterator | int | | List | of | E | | List | of | E[] | +| List | ofLazy | IntFunction | +| List | ofLazy | int | | List | remove | Object | | List | remove | int | | List | removeAll | Collection | @@ -222,6 +224,8 @@ methodWithDuplicate | List | listIterator | int | | List | of | E | | List | of | E[] | +| List | ofLazy | IntFunction | +| List | ofLazy | int | | List | remove | Object | | List | remove | int | | List | removeAll | Collection | @@ -248,6 +252,8 @@ methodWithDuplicate | List | listIterator | int | | List | of | E | | List | of | E[] | +| List | ofLazy | IntFunction | +| List | ofLazy | int | | List | remove | Object | | List | remove | int | | List | removeAll | Collection | @@ -280,6 +286,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | K | | Map | put | V | | Map | putAll | Map | @@ -310,6 +318,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | Identity | | Map | put | Object | | Map | putAll | Map | @@ -341,6 +351,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | K | | Map | put | V | | Map | putAll | Map | @@ -370,6 +382,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | Object | | Map | putAll | Map | | Map | putIfAbsent | Object | @@ -397,6 +411,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | String | | Map | putAll | Map | | Map | putIfAbsent | String | diff --git a/java/ql/test-kotlin2/library-tests/java-kotlin-collection-type-generic-methods/test.expected b/java/ql/test-kotlin2/library-tests/java-kotlin-collection-type-generic-methods/test.expected index 2495c1fc157..3237c89c8c7 100644 --- a/java/ql/test-kotlin2/library-tests/java-kotlin-collection-type-generic-methods/test.expected +++ b/java/ql/test-kotlin2/library-tests/java-kotlin-collection-type-generic-methods/test.expected @@ -191,6 +191,8 @@ methodWithDuplicate | List | listIterator | int | | List | of | E | | List | of | E[] | +| List | ofLazy | IntFunction | +| List | ofLazy | int | | List | remove | Object | | List | remove | int | | List | removeAll | Collection | @@ -216,6 +218,8 @@ methodWithDuplicate | List | listIterator | int | | List | of | E | | List | of | E[] | +| List | ofLazy | IntFunction | +| List | ofLazy | int | | List | remove | Object | | List | remove | int | | List | removeAll | Collection | @@ -242,6 +246,8 @@ methodWithDuplicate | List | listIterator | int | | List | of | E | | List | of | E[] | +| List | ofLazy | IntFunction | +| List | ofLazy | int | | List | remove | Object | | List | remove | int | | List | removeAll | Collection | @@ -274,6 +280,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | K | | Map | put | V | | Map | putAll | Map | @@ -303,6 +311,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | Identity | | Map | put | Object | | Map | putAll | Map | @@ -333,6 +343,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | K | | Map | put | V | | Map | putAll | Map | @@ -361,6 +373,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | Object | | Map | putAll | Map | | Map | putIfAbsent | Object | @@ -388,6 +402,8 @@ methodWithDuplicate | Map | of | K | | Map | of | V | | Map | ofEntries | Entry[] | +| Map | ofLazy | Function | +| Map | ofLazy | Set | | Map | put | String | | Map | putAll | Map | | Map | putIfAbsent | String | diff --git a/java/ql/test-kotlin2/library-tests/reflection/reflection.expected b/java/ql/test-kotlin2/library-tests/reflection/reflection.expected index b5de2b1adea..2c0bee11a9e 100644 --- a/java/ql/test-kotlin2/library-tests/reflection/reflection.expected +++ b/java/ql/test-kotlin2/library-tests/reflection/reflection.expected @@ -266,6 +266,7 @@ compGenerated | file:///AccessFlag$Location.class:0:0:0:0 | getEntries | Default property accessor | | file:///AccessFlag.class:0:0:0:0 | getEntries | Default property accessor | | file:///AccessMode.class:0:0:0:0 | getEntries | Default property accessor | +| file:///ByteOrder.class:0:0:0:0 | getEntries | Default property accessor | | file:///CharProgression.class:0:0:0:0 | forEach | Forwarder for a Kotlin class inheriting an interface default method | | file:///CharProgression.class:0:0:0:0 | spliterator | Forwarder for a Kotlin class inheriting an interface default method | | file:///CharRange.class:0:0:0:0 | forEach | Forwarder for a Kotlin class inheriting an interface default method | diff --git a/java/ql/test/library-tests/compact-source-files/CompactSourceAnalysis.expected b/java/ql/test/library-tests/compact-source-files/CompactSourceAnalysis.expected index 05db00aa26d..0e1dd647e41 100644 --- a/java/ql/test/library-tests/compact-source-files/CompactSourceAnalysis.expected +++ b/java/ql/test/library-tests/compact-source-files/CompactSourceAnalysis.expected @@ -1 +1 @@ -| Test.java:0:0:0:0 | Test | Test.java:1:1:1:1 | Test | Compact source file 'Test' contains implicit class 'Test' | +| Test.java:0:0:0:0 | Test | Test.java:1:1:29:1 | Test | Compact source file 'Test' contains implicit class 'Test' | diff --git a/java/ql/test/library-tests/compact-source-files/ImplicitClassDetection.expected b/java/ql/test/library-tests/compact-source-files/ImplicitClassDetection.expected index 61dcdd8a17f..9bfaaecbbcb 100644 --- a/java/ql/test/library-tests/compact-source-files/ImplicitClassDetection.expected +++ b/java/ql/test/library-tests/compact-source-files/ImplicitClassDetection.expected @@ -1,2 +1,2 @@ -| Test.java:1:1:1:1 | Test | implicit | +| Test.java:1:1:29:1 | Test | implicit | | Test.java:25:7:25:16 | NotCompact | not implicit | diff --git a/java/ql/test/library-tests/compact-source-files/MethodInCompactSource.expected b/java/ql/test/library-tests/compact-source-files/MethodInCompactSource.expected index 3c7b45f500e..d4b41c61441 100644 --- a/java/ql/test/library-tests/compact-source-files/MethodInCompactSource.expected +++ b/java/ql/test/library-tests/compact-source-files/MethodInCompactSource.expected @@ -1,5 +1,5 @@ -| Test.java:1:1:1:1 | | in compact source | -| Test.java:1:1:1:1 | | in compact source | +| Test.java:1:1:29:1 | | in compact source | +| Test.java:1:1:29:1 | | in compact source | | Test.java:5:6:5:9 | main | in compact source | | Test.java:11:6:11:16 | processData | in compact source | | Test.java:16:14:16:31 | updatePrivateField | in compact source | diff --git a/java/ql/test/library-tests/compact-source-files/options b/java/ql/test/library-tests/compact-source-files/options index db1dc01e53b..3d6e630aa73 100644 --- a/java/ql/test/library-tests/compact-source-files/options +++ b/java/ql/test/library-tests/compact-source-files/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args --release 25 --enable-preview +//semmle-extractor-options: --javac-args --release 25 diff --git a/java/ql/test/library-tests/dataflow/kdf/options b/java/ql/test/library-tests/dataflow/kdf/options index f4edc64c017..801b81e0752 100644 --- a/java/ql/test/library-tests/dataflow/kdf/options +++ b/java/ql/test/library-tests/dataflow/kdf/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args --enable-preview --release 25 \ No newline at end of file +//semmle-extractor-options: --javac-args --release 25 \ No newline at end of file diff --git a/java/ql/test/library-tests/dataflow/scoped-values/options b/java/ql/test/library-tests/dataflow/scoped-values/options index c793109355a..2d42b8d2cd8 100644 --- a/java/ql/test/library-tests/dataflow/scoped-values/options +++ b/java/ql/test/library-tests/dataflow/scoped-values/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args -source 25 -target 25 --enable-preview \ No newline at end of file +//semmle-extractor-options: --javac-args -source 25 -target 25 \ No newline at end of file diff --git a/java/ql/test/library-tests/errorexpr/Test.java b/java/ql/test/library-tests/errorexpr/Test.java index af314e5ced6..068690e7bb2 100644 --- a/java/ql/test/library-tests/errorexpr/Test.java +++ b/java/ql/test/library-tests/errorexpr/Test.java @@ -13,6 +13,5 @@ public class Test { } // Diagnostic Matches: Erroneous node in tree: (ERROR) -// Diagnostic Matches: In file Test.java:8:15 no end location for JCMethodInvocation : yield(x) // Diagnostic Matches: 1 errors during annotation processing // Diagnostic Matches: Unknown or erroneous type for expression of kind ErrorExpr diff --git a/java/ql/test/library-tests/flexible-constructors/options b/java/ql/test/library-tests/flexible-constructors/options index db1dc01e53b..3d6e630aa73 100644 --- a/java/ql/test/library-tests/flexible-constructors/options +++ b/java/ql/test/library-tests/flexible-constructors/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args --release 25 --enable-preview +//semmle-extractor-options: --javac-args --release 25 diff --git a/java/ql/test/library-tests/module-import-declarations/options b/java/ql/test/library-tests/module-import-declarations/options index b510fdce0df..801b81e0752 100644 --- a/java/ql/test/library-tests/module-import-declarations/options +++ b/java/ql/test/library-tests/module-import-declarations/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args --release 25 --enable-preview \ No newline at end of file +//semmle-extractor-options: --javac-args --release 25 \ No newline at end of file diff --git a/java/ql/test/query-tests/security/CWE-676/semmle/tests/options b/java/ql/test/query-tests/security/CWE-676/semmle/tests/options new file mode 100644 index 00000000000..3d6e630aa73 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-676/semmle/tests/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args --release 25 diff --git a/python/ql/lib/semmle/python/frameworks/Eventlet.model.yml b/python/ql/lib/semmle/python/frameworks/Eventlet.model.yml new file mode 100644 index 00000000000..f60b9218819 --- /dev/null +++ b/python/ql/lib/semmle/python/frameworks/Eventlet.model.yml @@ -0,0 +1,9 @@ +extensions: + - addsTo: + pack: codeql/python-all + extensible: typeModel + data: + # See https://eventlet.readthedocs.io/en/latest/patching.html + - ['socket.socket', 'eventlet', 'Member[green].Member[socket].Member[socket].ReturnValue'] + # eventlet also re-exports as eventlet.socket for convenience + - ['socket.socket', 'eventlet', 'Member[socket].Member[socket].ReturnValue'] diff --git a/python/ql/lib/semmle/python/frameworks/Gevent.model.yml b/python/ql/lib/semmle/python/frameworks/Gevent.model.yml new file mode 100644 index 00000000000..974ecedd073 --- /dev/null +++ b/python/ql/lib/semmle/python/frameworks/Gevent.model.yml @@ -0,0 +1,7 @@ +extensions: + - addsTo: + pack: codeql/python-all + extensible: typeModel + data: + # See https://www.gevent.org/api/gevent.socket.html + - ['socket.socket', 'gevent', 'Member[socket].Member[socket].ReturnValue'] diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.model.yml b/python/ql/lib/semmle/python/frameworks/Stdlib.model.yml index a01bf1b40ba..5b50dff313e 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.model.yml +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.model.yml @@ -27,6 +27,8 @@ extensions: extensible: sinkModel data: - ["zipfile.ZipFile","Member[extractall].Argument[0,path:]", "path-injection"] + # See https://docs.python.org/3/library/socket.html#socket.socket.bind + - ["socket.socket", "Member[bind].Argument[0,address:]", "bind-socket-all-interfaces"] - addsTo: pack: codeql/python-all @@ -184,6 +186,8 @@ extensions: pack: codeql/python-all extensible: typeModel data: + # See https://docs.python.org/3/library/socket.html#socket.socket + - ['socket.socket', 'socket', 'Member[socket].ReturnValue'] # See https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlparse - ["urllib.parse.ParseResult~Subclass", 'urllib', 'Member[parse].Member[urlparse]'] diff --git a/python/ql/src/Security/CVE-2018-1281/BindToAllInterfaces.ql b/python/ql/src/Security/CVE-2018-1281/BindToAllInterfaces.ql index 5e2e27b3bf4..14c17edc359 100644 --- a/python/ql/src/Security/CVE-2018-1281/BindToAllInterfaces.ql +++ b/python/ql/src/Security/CVE-2018-1281/BindToAllInterfaces.ql @@ -2,7 +2,7 @@ * @name Binding a socket to all network interfaces * @description Binding a socket to all interfaces opens it up to traffic from any IPv4 address * and is therefore associated with security risks. - * @kind problem + * @kind path-problem * @tags security * external/cwe/cwe-200 * @problem.severity error @@ -14,7 +14,9 @@ import python import semmle.python.dataflow.new.DataFlow -import semmle.python.ApiGraphs +import semmle.python.dataflow.new.TaintTracking +private import semmle.python.frameworks.data.ModelsAsData +import BindToAllInterfacesFlow::PathGraph /** Gets a hostname that can be used to bind to all interfaces. */ private string vulnerableHostname() { @@ -26,45 +28,26 @@ private string vulnerableHostname() { ] } -/** Gets a reference to a hostname that can be used to bind to all interfaces. */ -private DataFlow::TypeTrackingNode vulnerableHostnameRef(DataFlow::TypeTracker t, string hostname) { - t.start() and - exists(StringLiteral allInterfacesStringLiteral | hostname = vulnerableHostname() | - allInterfacesStringLiteral.getText() = hostname and - result.asExpr() = allInterfacesStringLiteral - ) - or - exists(DataFlow::TypeTracker t2 | result = vulnerableHostnameRef(t2, hostname).track(t2, t)) +private module BindToAllInterfacesConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source.asExpr().(StringLiteral).getText() = vulnerableHostname() + } + + predicate isSink(DataFlow::Node sink) { + ModelOutput::sinkNode(sink, "bind-socket-all-interfaces") and + // Network socket addresses are tuples like (host, port), so we require + // the bind() argument to originate from a tuple expression. This excludes + // AF_UNIX sockets, which pass a plain string path to bind(). + any(DataFlow::LocalSourceNode n | n.asExpr() instanceof Tuple).flowsTo(sink) + } } -/** Gets a reference to a hostname that can be used to bind to all interfaces. */ -DataFlow::Node vulnerableHostnameRef(string hostname) { - vulnerableHostnameRef(DataFlow::TypeTracker::end(), hostname).flowsTo(result) -} +private module BindToAllInterfacesFlow = TaintTracking::Global; -/** Gets a reference to a tuple for which the first element is a hostname that can be used to bind to all interfaces. */ -private DataFlow::TypeTrackingNode vulnerableAddressTuple(DataFlow::TypeTracker t, string hostname) { - t.start() and - result.asExpr() = any(Tuple tup | tup.getElt(0) = vulnerableHostnameRef(hostname).asExpr()) - or - exists(DataFlow::TypeTracker t2 | result = vulnerableAddressTuple(t2, hostname).track(t2, t)) -} +private import BindToAllInterfacesFlow -/** Gets a reference to a tuple for which the first element is a hostname that can be used to bind to all interfaces. */ -DataFlow::Node vulnerableAddressTuple(string hostname) { - vulnerableAddressTuple(DataFlow::TypeTracker::end(), hostname).flowsTo(result) -} - -/** - * Gets an instance of `socket.socket` using _some_ address family. - * - * See https://docs.python.org/3/library/socket.html - */ -API::Node socketInstance() { result = API::moduleImport("socket").getMember("socket").getReturn() } - -from DataFlow::CallCfgNode bindCall, DataFlow::Node addressArg, string hostname -where - bindCall = socketInstance().getMember("bind").getACall() and - addressArg = bindCall.getArg(0) and - addressArg = vulnerableAddressTuple(hostname) -select bindCall.asExpr(), "'" + hostname + "' binds a socket to all interfaces." +from PathNode source, PathNode sink +where flowPath(source, sink) +select sink.getNode(), source, sink, + "Binding a socket to all interfaces (using $@) is a security risk.", source.getNode(), + "'" + source.getNode().asExpr().(StringLiteral).getText() + "'" diff --git a/python/ql/src/Statements/ShouldUseWithStatement.ql b/python/ql/src/Statements/ShouldUseWithStatement.ql index eb5cf9237d5..20bf053f6da 100644 --- a/python/ql/src/Statements/ShouldUseWithStatement.ql +++ b/python/ql/src/Statements/ShouldUseWithStatement.ql @@ -13,7 +13,7 @@ */ import python -private import LegacyPointsTo +private import semmle.python.dataflow.new.internal.DataFlowDispatch predicate calls_close(Call c) { exists(Attribute a | c.getFunc() = a and a.getName() = "close") } @@ -23,18 +23,12 @@ predicate only_stmt_in_finally(Try t, Call c) { ) } -predicate points_to_context_manager(ControlFlowNodeWithPointsTo f, ClassValue cls) { - forex(Value v | f.pointsTo(v) | v.getClass() = cls) and - cls.isContextManager() -} - -from Call close, Try t, ClassValue cls +from Call close, Try t, Class cls where only_stmt_in_finally(t, close) and calls_close(close) and - exists(ControlFlowNode f | f = close.getFunc().getAFlowNode().(AttrNode).getObject() | - points_to_context_manager(f, cls) - ) + classInstanceTracker(cls).asExpr() = close.getFunc().(Attribute).getObject() and + DuckTyping::isContextManager(cls) select close, "Instance of context-manager class $@ is closed in a finally block. Consider using 'with' statement.", cls, cls.getName() diff --git a/python/ql/src/change-notes/2026-03-26-improve-bind-all-interfaces-query.md b/python/ql/src/change-notes/2026-03-26-improve-bind-all-interfaces-query.md new file mode 100644 index 00000000000..bc78b2b6f77 --- /dev/null +++ b/python/ql/src/change-notes/2026-03-26-improve-bind-all-interfaces-query.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- + +- The `py/bind-socket-all-network-interfaces` query now uses the global data-flow library, leading to better precision and more results. Also, wrappers of `socket.socket` in the `eventlet` and `gevent` libraries are now also recognized as socket binding operations. diff --git a/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces.expected b/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces.expected index 86c67af4eae..0b96b2df650 100644 --- a/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces.expected +++ b/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces.expected @@ -1,5 +1,63 @@ -| BindToAllInterfaces_test.py:5:1:5:26 | Attribute() | '0.0.0.0' binds a socket to all interfaces. | -| BindToAllInterfaces_test.py:9:1:9:18 | Attribute() | '' binds a socket to all interfaces. | -| BindToAllInterfaces_test.py:17:1:17:26 | Attribute() | '0.0.0.0' binds a socket to all interfaces. | -| BindToAllInterfaces_test.py:21:1:21:11 | Attribute() | '0.0.0.0' binds a socket to all interfaces. | -| BindToAllInterfaces_test.py:26:1:26:20 | Attribute() | '::' binds a socket to all interfaces. | +#select +| BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | '0.0.0.0' | +| BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | '' | +| BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | '0.0.0.0' | +| BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | '0.0.0.0' | +| BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | '::' | +| BindToAllInterfaces_test.py:39:17:39:41 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:34:26:34:34 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:39:17:39:41 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:34:26:34:34 | ControlFlowNode for StringLiteral | '0.0.0.0' | +| BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | '0.0.0.0' | +| BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | '0.0.0.0' | +| BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | '0.0.0.0' | +edges +| BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 | +| BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 | +| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 | +| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup | provenance | | +| BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | provenance | | +| BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup | BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | provenance | Sink:MaD:63 | +| BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 | +| BindToAllInterfaces_test.py:33:18:33:21 | ControlFlowNode for self [Return] [Attribute bind_addr] | BindToAllInterfaces_test.py:41:10:41:17 | ControlFlowNode for Server() [Attribute bind_addr] | provenance | | +| BindToAllInterfaces_test.py:34:9:34:12 | [post] ControlFlowNode for self [Attribute bind_addr] | BindToAllInterfaces_test.py:33:18:33:21 | ControlFlowNode for self [Return] [Attribute bind_addr] | provenance | | +| BindToAllInterfaces_test.py:34:26:34:34 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:34:9:34:12 | [post] ControlFlowNode for self [Attribute bind_addr] | provenance | | +| BindToAllInterfaces_test.py:37:15:37:18 | ControlFlowNode for self [Attribute bind_addr] | BindToAllInterfaces_test.py:39:17:39:20 | ControlFlowNode for self [Attribute bind_addr] | provenance | | +| BindToAllInterfaces_test.py:39:17:39:20 | ControlFlowNode for self [Attribute bind_addr] | BindToAllInterfaces_test.py:39:17:39:30 | ControlFlowNode for Attribute | provenance | | +| BindToAllInterfaces_test.py:39:17:39:30 | ControlFlowNode for Attribute | BindToAllInterfaces_test.py:39:17:39:41 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 | +| BindToAllInterfaces_test.py:41:1:41:6 | ControlFlowNode for server [Attribute bind_addr] | BindToAllInterfaces_test.py:42:1:42:6 | ControlFlowNode for server [Attribute bind_addr] | provenance | | +| BindToAllInterfaces_test.py:41:10:41:17 | ControlFlowNode for Server() [Attribute bind_addr] | BindToAllInterfaces_test.py:41:1:41:6 | ControlFlowNode for server [Attribute bind_addr] | provenance | | +| BindToAllInterfaces_test.py:42:1:42:6 | ControlFlowNode for server [Attribute bind_addr] | BindToAllInterfaces_test.py:37:15:37:18 | ControlFlowNode for self [Attribute bind_addr] | provenance | | +| BindToAllInterfaces_test.py:46:1:46:4 | ControlFlowNode for host | BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 | +| BindToAllInterfaces_test.py:46:8:46:44 | ControlFlowNode for Attribute() | BindToAllInterfaces_test.py:46:1:46:4 | ControlFlowNode for host | provenance | | +| BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:46:8:46:44 | ControlFlowNode for Attribute() | provenance | dict.get | +| BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 | +| BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 | +nodes +| BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral | +| BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple | +| BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral | +| BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple | +| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | semmle.label | ControlFlowNode for ALL_LOCALS | +| BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral | +| BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple | +| BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup | semmle.label | ControlFlowNode for tup | +| BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | semmle.label | ControlFlowNode for tup | +| BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral | +| BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple | +| BindToAllInterfaces_test.py:33:18:33:21 | ControlFlowNode for self [Return] [Attribute bind_addr] | semmle.label | ControlFlowNode for self [Return] [Attribute bind_addr] | +| BindToAllInterfaces_test.py:34:9:34:12 | [post] ControlFlowNode for self [Attribute bind_addr] | semmle.label | [post] ControlFlowNode for self [Attribute bind_addr] | +| BindToAllInterfaces_test.py:34:26:34:34 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral | +| BindToAllInterfaces_test.py:37:15:37:18 | ControlFlowNode for self [Attribute bind_addr] | semmle.label | ControlFlowNode for self [Attribute bind_addr] | +| BindToAllInterfaces_test.py:39:17:39:20 | ControlFlowNode for self [Attribute bind_addr] | semmle.label | ControlFlowNode for self [Attribute bind_addr] | +| BindToAllInterfaces_test.py:39:17:39:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | +| BindToAllInterfaces_test.py:39:17:39:41 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple | +| BindToAllInterfaces_test.py:41:1:41:6 | ControlFlowNode for server [Attribute bind_addr] | semmle.label | ControlFlowNode for server [Attribute bind_addr] | +| BindToAllInterfaces_test.py:41:10:41:17 | ControlFlowNode for Server() [Attribute bind_addr] | semmle.label | ControlFlowNode for Server() [Attribute bind_addr] | +| BindToAllInterfaces_test.py:42:1:42:6 | ControlFlowNode for server [Attribute bind_addr] | semmle.label | ControlFlowNode for server [Attribute bind_addr] | +| BindToAllInterfaces_test.py:46:1:46:4 | ControlFlowNode for host | semmle.label | ControlFlowNode for host | +| BindToAllInterfaces_test.py:46:8:46:44 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | +| BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral | +| BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple | +| BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral | +| BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple | +| BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral | +| BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple | +subpaths diff --git a/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces.qlref b/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces.qlref index f06cc3d869d..6396fd91863 100644 --- a/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces.qlref +++ b/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces.qlref @@ -1 +1,2 @@ -Security/CVE-2018-1281/BindToAllInterfaces.ql \ No newline at end of file +query: Security/CVE-2018-1281/BindToAllInterfaces.ql +postprocess: utils/test/InlineExpectationsTestQuery.ql \ No newline at end of file diff --git a/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces_test.py b/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces_test.py index bbab44d8103..27ba6642b64 100644 --- a/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces_test.py +++ b/python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces_test.py @@ -2,25 +2,61 @@ import socket # binds to all interfaces, insecure s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -s.bind(('0.0.0.0', 31137)) +s.bind(('0.0.0.0', 31137)) # $ Alert[py/bind-socket-all-network-interfaces] # binds to all interfaces, insecure s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -s.bind(('', 4040)) +s.bind(('', 4040)) # $ Alert[py/bind-socket-all-network-interfaces] # binds only to a dedicated interface, secure s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('84.68.10.12', 8080)) # binds to all interfaces, insecure -ALL_LOCALS = "0.0.0.0" -s.bind((ALL_LOCALS, 9090)) +ALL_LOCALS = "0.0.0.0" # $ Source +s.bind((ALL_LOCALS, 9090)) # $ Alert[py/bind-socket-all-network-interfaces] # binds to all interfaces, insecure tup = (ALL_LOCALS, 8080) -s.bind(tup) +s.bind(tup) # $ Alert[py/bind-socket-all-network-interfaces] # IPv6 s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) -s.bind(("::", 8080)) # NOT OK +s.bind(("::", 8080)) # $ Alert[py/bind-socket-all-network-interfaces] + + +# FN cases from https://github.com/github/codeql/issues/21582 + +# Address stored in a class attribute +class Server: + def __init__(self): + self.bind_addr = '0.0.0.0' # $ Source + self.port = 31137 + + def start(self): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.bind((self.bind_addr, self.port)) # $ Alert[py/bind-socket-all-network-interfaces] + +server = Server() +server.start() + +# os.environ.get with insecure default +import os +host = os.environ.get('APP_HOST', '0.0.0.0') # $ Source +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.bind((host, 8080)) # $ Alert[py/bind-socket-all-network-interfaces] + +# gevent.socket (alternative socket module) +from gevent import socket as gsocket +gs = gsocket.socket(gsocket.AF_INET, gsocket.SOCK_STREAM) +gs.bind(('0.0.0.0', 31137)) # $ Alert[py/bind-socket-all-network-interfaces] + +# eventlet.green.socket (another alternative socket module) +from eventlet.green import socket as esocket +es = esocket.socket(esocket.AF_INET, esocket.SOCK_STREAM) +es.bind(('0.0.0.0', 31137)) # $ Alert[py/bind-socket-all-network-interfaces] + +# AF_UNIX socket binding should not be flagged +us = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +us.bind('') diff --git a/python/ql/test/query-tests/Statements/general/ShouldUseWithStatement.expected b/python/ql/test/query-tests/Statements/general/ShouldUseWithStatement.expected index d062717bbf2..50ff6cc1f91 100644 --- a/python/ql/test/query-tests/Statements/general/ShouldUseWithStatement.expected +++ b/python/ql/test/query-tests/Statements/general/ShouldUseWithStatement.expected @@ -1 +1 @@ -| test.py:168:9:168:17 | Attribute() | Instance of context-manager class $@ is closed in a finally block. Consider using 'with' statement. | test.py:151:1:151:17 | class CM | CM | +| test.py:168:9:168:17 | Attribute() | Instance of context-manager class $@ is closed in a finally block. Consider using 'with' statement. | test.py:151:1:151:17 | Class CM | CM | diff --git a/rust/ql/lib/codeql/files/FileSystem.qll b/rust/ql/lib/codeql/files/FileSystem.qll index cfab33b9a44..93ff7be604e 100644 --- a/rust/ql/lib/codeql/files/FileSystem.qll +++ b/rust/ql/lib/codeql/files/FileSystem.qll @@ -45,13 +45,16 @@ extensible predicate additionalExternalFile(string relativePath); /** A file. */ class File extends Container, Impl::File { + pragma[nomagic] + private predicate isAdditionalExternalFile() { additionalExternalFile(this.getRelativePath()) } + /** * Holds if this file was extracted from the source code of the target project * (rather than another location such as inside a dependency). */ predicate fromSource() { exists(ExtractorStep s | s.getAction() = "Extract" and s.getFile() = this) and - not additionalExternalFile(this.getRelativePath()) + not this.isAdditionalExternalFile() } /** diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll b/rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll index 97dbf2d8f3a..26e8bdea4e0 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll @@ -134,7 +134,7 @@ module SatisfiesBlanketConstraint< exists(ArgumentTypeAndBlanketOffset ato, Trait traitBound | ato = MkArgumentTypeAndBlanketOffset(at, _) and SatisfiesBlanketConstraintInput::relevantConstraint(ato, impl, traitBound) and - SatisfiesBlanketConstraint::satisfiesConstraintType(ato, TTrait(traitBound), _, _) + SatisfiesBlanketConstraint::satisfiesConstraint(ato, TTrait(traitBound), _, _) ) or exists(TypeParam blanketTypeParam | diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index 0f9afcd06bb..c6a268be126 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -467,6 +467,41 @@ private predicate isPanicMacroCall(MacroExpr me) { me.getMacroCall().resolveMacro().(MacroRules).getName().getText() = "panic" } +// Due to "binding modes" the type of the pattern is not necessarily the +// same as the type of the initializer. However, when the pattern is an +// identifier pattern, its type is guaranteed to be the same as the type of the +// initializer. +private predicate identLetStmt(LetStmt let, IdentPat lhs, Expr rhs) { + let.getPat() = lhs and + let.getInitializer() = rhs +} + +/** + * Gets the root type of a closure. + * + * We model closures as `dyn Fn` trait object types. A closure might implement + * only `Fn`, `FnMut`, or `FnOnce`. But since `Fn` is a subtrait of the others, + * giving closures the type `dyn Fn` works well in practice -- even if not + * entirely accurate. + */ +private DynTraitType closureRootType() { + result = TDynTraitType(any(FnTrait t)) // always exists because of the mention in `builtins/mentions.rs` +} + +/** Gets the path to a closure's return type. */ +private TypePath closureReturnPath() { + result = + TypePath::singleton(TDynTraitTypeParameter(any(FnTrait t), any(FnOnceTrait t).getOutputType())) +} + +/** Gets the path to a closure's `index`th parameter type, where the arity is `arity`. */ +pragma[nomagic] +private TypePath closureParameterPath(int arity, int index) { + result = + TypePath::cons(TDynTraitTypeParameter(_, any(FnTrait t).getTypeParam()), + TypePath::singleton(getTupleTypeParameter(arity, index))) +} + /** Module for inferring certain type information. */ module CertainTypeInference { pragma[nomagic] @@ -544,11 +579,7 @@ module CertainTypeInference { // is not a certain type equality. exists(LetStmt let | not let.hasTypeRepr() and - // Due to "binding modes" the type of the pattern is not necessarily the - // same as the type of the initializer. The pattern being an identifier - // pattern is sufficient to ensure that this is not the case. - let.getPat().(IdentPat) = n1 and - let.getInitializer() = n2 + identLetStmt(let, n1, n2) ) or exists(LetExpr let | @@ -572,6 +603,21 @@ module CertainTypeInference { ) else prefix2.isEmpty() ) + or + exists(CallExprImpl::DynamicCallExpr dce, TupleType tt, int i | + n1 = dce.getArgList() and + tt.getArity() = dce.getNumberOfSyntacticArguments() and + n2 = dce.getSyntacticPositionalArgument(i) and + prefix1 = TypePath::singleton(tt.getPositionalTypeParameter(i)) and + prefix2.isEmpty() + ) + or + exists(ClosureExpr ce, int index | + n1 = ce and + n2 = ce.getParam(index).getPat() and + prefix1 = closureParameterPath(ce.getNumberOfParams(), index) and + prefix2.isEmpty() + ) } pragma[nomagic] @@ -636,6 +682,10 @@ module CertainTypeInference { path.isEmpty() and result instanceof NeverType or + n instanceof ClosureExpr and + path.isEmpty() and + result = closureRootType() + or infersCertainTypeAt(n, path, result.getATypeParameter()) } @@ -835,17 +885,6 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat n1.(ArrayRepeatExpr).getRepeatOperand() = n2 and prefix1 = TypePath::singleton(getArrayTypeParameter()) and prefix2.isEmpty() - or - exists(ClosureExpr ce, int index | - n1 = ce and - n2 = ce.getParam(index).getPat() and - prefix1 = closureParameterPath(ce.getNumberOfParams(), index) and - prefix2.isEmpty() - ) - or - n1.(ClosureExpr).getClosureBody() = n2 and - prefix1 = closureReturnPath() and - prefix2.isEmpty() } /** @@ -881,6 +920,9 @@ private predicate lubCoercion(AstNode parent, AstNode child, TypePath prefix) { strictcount(Expr e | bodyReturns(parent, e)) > 1 and prefix.isEmpty() or + parent = any(ClosureExpr ce | not ce.hasRetType() and ce.getClosureBody() = child) and + prefix = closureReturnPath() + or exists(Struct s | child = [parent.(RangeExpr).getStart(), parent.(RangeExpr).getEnd()] and prefix = TypePath::singleton(TTypeParamTypeParameter(s.getGenericParamList().getATypeParam())) and @@ -888,6 +930,19 @@ private predicate lubCoercion(AstNode parent, AstNode child, TypePath prefix) { ) } +private Type inferUnknownTypeFromAnnotation(AstNode n, TypePath path) { + inferType(n, path) = TUnknownType() and + // Normally, these are coercion sites, but in case a type is unknown we + // allow for type information to flow from the type annotation. + exists(TypeMention tm | result = tm.getTypeAt(path) | + tm = any(LetStmt let | identLetStmt(let, _, n)).getTypeRepr() + or + tm = any(ClosureExpr ce | n = ce.getBody()).getRetType().getTypeRepr() + or + tm = getReturnTypeMention(any(Function f | n = f.getBody())) + ) +} + /** * Holds if the type tree of `n1` at `prefix1` should be equal to the type tree * of `n2` at `prefix2`, but type information should only propagate from `n1` to @@ -1545,12 +1600,14 @@ private module AssocFunctionResolution { * * This is either: * - * 1. `AssocFunctionCallMethodCallExpr`: a method call, `x.m()`; - * 2. `AssocFunctionCallIndexExpr`: an index expression, `x[i]`, which is [syntactic sugar][1] + * 1. `MethodCallExprAssocFunctionCall`: a method call, `x.m()`; + * 2. `IndexExprAssocFunctionCall`: an index expression, `x[i]`, which is [syntactic sugar][1] * for `*x.index(i)`; - * 3. `AssocFunctionCallCallExpr`: a qualified function call, `Q::f(x)`; or - * 4. `AssocFunctionCallOperation`: an operation expression, `x + y`, which is syntactic sugar + * 3. `CallExprAssocFunctionCall`: a qualified function call, `Q::f(x)`; or + * 4. `OperationAssocFunctionCall`: an operation expression, `x + y`, which is syntactic sugar * for `Add::add(x, y)`. + * 5. `DynamicAssocFunctionCall`: a call to a closure, `c(x)`, which is syntactic sugar for + * `c.call_once(x)`, `c.call_mut(x)`, or `c.call(x)`. * * Note that only in case 1 and 2 is auto-dereferencing and borrowing allowed. * @@ -1567,7 +1624,7 @@ private module AssocFunctionResolution { pragma[nomagic] abstract predicate hasNameAndArity(string name, int arity); - abstract Expr getNonReturnNodeAt(FunctionPosition pos); + abstract AstNode getNonReturnNodeAt(FunctionPosition pos); AstNode getNodeAt(FunctionPosition pos) { result = this.getNonReturnNodeAt(pos) @@ -2101,7 +2158,7 @@ private module AssocFunctionResolution { } } - private class AssocFunctionCallMethodCallExpr extends AssocFunctionCall instanceof MethodCallExpr { + private class MethodCallExprAssocFunctionCall extends AssocFunctionCall instanceof MethodCallExpr { override predicate hasNameAndArity(string name, int arity) { name = super.getIdentifier().getText() and arity = super.getNumberOfSyntacticArguments() @@ -2121,7 +2178,7 @@ private module AssocFunctionResolution { override Trait getTrait() { none() } } - private class AssocFunctionCallIndexExpr extends AssocFunctionCall, IndexExpr { + private class IndexExprAssocFunctionCall extends AssocFunctionCall, IndexExpr { private predicate isInMutableContext() { // todo: does not handle all cases yet VariableImpl::assignmentOperationDescendant(_, this) @@ -2151,8 +2208,8 @@ private module AssocFunctionResolution { } } - private class AssocFunctionCallCallExpr extends AssocFunctionCall, CallExpr { - AssocFunctionCallCallExpr() { + private class CallExprAssocFunctionCall extends AssocFunctionCall, CallExpr { + CallExprAssocFunctionCall() { exists(getCallExprPathQualifier(this)) and // even if a target cannot be resolved by path resolution, it may still // be possible to resolve a blanket implementation (so not `forex`) @@ -2184,7 +2241,7 @@ private module AssocFunctionResolution { override Trait getTrait() { result = getCallExprTraitQualifier(this) } } - final class AssocFunctionCallOperation extends AssocFunctionCall, Operation { + final class OperationAssocFunctionCall extends AssocFunctionCall, Operation { override predicate hasNameAndArity(string name, int arity) { this.isOverloaded(_, name, _) and arity = this.getNumberOfOperands() @@ -2242,6 +2299,29 @@ private module AssocFunctionResolution { override Trait getTrait() { this.isOverloaded(result, _, _) } } + private class DynamicAssocFunctionCall extends AssocFunctionCall instanceof CallExprImpl::DynamicCallExpr + { + pragma[nomagic] + override predicate hasNameAndArity(string name, int arity) { + name = "call_once" and // todo: handle call_mut and call + arity = 2 // args are passed in a tuple + } + + override predicate hasReceiver() { any() } + + override AstNode getNonReturnNodeAt(FunctionPosition pos) { + pos.asPosition() = 0 and + result = super.getFunction() + or + pos.asPosition() = 1 and + result = super.getArgList() + } + + override predicate supportsAutoDerefAndBorrow() { any() } + + override Trait getTrait() { result instanceof AnyFnTrait } + } + pragma[nomagic] private AssocFunctionDeclaration getAssocFunctionSuccessor( ImplOrTraitItemNode i, string name, int arity @@ -2445,7 +2525,7 @@ private module AssocFunctionResolution { ) { exists(CallDerefCand cdc, TypePath exprPath | cdc = MkCallDerefCand(afc, selfPos, derefChain) and - CallSatisfiesDerefConstraint::satisfiesConstraintTypeThrough(cdc, impl, _, exprPath, result) and + CallSatisfiesDerefConstraint::satisfiesConstraintThrough(cdc, impl, _, exprPath, result) and exprPath.isCons(getDerefTargetTypeParameter(), path) ) } @@ -3198,7 +3278,7 @@ private module OperationMatchingInput implements MatchingInputSig { } } - class Access extends AssocFunctionResolution::AssocFunctionCallOperation { + class Access extends AssocFunctionResolution::OperationAssocFunctionCall { Type getTypeArgument(TypeArgumentPosition apos, TypePath path) { none() } pragma[nomagic] @@ -3566,7 +3646,7 @@ private module AwaitSatisfiesType = SatisfiesType type of pattern (loop variable) exists(ForExpr fe, TypePath exprPath, AssociatedTypeTypeParameter tp | n = fe.getPat() and - ForIterableSatisfiesType::satisfiesConstraintType(fe.getIterable(), _, exprPath, result) and + ForIterableSatisfiesType::satisfiesConstraint(fe.getIterable(), _, exprPath, result) and exprPath.isCons(tp, path) | tp = getIntoIteratorItemTypeParameter() @@ -3744,130 +3824,36 @@ private Type inferForLoopExprType(AstNode n, TypePath path) { ) } -/** - * An invoked expression, the target of a call that is either a local variable - * or a non-path expression. This means that the expression denotes a - * first-class function. - */ -final private class InvokedClosureExpr extends Expr { - private CallExprImpl::DynamicCallExpr call; - - InvokedClosureExpr() { call.getFunction() = this } - - Type getTypeAt(TypePath path) { result = inferType(this, path) } - - CallExpr getCall() { result = call } -} - -private module InvokedClosureSatisfiesTypeInput implements SatisfiesTypeInputSig -{ - predicate relevantConstraint(InvokedClosureExpr term, Type constraint) { - exists(term) and - constraint.(TraitType).getTrait() instanceof FnOnceTrait - } -} - -private module InvokedClosureSatisfiesType = - SatisfiesType; - -/** Gets the type of `ce` when viewed as an implementation of `FnOnce`. */ -private Type invokedClosureFnTypeAt(InvokedClosureExpr ce, TypePath path) { - InvokedClosureSatisfiesType::satisfiesConstraintType(ce, _, path, result) -} - -/** - * Gets the root type of a closure. - * - * We model closures as `dyn Fn` trait object types. A closure might implement - * only `Fn`, `FnMut`, or `FnOnce`. But since `Fn` is a subtrait of the others, - * giving closures the type `dyn Fn` works well in practice -- even if not - * entirely accurate. - */ -private DynTraitType closureRootType() { - result = TDynTraitType(any(FnTrait t)) // always exists because of the mention in `builtins/mentions.rs` -} - -/** Gets the path to a closure's return type. */ -private TypePath closureReturnPath() { - result = - TypePath::singleton(TDynTraitTypeParameter(any(FnTrait t), any(FnOnceTrait t).getOutputType())) -} - -/** Gets the path to a closure with arity `arity`'s `index`th parameter type. */ pragma[nomagic] -private TypePath closureParameterPath(int arity, int index) { - result = - TypePath::cons(TDynTraitTypeParameter(_, any(FnTrait t).getTypeParam()), - TypePath::singleton(getTupleTypeParameter(arity, index))) -} - -/** Gets the path to the return type of the `FnOnce` trait. */ -private TypePath fnReturnPath() { - result = TypePath::singleton(getAssociatedTypeTypeParameter(any(FnOnceTrait t).getOutputType())) -} - -/** - * Gets the path to the parameter type of the `FnOnce` trait with arity `arity` - * and index `index`. - */ -pragma[nomagic] -private TypePath fnParameterPath(int arity, int index) { - result = - TypePath::cons(TTypeParamTypeParameter(any(FnOnceTrait t).getTypeParam()), - TypePath::singleton(getTupleTypeParameter(arity, index))) -} - -pragma[nomagic] -private Type inferDynamicCallExprType(Expr n, TypePath path) { - exists(InvokedClosureExpr ce | - // Propagate the function's return type to the call expression - exists(TypePath path0 | result = invokedClosureFnTypeAt(ce, path0) | - n = ce.getCall() and - path = path0.stripPrefix(fnReturnPath()) +private Type inferClosureExprType(AstNode n, TypePath path) { + exists(ClosureExpr ce | + n = ce and + ( + path = TypePath::singleton(TDynTraitTypeParameter(_, any(FnTrait t).getTypeParam())) and + result.(TupleType).getArity() = ce.getNumberOfParams() or - // Propagate the function's parameter type to the arguments - exists(int index | - n = ce.getCall().getSyntacticPositionalArgument(index) and - path = - path0.stripPrefix(fnParameterPath(ce.getCall().getArgList().getNumberOfArgs(), index)) + exists(TypePath path0 | + result = ce.getRetType().getTypeRepr().(TypeMention).getTypeAt(path0) and + path = closureReturnPath().append(path0) ) ) or - // _If_ the invoked expression has the type of a closure, then we propagate - // the surrounding types into the closure. - exists(int arity, TypePath path0 | ce.getTypeAt(TypePath::nil()) = closureRootType() | - // Propagate the type of arguments to the parameter types of closure - exists(int index, ArgList args | - n = ce and - args = ce.getCall().getArgList() and - arity = args.getNumberOfArgs() and - result = inferType(args.getArg(index), path0) and - path = closureParameterPath(arity, index).append(path0) - ) - or - // Propagate the type of the call expression to the return type of the closure - n = ce and - arity = ce.getCall().getArgList().getNumberOfArgs() and - result = inferType(ce.getCall(), path0) and - path = closureReturnPath().append(path0) + exists(Param p | + p = ce.getAParam() and + not p.hasTypeRepr() and + n = p.getPat() and + result = TUnknownType() and + path.isEmpty() ) ) } pragma[nomagic] -private Type inferClosureExprType(AstNode n, TypePath path) { - exists(ClosureExpr ce | - n = ce and - path.isEmpty() and - result = closureRootType() - or - n = ce and - path = TypePath::singleton(TDynTraitTypeParameter(_, any(FnTrait t).getTypeParam())) and - result.(TupleType).getArity() = ce.getNumberOfParams() - or - // Propagate return type annotation to body - n = ce.getClosureBody() and - result = ce.getRetType().getTypeRepr().(TypeMention).getTypeAt(path) +private TupleType inferArgList(ArgList args, TypePath path) { + exists(CallExprImpl::DynamicCallExpr dce | + args = dce.getArgList() and + result.getArity() = dce.getNumberOfSyntacticArguments() and + path.isEmpty() ) } @@ -3915,7 +3901,8 @@ private module Cached { or i instanceof ImplItemNode and dispatch = false | - result = call.(AssocFunctionResolution::AssocFunctionCall).resolveCallTarget(i, _, _, _) + result = call.(AssocFunctionResolution::AssocFunctionCall).resolveCallTarget(i, _, _, _) and + not call instanceof CallExprImpl::DynamicCallExpr ) } @@ -4023,11 +4010,13 @@ private module Cached { or result = inferForLoopExprType(n, path) or - result = inferDynamicCallExprType(n, path) - or result = inferClosureExprType(n, path) or + result = inferArgList(n, path) + or result = inferDeconstructionPatType(n, path) + or + result = inferUnknownTypeFromAnnotation(n, path) ) } } diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll index 70dfbeda848..c4650f97c34 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll @@ -769,7 +769,7 @@ private Type getPathConcreteAssocTypeAt(Path path, TypePath typePath) { TypeAlias alias, TypePath path0 | pathConcreteTypeAssocType(path, tm, trait, traitOrTmTrait, alias) and - PathSatisfiesConstraint::satisfiesConstraintTypeThrough(tm, impl, traitOrTmTrait, path0, result) and + PathSatisfiesConstraint::satisfiesConstraintThrough(tm, impl, traitOrTmTrait, path0, result) and path0.isCons(TAssociatedTypeTypeParameter(trait, alias), typePath) ) } diff --git a/rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected b/rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected index 2ac439e085b..ffc2576a05e 100644 --- a/rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected +++ b/rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected @@ -2,3 +2,4 @@ multipleResolvedTargets | main.rs:2223:9:2223:31 | ... .my_add(...) | | main.rs:2225:9:2225:29 | ... .my_add(...) | | main.rs:2740:13:2740:17 | x.f() | +| regressions.rs:179:17:179:27 | ... + ... | diff --git a/rust/ql/test/library-tests/type-inference/closure.rs b/rust/ql/test/library-tests/type-inference/closure.rs index cc756a6b267..fbef401bb08 100644 --- a/rust/ql/test/library-tests/type-inference/closure.rs +++ b/rust/ql/test/library-tests/type-inference/closure.rs @@ -63,7 +63,7 @@ mod fn_once_trait { }; let _r = apply(f, true); // $ target=apply type=_r:i64 - let f = |x| x + 1; // $ MISSING: type=x:i64 target=add + let f = |x| x + 1; // $ type=x:i64 $ MISSING: target=add let _r2 = apply_two(f); // $ target=apply_two certainType=_r2:i64 } } @@ -100,7 +100,7 @@ mod fn_mut_trait { }; let _r = apply(f, true); // $ target=apply type=_r:i64 - let f = |x| x + 1; // $ MISSING: type=x:i64 target=add + let f = |x| x + 1; // $ type=x:i64 $ MISSING: target=add let _r2 = apply_two(f); // $ target=apply_two certainType=_r2:i64 } } @@ -137,7 +137,7 @@ mod fn_trait { }; let _r = apply(f, true); // $ target=apply type=_r:i64 - let f = |x| x + 1; // $ MISSING: type=x:i64 target=add + let f = |x| x + 1; // $ type=x:i64 $ MISSING: target=add let _r2 = apply_two(f); // $ target=apply_two certainType=_r2:i64 } } @@ -152,3 +152,90 @@ mod dyn_fn_once { let _r2 = apply_boxed(Box::new(|_: i64| true), 3); // $ target=apply_boxed target=new type=_r2:bool } } + +mod closure_infer_param { + fn apply1 i64>(f: F, a: i64) -> i64 { + f(a) + } + + fn apply2(f: impl Fn(i64) -> i64, a: i64) -> i64 { + f(a) + } + + fn apply3(f: &dyn Fn(i64) -> i64, a: i64) -> i64 { + f(a) + } + + fn apply4 i64>(mut f: F, a: i64) -> i64 { + f(a) + } + + fn apply5(f: &mut dyn FnMut(i64) -> i64, a: i64) -> i64 { + f(a) + } + + fn apply6(f: impl Fn(T) -> i64, a: T) -> i64 { + f(a) + } + + fn apply7 i64>(mut f: F, a: T) -> i64 { + f(a) + } + + fn test() { + let f = |x| x; // $ type=x:i64 + let _r = apply1(f, 1i64); // $ target=apply1 + + let f = |x| x; // $ type=x:i64 + let _r = apply2(f, 2i64); // $ target=apply2 + + let f = |x| x; // $ type=x:i64 + let _r = apply3(&f, 3i64); // $ target=apply3 + + let f = |x| x; // $ type=x:i64 + let _r = apply4(f, 4i64); // $ target=apply4 + + let mut f = |x| x; // $ MISSING: type=x:i64 + let _r = apply5(&mut f, 5i64); // $ target=apply5 + + let f = |x| x; // $ type=x:i64 + let _r = apply6(f, 6i64); // $ target=apply6 + + let f = |x| x; // $ type=x:i64 + let _r = apply7(f, 7i64); // $ target=apply7 + } +} + +mod implicit_deref { + use std::ops::Deref; + + struct S(T); + + impl Deref for S { + type Target = dyn Fn(T) -> bool; + + fn deref(&self) -> &Self::Target { + &|_| false + } + } + + pub fn test() { + let x = 0i64; + let v = Default::default(); // $ type=v:i64 target=default + let s = S(v); + let _ret = s(x); // $ type=_ret:bool + + let x = 0i32; + let v = Default::default(); // $ type=v:i32 target=default + let s = S(v); + let s_ref = &s; + let _ret = s_ref(x); // $ type=_ret:bool + + // The call below is not an implicit deref, instead it will target + // `impl FnOnce for &F` from + // https://doc.rust-lang.org/std/ops/trait.FnOnce.html#impl-FnOnce%3CA%3E-for-%26F + // and we currently cannot handle inferring the output type + let c = |x| x; // $ MISSING: type=x:i64 + (&c)(x); // $ MISSING: type=_:i64 + } +} diff --git a/rust/ql/test/library-tests/type-inference/main.rs b/rust/ql/test/library-tests/type-inference/main.rs index 6c9f2c801d5..ecb4816ebb0 100644 --- a/rust/ql/test/library-tests/type-inference/main.rs +++ b/rust/ql/test/library-tests/type-inference/main.rs @@ -2259,7 +2259,7 @@ mod loops { // for loops with arrays for i in [1, 2, 3] {} // $ type=i:i32 - for i in [1, 2, 3].map(|x| x + 1) {} // $ target=map MISSING: type=i:i32 + for i in [1, 2, 3].map(|x| x + 1) {} // $ target=map target=add type=i:i32 for i in [1, 2, 3].into_iter() {} // $ target=into_iter type=i:i32 let vals1 = [1u8, 2, 3]; // $ type=vals1:TArray.u8 @@ -2759,6 +2759,30 @@ mod dereference; mod dyn_type; mod regressions; +mod arg_trait_bounds { + struct Gen(T); + + trait Container { + fn get_input(&self) -> T; + } + + fn my_get>(c: &T) -> bool { + c.get_input() == 42 // $ target=get_input target=eq + } + + impl Container for Gen { + fn get_input(&self) -> GT { + self.0 // $ fieldof=Gen + } + } + + fn test() { + let v = Default::default(); // $ type=v:i64 target=default + let g = Gen(v); + let _ = my_get(&g); // $ target=my_get + } +} + fn main() { field_access::f(); // $ target=f method_impl::f(); // $ target=f diff --git a/rust/ql/test/library-tests/type-inference/regressions.rs b/rust/ql/test/library-tests/type-inference/regressions.rs index e1b47479f5d..5c830bb3db2 100644 --- a/rust/ql/test/library-tests/type-inference/regressions.rs +++ b/rust/ql/test/library-tests/type-inference/regressions.rs @@ -130,3 +130,52 @@ mod regression4 { } } } + +mod regression5 { + struct S1; + struct S2(T2); + + impl From<&S1> for S2 { + fn from(_: &S1) -> Self { + S2(S1) + } + } + + impl From for S2 { + fn from(t: T) -> Self { + S2(t) + } + } + + fn foo() -> S2 { + let x = S1.into(); // $ target=into + x // $ SPURIOUS: type=x:T2.TRef.S1 -- happens because we currently do not consider the two `impl` blocks to be siblings + } +} + +mod regression6 { + use std::ops::Add; + struct S(T); + + impl Add for S { + type Output = Self; + + // add1 + fn add(self, _rhs: Self) -> Self::Output { + self + } + } + + impl Add for S { + type Output = Self; + + // add2 + fn add(self, _rhs: T) -> Self::Output { + self + } + } + + fn foo() { + let x = S(0) + S(1); // $ target=add1 $ SPURIOUS: target=add2 type=x:T.T.i32 + } +} diff --git a/rust/ql/test/library-tests/type-inference/type-inference.expected b/rust/ql/test/library-tests/type-inference/type-inference.expected index 1e2c753b242..4be70359842 100644 --- a/rust/ql/test/library-tests/type-inference/type-inference.expected +++ b/rust/ql/test/library-tests/type-inference/type-inference.expected @@ -545,6 +545,14 @@ inferCertainType | blanket_impl.rs:299:47:299:67 | "SELECT * FROM users" | | {EXTERNAL LOCATION} | & | | blanket_impl.rs:299:47:299:67 | "SELECT * FROM users" | TRef | {EXTERNAL LOCATION} | str | | closure.rs:4:19:31:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:6:13:6:22 | my_closure | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:6:13:6:22 | my_closure | dyn(Args) | {EXTERNAL LOCATION} | (T_2) | +| closure.rs:6:13:6:22 | my_closure | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | +| closure.rs:6:13:6:22 | my_closure | dyn(Args).T1 | {EXTERNAL LOCATION} | bool | +| closure.rs:6:26:6:38 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:6:26:6:38 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_2) | +| closure.rs:6:26:6:38 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | +| closure.rs:6:26:6:38 | \|...\| ... | dyn(Args).T1 | {EXTERNAL LOCATION} | bool | | closure.rs:6:27:6:27 | a | | {EXTERNAL LOCATION} | bool | | closure.rs:6:30:6:30 | b | | {EXTERNAL LOCATION} | bool | | closure.rs:6:33:6:33 | a | | {EXTERNAL LOCATION} | bool | @@ -552,19 +560,47 @@ inferCertainType | closure.rs:6:38:6:38 | b | | {EXTERNAL LOCATION} | bool | | closure.rs:8:13:8:13 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:8:22:8:25 | 1i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:9:13:9:19 | add_one | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:9:23:9:34 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:9:31:9:34 | 1i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:10:18:10:24 | add_one | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:10:25:10:27 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:10:25:10:27 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:10:26:10:26 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:14:13:14:20 | add_zero | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:14:13:14:20 | add_zero | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:14:13:14:20 | add_zero | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:14:24:14:33 | \|...\| n | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:14:24:14:33 | \|...\| n | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:14:24:14:33 | \|...\| n | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:14:25:14:25 | n | | {EXTERNAL LOCATION} | i64 | | closure.rs:14:33:14:33 | n | | {EXTERNAL LOCATION} | i64 | +| closure.rs:15:18:15:25 | add_zero | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:15:18:15:25 | add_zero | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:15:18:15:25 | add_zero | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:17:13:17:21 | _get_bool | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:17:25:21:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:24:13:24:14 | id | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:24:18:24:22 | \|...\| b | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:25:18:25:19 | id | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:25:20:25:25 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:25:20:25:25 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:25:21:25:24 | true | | {EXTERNAL LOCATION} | bool | +| closure.rs:28:13:28:15 | id2 | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:28:19:28:23 | \|...\| b | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:30:13:30:15 | _b2 | | {EXTERNAL LOCATION} | bool | +| closure.rs:30:25:30:27 | id2 | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:35:44:35:44 | f | | closure.rs:35:20:35:41 | F | | closure.rs:35:50:37:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:36:23:36:23 | f | | closure.rs:35:20:35:41 | F | +| closure.rs:36:24:36:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:36:24:36:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:36:25:36:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:39:45:39:45 | f | | closure.rs:39:28:39:42 | F | | closure.rs:39:51:41:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:40:23:40:23 | f | | closure.rs:39:28:39:42 | F | +| closure.rs:40:24:40:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:40:24:40:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:40:25:40:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:43:46:43:46 | f | | closure.rs:43:22:43:43 | F | | closure.rs:43:52:46:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -573,23 +609,41 @@ inferCertainType | closure.rs:48:45:48:45 | a | | closure.rs:48:14:48:14 | A | | closure.rs:48:56:50:5 | { ... } | | closure.rs:48:17:48:17 | B | | closure.rs:49:9:49:9 | f | | closure.rs:48:20:48:36 | F | +| closure.rs:49:10:49:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:49:10:49:12 | ArgList | T0 | closure.rs:48:14:48:14 | A | | closure.rs:49:11:49:11 | a | | closure.rs:48:14:48:14 | A | | closure.rs:52:18:52:18 | f | | closure.rs:52:21:52:43 | impl ... | | closure.rs:52:53:54:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:53:9:53:9 | f | | closure.rs:52:21:52:43 | impl ... | | closure.rs:56:15:68:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:57:13:57:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:57:13:57:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:57:13:57:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | +| closure.rs:57:17:63:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:57:17:63:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:57:17:63:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:57:18:57:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:58:16:58:16 | x | | {EXTERNAL LOCATION} | bool | +| closure.rs:64:24:64:24 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:64:24:64:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:64:24:64:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:64:27:64:30 | true | | {EXTERNAL LOCATION} | bool | +| closure.rs:66:13:66:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:66:17:66:25 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:67:13:67:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:67:19:67:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:67:29:67:29 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:72:47:72:47 | f | | closure.rs:72:20:72:40 | F | | closure.rs:72:53:74:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:73:23:73:23 | f | | closure.rs:72:20:72:40 | F | +| closure.rs:73:24:73:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:73:24:73:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:73:25:73:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:76:48:76:48 | f | | closure.rs:76:28:76:41 | F | | closure.rs:76:54:78:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:77:23:77:23 | f | | closure.rs:76:28:76:41 | F | +| closure.rs:77:24:77:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:77:24:77:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:77:25:77:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:80:49:80:49 | f | | closure.rs:80:22:80:42 | F | | closure.rs:80:55:83:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -598,23 +652,41 @@ inferCertainType | closure.rs:85:48:85:48 | a | | closure.rs:85:14:85:14 | A | | closure.rs:85:59:87:5 | { ... } | | closure.rs:85:17:85:17 | B | | closure.rs:86:9:86:9 | f | | closure.rs:85:20:85:35 | F | +| closure.rs:86:10:86:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:86:10:86:12 | ArgList | T0 | closure.rs:85:14:85:14 | A | | closure.rs:86:11:86:11 | a | | closure.rs:85:14:85:14 | A | | closure.rs:89:22:89:22 | f | | closure.rs:89:25:89:46 | impl ... | | closure.rs:89:56:91:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:90:9:90:9 | f | | closure.rs:89:25:89:46 | impl ... | | closure.rs:93:15:105:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:94:13:94:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:94:13:94:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:94:13:94:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | +| closure.rs:94:17:100:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:94:17:100:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:94:17:100:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:94:18:94:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:95:16:95:16 | x | | {EXTERNAL LOCATION} | bool | +| closure.rs:101:24:101:24 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:101:24:101:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:101:24:101:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:101:27:101:30 | true | | {EXTERNAL LOCATION} | bool | +| closure.rs:103:13:103:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:103:17:103:25 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:104:13:104:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:104:19:104:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:104:29:104:29 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:109:40:109:40 | f | | closure.rs:109:20:109:37 | F | | closure.rs:109:46:111:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:110:23:110:23 | f | | closure.rs:109:20:109:37 | F | +| closure.rs:110:24:110:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:110:24:110:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:110:25:110:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:113:41:113:41 | f | | closure.rs:113:28:113:38 | F | | closure.rs:113:47:115:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:114:23:114:23 | f | | closure.rs:113:28:113:38 | F | +| closure.rs:114:24:114:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:114:24:114:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:114:25:114:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:117:42:117:42 | f | | closure.rs:117:22:117:39 | F | | closure.rs:117:48:120:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -623,16 +695,30 @@ inferCertainType | closure.rs:122:41:122:41 | a | | closure.rs:122:14:122:14 | A | | closure.rs:122:52:124:5 | { ... } | | closure.rs:122:17:122:17 | B | | closure.rs:123:9:123:9 | f | | closure.rs:122:20:122:32 | F | +| closure.rs:123:10:123:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:123:10:123:12 | ArgList | T0 | closure.rs:122:14:122:14 | A | | closure.rs:123:11:123:11 | a | | closure.rs:122:14:122:14 | A | | closure.rs:126:18:126:18 | f | | closure.rs:126:21:126:39 | impl ... | | closure.rs:126:49:128:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:127:9:127:9 | f | | closure.rs:126:21:126:39 | impl ... | | closure.rs:130:15:142:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:131:13:131:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:131:13:131:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:131:13:131:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | +| closure.rs:131:17:137:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:131:17:137:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:131:17:137:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:131:18:131:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:132:16:132:16 | x | | {EXTERNAL LOCATION} | bool | +| closure.rs:138:24:138:24 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:138:24:138:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:138:24:138:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:138:27:138:30 | true | | {EXTERNAL LOCATION} | bool | +| closure.rs:140:13:140:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:140:17:140:25 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:141:13:141:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:141:19:141:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:141:29:141:29 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:146:54:146:54 | f | | {EXTERNAL LOCATION} | Box | | closure.rs:146:54:146:54 | f | A | {EXTERNAL LOCATION} | Global | | closure.rs:146:54:146:54 | f | T | closure.rs:146:26:146:51 | F | @@ -641,6 +727,8 @@ inferCertainType | closure.rs:147:9:147:9 | f | | {EXTERNAL LOCATION} | Box | | closure.rs:147:9:147:9 | f | A | {EXTERNAL LOCATION} | Global | | closure.rs:147:9:147:9 | f | T | closure.rs:146:26:146:51 | F | +| closure.rs:147:10:147:14 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:147:10:147:14 | ArgList | T0 | closure.rs:146:20:146:20 | A | | closure.rs:147:11:147:13 | arg | | closure.rs:146:20:146:20 | A | | closure.rs:150:30:150:30 | f | | {EXTERNAL LOCATION} | Box | | closure.rs:150:30:150:30 | f | A | {EXTERNAL LOCATION} | Global | @@ -659,8 +747,154 @@ inferCertainType | closure.rs:151:34:151:36 | arg | | closure.rs:150:24:150:24 | A | | closure.rs:152:31:152:53 | ...::new(...) | | {EXTERNAL LOCATION} | Box | | closure.rs:152:31:152:53 | ...::new(...) | A | {EXTERNAL LOCATION} | Global | +| closure.rs:152:40:152:52 | \|...\| true | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:152:40:152:52 | \|...\| true | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:152:40:152:52 | \|...\| true | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:152:41:152:41 | _ | | {EXTERNAL LOCATION} | i64 | | closure.rs:152:49:152:52 | true | | {EXTERNAL LOCATION} | bool | +| closure.rs:157:34:157:34 | f | | closure.rs:157:15:157:31 | F | +| closure.rs:157:40:157:40 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:157:55:159:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:158:9:158:9 | f | | closure.rs:157:15:157:31 | F | +| closure.rs:158:10:158:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:158:10:158:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:158:11:158:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:161:15:161:15 | f | | closure.rs:161:18:161:36 | impl ... | +| closure.rs:161:39:161:39 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:161:54:163:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:162:9:162:9 | f | | closure.rs:161:18:161:36 | impl ... | +| closure.rs:162:10:162:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:162:10:162:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:162:11:162:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:15:165:15 | f | | {EXTERNAL LOCATION} | & | +| closure.rs:165:15:165:15 | f | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:165:15:165:15 | f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:165:15:165:15 | f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:15:165:15 | f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:39:165:39 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:54:167:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:9:166:9 | f | | {EXTERNAL LOCATION} | & | +| closure.rs:166:9:166:9 | f | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:166:9:166:9 | f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:166:9:166:9 | f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:9:166:9 | f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:10:166:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:166:10:166:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:11:166:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:169:41:169:41 | f | | closure.rs:169:15:169:34 | F | +| closure.rs:169:47:169:47 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:169:62:171:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:170:9:170:9 | f | | closure.rs:169:15:169:34 | F | +| closure.rs:170:10:170:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:170:10:170:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:170:11:170:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:15:173:15 | f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:173:15:173:15 | f | TRefMut | {EXTERNAL LOCATION} | dyn FnMut | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:46:173:46 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:61:175:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:9:174:9 | f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:174:9:174:9 | f | TRefMut | {EXTERNAL LOCATION} | dyn FnMut | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:10:174:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:174:10:174:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:11:174:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:177:18:177:18 | f | | closure.rs:177:21:177:37 | impl ... | +| closure.rs:177:40:177:40 | a | | closure.rs:177:15:177:15 | T | +| closure.rs:177:53:179:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:178:9:178:9 | f | | closure.rs:177:21:177:37 | impl ... | +| closure.rs:178:10:178:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:178:10:178:12 | ArgList | T0 | closure.rs:177:15:177:15 | T | +| closure.rs:178:11:178:11 | a | | closure.rs:177:15:177:15 | T | +| closure.rs:181:42:181:42 | f | | closure.rs:181:18:181:35 | F | +| closure.rs:181:48:181:48 | a | | closure.rs:181:15:181:15 | T | +| closure.rs:181:61:183:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:182:9:182:9 | f | | closure.rs:181:18:181:35 | F | +| closure.rs:182:10:182:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:182:10:182:12 | ArgList | T0 | closure.rs:181:15:181:15 | T | +| closure.rs:182:11:182:11 | a | | closure.rs:181:15:181:15 | T | +| closure.rs:185:15:206:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:186:13:186:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:186:17:186:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:187:13:187:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:18:187:32 | apply1(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:25:187:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:187:28:187:31 | 1i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:13:189:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:189:17:189:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:190:13:190:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:18:190:32 | apply2(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:25:190:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:190:28:190:31 | 2i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:13:192:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:192:17:192:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:193:13:193:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:18:193:33 | apply3(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:25:193:26 | &f | | {EXTERNAL LOCATION} | & | +| closure.rs:193:26:193:26 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:193:29:193:32 | 3i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:13:195:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:195:17:195:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:196:13:196:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:18:196:32 | apply4(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:25:196:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:196:28:196:31 | 4i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:198:17:198:17 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:198:21:198:25 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:199:13:199:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:199:18:199:37 | apply5(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:199:25:199:30 | &mut f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:199:30:199:30 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:199:33:199:36 | 5i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:13:201:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:201:17:201:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:202:13:202:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:18:202:32 | apply6(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:25:202:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:202:28:202:31 | 6i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:13:204:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:204:17:204:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:205:13:205:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:18:205:32 | apply7(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:25:205:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:205:28:205:31 | 7i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:217:18:217:22 | SelfParam | | {EXTERNAL LOCATION} | & | +| closure.rs:217:18:217:22 | SelfParam | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:217:18:217:22 | SelfParam | TRef.T | closure.rs:214:10:214:10 | T | +| closure.rs:217:42:219:9 | { ... } | | {EXTERNAL LOCATION} | & | +| closure.rs:217:42:219:9 | { ... } | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Args).T0 | closure.rs:214:10:214:10 | T | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Output) | {EXTERNAL LOCATION} | bool | +| closure.rs:218:13:218:22 | &... | | {EXTERNAL LOCATION} | & | +| closure.rs:218:14:218:22 | \|...\| false | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:218:18:218:22 | false | | {EXTERNAL LOCATION} | bool | +| closure.rs:222:19:240:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:223:13:223:13 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:223:17:223:20 | 0i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:226:21:226:23 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:226:21:226:23 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:226:22:226:22 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:228:13:228:13 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:228:17:228:20 | 0i32 | | {EXTERNAL LOCATION} | i32 | +| closure.rs:231:13:231:17 | s_ref | | {EXTERNAL LOCATION} | & | +| closure.rs:231:21:231:22 | &s | | {EXTERNAL LOCATION} | & | +| closure.rs:232:20:232:24 | s_ref | | {EXTERNAL LOCATION} | & | +| closure.rs:232:25:232:27 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:232:25:232:27 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:232:26:232:26 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:13:238:13 | c | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:238:17:238:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:239:9:239:12 | (...) | | {EXTERNAL LOCATION} | & | +| closure.rs:239:10:239:11 | &c | | {EXTERNAL LOCATION} | & | +| closure.rs:239:11:239:11 | c | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:239:13:239:15 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:13:239:15 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:14:239:14 | x | | {EXTERNAL LOCATION} | i32 | | dereference.rs:13:14:13:18 | SelfParam | | {EXTERNAL LOCATION} | & | | dereference.rs:13:14:13:18 | SelfParam | TRef | dereference.rs:5:1:7:1 | MyIntPointer | | dereference.rs:13:29:15:5 | { ... } | | {EXTERNAL LOCATION} | & | @@ -2259,6 +2493,7 @@ inferCertainType | main.rs:1340:40:1345:5 | { ... } | | {EXTERNAL LOCATION} | Result | | main.rs:1340:40:1345:5 | { ... } | E | main.rs:1320:5:1321:14 | S2 | | main.rs:1340:40:1345:5 | { ... } | T | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:24:1343:28 | \|...\| s | | {EXTERNAL LOCATION} | dyn Fn | | main.rs:1349:30:1349:34 | input | | {EXTERNAL LOCATION} | Result | | main.rs:1349:30:1349:34 | input | E | main.rs:1317:5:1318:14 | S1 | | main.rs:1349:30:1349:34 | input | T | main.rs:1349:20:1349:27 | T | @@ -2268,6 +2503,7 @@ inferCertainType | main.rs:1350:21:1350:25 | input | | {EXTERNAL LOCATION} | Result | | main.rs:1350:21:1350:25 | input | E | main.rs:1317:5:1318:14 | S1 | | main.rs:1350:21:1350:25 | input | T | main.rs:1349:20:1349:27 | T | +| main.rs:1351:49:1354:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | main.rs:1352:22:1352:27 | "{:?}\\n" | | {EXTERNAL LOCATION} | & | | main.rs:1352:22:1352:27 | "{:?}\\n" | TRef | {EXTERNAL LOCATION} | str | | main.rs:1352:22:1352:30 | ...::_print(...) | | {EXTERNAL LOCATION} | () | @@ -3182,6 +3418,7 @@ inferCertainType | main.rs:2261:28:2261:29 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2262:9:2262:44 | for ... in ... { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2262:18:2262:26 | [...] | | {EXTERNAL LOCATION} | [;] | +| main.rs:2262:32:2262:40 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | main.rs:2262:43:2262:44 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2263:9:2263:41 | for ... in ... { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2263:18:2263:26 | [...] | | {EXTERNAL LOCATION} | [;] | @@ -3715,48 +3952,65 @@ inferCertainType | main.rs:2747:21:2747:21 | y | | {EXTERNAL LOCATION} | & | | main.rs:2750:13:2750:13 | y | | {EXTERNAL LOCATION} | usize | | main.rs:2751:23:2751:23 | y | | {EXTERNAL LOCATION} | usize | -| main.rs:2762:11:2797:1 | { ... } | | {EXTERNAL LOCATION} | () | -| main.rs:2763:5:2763:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2764:5:2764:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:5:2765:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:20:2765:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:41:2765:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2766:5:2766:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2767:5:2767:41 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2768:5:2768:45 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2769:5:2769:30 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2770:5:2770:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2771:5:2771:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2772:5:2772:32 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2773:5:2773:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2774:5:2774:36 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2775:5:2775:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2776:5:2776:29 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2777:5:2777:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2778:5:2778:24 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2779:5:2779:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2780:5:2780:18 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2781:5:2781:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future | -| main.rs:2781:5:2781:15 | ...::f(...) | dyn(Output) | {EXTERNAL LOCATION} | () | -| main.rs:2782:5:2782:19 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2783:5:2783:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2784:5:2784:14 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2785:5:2785:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2786:5:2786:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2787:5:2787:43 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2788:5:2788:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2789:5:2789:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2790:5:2790:28 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2791:5:2791:23 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2792:5:2792:41 | ...::test_all_patterns(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2793:5:2793:49 | ...::box_patterns(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2794:5:2794:20 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2795:5:2795:20 | ...::f(...) | | {EXTERNAL LOCATION} | Box | -| main.rs:2795:5:2795:20 | ...::f(...) | A | {EXTERNAL LOCATION} | Global | -| main.rs:2795:5:2795:20 | ...::f(...) | T | main.rs:2547:5:2549:5 | dyn MyTrait | -| main.rs:2795:5:2795:20 | ...::f(...) | T.dyn(T) | {EXTERNAL LOCATION} | i32 | -| main.rs:2795:16:2795:19 | true | | {EXTERNAL LOCATION} | bool | -| main.rs:2796:5:2796:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2766:22:2766:26 | SelfParam | | {EXTERNAL LOCATION} | & | +| main.rs:2766:22:2766:26 | SelfParam | TRef | main.rs:2765:5:2767:5 | Self [trait Container] | +| main.rs:2769:34:2769:34 | c | | {EXTERNAL LOCATION} | & | +| main.rs:2769:34:2769:34 | c | TRef | main.rs:2769:15:2769:31 | T | +| main.rs:2769:49:2771:5 | { ... } | | {EXTERNAL LOCATION} | bool | +| main.rs:2770:9:2770:9 | c | | {EXTERNAL LOCATION} | & | +| main.rs:2770:9:2770:9 | c | TRef | main.rs:2769:15:2769:31 | T | +| main.rs:2774:22:2774:26 | SelfParam | | {EXTERNAL LOCATION} | & | +| main.rs:2774:22:2774:26 | SelfParam | TRef | main.rs:2763:5:2763:21 | Gen | +| main.rs:2774:22:2774:26 | SelfParam | TRef.T | main.rs:2773:10:2773:17 | GT | +| main.rs:2774:35:2776:9 | { ... } | | main.rs:2773:10:2773:17 | GT | +| main.rs:2775:13:2775:16 | self | | {EXTERNAL LOCATION} | & | +| main.rs:2775:13:2775:16 | self | TRef | main.rs:2763:5:2763:21 | Gen | +| main.rs:2775:13:2775:16 | self | TRef.T | main.rs:2773:10:2773:17 | GT | +| main.rs:2779:15:2783:5 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2782:17:2782:26 | my_get(...) | | {EXTERNAL LOCATION} | bool | +| main.rs:2782:24:2782:25 | &g | | {EXTERNAL LOCATION} | & | +| main.rs:2786:11:2821:1 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2787:5:2787:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2788:5:2788:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:5:2789:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:20:2789:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:41:2789:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2790:5:2790:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2791:5:2791:41 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2792:5:2792:45 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2793:5:2793:30 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2794:5:2794:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2795:5:2795:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2796:5:2796:32 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2797:5:2797:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2798:5:2798:36 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2799:5:2799:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2800:5:2800:29 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2801:5:2801:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2802:5:2802:24 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2803:5:2803:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2804:5:2804:18 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2805:5:2805:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future | +| main.rs:2805:5:2805:15 | ...::f(...) | dyn(Output) | {EXTERNAL LOCATION} | () | +| main.rs:2806:5:2806:19 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2807:5:2807:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2808:5:2808:14 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2809:5:2809:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2810:5:2810:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2811:5:2811:43 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2812:5:2812:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2813:5:2813:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2814:5:2814:28 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2815:5:2815:23 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2816:5:2816:41 | ...::test_all_patterns(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2817:5:2817:49 | ...::box_patterns(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2818:5:2818:20 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2819:5:2819:20 | ...::f(...) | | {EXTERNAL LOCATION} | Box | +| main.rs:2819:5:2819:20 | ...::f(...) | A | {EXTERNAL LOCATION} | Global | +| main.rs:2819:5:2819:20 | ...::f(...) | T | main.rs:2547:5:2549:5 | dyn MyTrait | +| main.rs:2819:5:2819:20 | ...::f(...) | T.dyn(T) | {EXTERNAL LOCATION} | i32 | +| main.rs:2819:16:2819:19 | true | | {EXTERNAL LOCATION} | bool | +| main.rs:2820:5:2820:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | | overloading.rs:4:19:4:23 | SelfParam | | {EXTERNAL LOCATION} | & | | overloading.rs:4:19:4:23 | SelfParam | TRef | overloading.rs:2:5:11:5 | Self [trait FirstTrait] | | overloading.rs:4:34:6:9 | { ... } | | {EXTERNAL LOCATION} | bool | @@ -5092,6 +5346,32 @@ inferCertainType | regressions.rs:127:9:130:9 | { ... } | | {EXTERNAL LOCATION} | () | | regressions.rs:128:24:128:27 | self | | regressions.rs:121:5:121:19 | S | | regressions.rs:128:24:128:27 | self | T | regressions.rs:123:10:123:10 | T | +| regressions.rs:139:17:139:17 | _ | | {EXTERNAL LOCATION} | & | +| regressions.rs:139:17:139:17 | _ | TRef | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:139:33:141:9 | { ... } | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:139:33:141:9 | { ... } | T2 | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:145:17:145:17 | t | | regressions.rs:144:10:144:10 | T | +| regressions.rs:145:31:147:9 | { ... } | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:145:31:147:9 | { ... } | T2 | regressions.rs:144:10:144:10 | T | +| regressions.rs:146:16:146:16 | t | | regressions.rs:144:10:144:10 | T | +| regressions.rs:150:24:153:5 | { ... } | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:150:24:153:5 | { ... } | T2 | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:164:16:164:19 | SelfParam | | regressions.rs:158:5:158:19 | S | +| regressions.rs:164:16:164:19 | SelfParam | T | regressions.rs:160:10:160:10 | T | +| regressions.rs:164:22:164:25 | _rhs | | regressions.rs:158:5:158:19 | S | +| regressions.rs:164:22:164:25 | _rhs | T | regressions.rs:160:10:160:10 | T | +| regressions.rs:164:50:166:9 | { ... } | | regressions.rs:158:5:158:19 | S | +| regressions.rs:164:50:166:9 | { ... } | T | regressions.rs:160:10:160:10 | T | +| regressions.rs:165:13:165:16 | self | | regressions.rs:158:5:158:19 | S | +| regressions.rs:165:13:165:16 | self | T | regressions.rs:160:10:160:10 | T | +| regressions.rs:173:16:173:19 | SelfParam | | regressions.rs:158:5:158:19 | S | +| regressions.rs:173:16:173:19 | SelfParam | T | regressions.rs:169:10:169:10 | T | +| regressions.rs:173:22:173:25 | _rhs | | regressions.rs:169:10:169:10 | T | +| regressions.rs:173:47:175:9 | { ... } | | regressions.rs:158:5:158:19 | S | +| regressions.rs:173:47:175:9 | { ... } | T | regressions.rs:169:10:169:10 | T | +| regressions.rs:174:13:174:16 | self | | regressions.rs:158:5:158:19 | S | +| regressions.rs:174:13:174:16 | self | T | regressions.rs:169:10:169:10 | T | +| regressions.rs:178:14:180:5 | { ... } | | {EXTERNAL LOCATION} | () | inferType | associated_types.rs:5:15:5:18 | SelfParam | | associated_types.rs:1:1:2:21 | Wrapper | | associated_types.rs:5:15:5:18 | SelfParam | A | associated_types.rs:4:6:4:6 | A | @@ -6051,6 +6331,8 @@ inferType | closure.rs:10:18:10:24 | add_one | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:10:18:10:24 | add_one | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:10:18:10:27 | add_one(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:10:25:10:27 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:10:25:10:27 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:10:26:10:26 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:13:13:13:13 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:13:17:13:34 | ...::default(...) | | {EXTERNAL LOCATION} | i64 | @@ -6070,6 +6352,8 @@ inferType | closure.rs:15:18:15:25 | add_zero | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:15:18:15:25 | add_zero | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:15:18:15:28 | add_zero(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:15:26:15:28 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:15:26:15:28 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:15:27:15:27 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:17:13:17:21 | _get_bool | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:17:13:17:21 | _get_bool | dyn(Args) | {EXTERNAL LOCATION} | () | @@ -6097,6 +6381,8 @@ inferType | closure.rs:25:18:25:19 | id | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:25:18:25:19 | id | dyn(Output) | {EXTERNAL LOCATION} | bool | | closure.rs:25:18:25:25 | id(...) | | {EXTERNAL LOCATION} | bool | +| closure.rs:25:20:25:25 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:25:20:25:25 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:25:21:25:24 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:28:13:28:15 | id2 | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:28:13:28:15 | id2 | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | @@ -6116,18 +6402,24 @@ inferType | closure.rs:30:25:30:27 | id2 | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | | closure.rs:30:25:30:27 | id2 | dyn(Output) | {EXTERNAL LOCATION} | bool | | closure.rs:30:25:30:32 | id2(...) | | {EXTERNAL LOCATION} | bool | +| closure.rs:30:28:30:32 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:30:28:30:32 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:30:29:30:31 | arg | | {EXTERNAL LOCATION} | bool | | closure.rs:35:44:35:44 | f | | closure.rs:35:20:35:41 | F | | closure.rs:35:50:37:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:36:13:36:19 | _return | | {EXTERNAL LOCATION} | i64 | | closure.rs:36:23:36:23 | f | | closure.rs:35:20:35:41 | F | | closure.rs:36:23:36:29 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:36:24:36:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:36:24:36:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:36:25:36:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:39:45:39:45 | f | | closure.rs:39:28:39:42 | F | | closure.rs:39:51:41:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:40:13:40:19 | _return | | {EXTERNAL LOCATION} | () | | closure.rs:40:23:40:23 | f | | closure.rs:39:28:39:42 | F | | closure.rs:40:23:40:29 | f(...) | | {EXTERNAL LOCATION} | () | +| closure.rs:40:24:40:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:40:24:40:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:40:25:40:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:43:46:43:46 | f | | closure.rs:43:22:43:43 | F | | closure.rs:43:52:46:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -6135,74 +6427,77 @@ inferType | closure.rs:44:19:44:36 | ...::default(...) | | {EXTERNAL LOCATION} | bool | | closure.rs:45:9:45:9 | f | | closure.rs:43:22:43:43 | F | | closure.rs:45:9:45:14 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:45:10:45:14 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:45:10:45:14 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:45:11:45:13 | arg | | {EXTERNAL LOCATION} | bool | | closure.rs:48:39:48:39 | f | | closure.rs:48:20:48:36 | F | | closure.rs:48:45:48:45 | a | | closure.rs:48:14:48:14 | A | | closure.rs:48:56:50:5 | { ... } | | closure.rs:48:17:48:17 | B | | closure.rs:49:9:49:9 | f | | closure.rs:48:20:48:36 | F | | closure.rs:49:9:49:12 | f(...) | | closure.rs:48:17:48:17 | B | +| closure.rs:49:10:49:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:49:10:49:12 | ArgList | T0 | closure.rs:48:14:48:14 | A | | closure.rs:49:11:49:11 | a | | closure.rs:48:14:48:14 | A | | closure.rs:52:18:52:18 | f | | closure.rs:52:21:52:43 | impl ... | | closure.rs:52:53:54:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:53:9:53:9 | f | | closure.rs:52:21:52:43 | impl ... | | closure.rs:53:9:53:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:53:10:53:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:53:10:53:12 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | | closure.rs:53:11:53:11 | 2 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:53:11:53:11 | 2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:56:15:68:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:57:13:57:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:57:13:57:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:57:13:57:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:57:13:57:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:57:13:57:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:57:17:63:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:57:17:63:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:57:17:63:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:57:17:63:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:57:17:63:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:57:18:57:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:57:34:63:9 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:57:34:63:9 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:58:13:62:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i32 | -| closure.rs:58:13:62:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i64 | | closure.rs:58:16:58:16 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:58:18:60:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:58:18:60:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:59:17:59:17 | 1 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:59:17:59:17 | 1 | | {EXTERNAL LOCATION} | i64 | | closure.rs:60:20:62:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:60:20:62:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:61:17:61:17 | 0 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:61:17:61:17 | 0 | | {EXTERNAL LOCATION} | i64 | -| closure.rs:64:13:64:14 | _r | | {EXTERNAL LOCATION} | i32 | | closure.rs:64:13:64:14 | _r | | {EXTERNAL LOCATION} | i64 | -| closure.rs:64:18:64:31 | apply(...) | | {EXTERNAL LOCATION} | i32 | | closure.rs:64:18:64:31 | apply(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:64:24:64:24 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:64:24:64:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:64:24:64:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:64:24:64:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:64:24:64:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:64:27:64:30 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:66:13:66:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:66:13:66:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:66:13:66:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:66:17:66:25 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:66:17:66:25 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:66:17:66:25 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:66:18:66:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:66:21:66:21 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:66:25:66:25 | 1 | | {EXTERNAL LOCATION} | i32 | | closure.rs:67:13:67:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:67:19:67:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:67:29:67:29 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:67:29:67:29 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:67:29:67:29 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:72:47:72:47 | f | | closure.rs:72:20:72:40 | F | | closure.rs:72:53:74:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:73:13:73:19 | _return | | {EXTERNAL LOCATION} | i64 | | closure.rs:73:23:73:23 | f | | closure.rs:72:20:72:40 | F | | closure.rs:73:23:73:29 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:73:24:73:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:73:24:73:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:73:25:73:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:76:48:76:48 | f | | closure.rs:76:28:76:41 | F | | closure.rs:76:54:78:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:77:13:77:19 | _return | | {EXTERNAL LOCATION} | () | | closure.rs:77:23:77:23 | f | | closure.rs:76:28:76:41 | F | | closure.rs:77:23:77:29 | f(...) | | {EXTERNAL LOCATION} | () | +| closure.rs:77:24:77:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:77:24:77:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:77:25:77:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:80:49:80:49 | f | | closure.rs:80:22:80:42 | F | | closure.rs:80:55:83:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -6210,74 +6505,77 @@ inferType | closure.rs:81:19:81:36 | ...::default(...) | | {EXTERNAL LOCATION} | bool | | closure.rs:82:9:82:9 | f | | closure.rs:80:22:80:42 | F | | closure.rs:82:9:82:14 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:82:10:82:14 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:82:10:82:14 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:82:11:82:13 | arg | | {EXTERNAL LOCATION} | bool | | closure.rs:85:42:85:42 | f | | closure.rs:85:20:85:35 | F | | closure.rs:85:48:85:48 | a | | closure.rs:85:14:85:14 | A | | closure.rs:85:59:87:5 | { ... } | | closure.rs:85:17:85:17 | B | | closure.rs:86:9:86:9 | f | | closure.rs:85:20:85:35 | F | | closure.rs:86:9:86:12 | f(...) | | closure.rs:85:17:85:17 | B | +| closure.rs:86:10:86:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:86:10:86:12 | ArgList | T0 | closure.rs:85:14:85:14 | A | | closure.rs:86:11:86:11 | a | | closure.rs:85:14:85:14 | A | | closure.rs:89:22:89:22 | f | | closure.rs:89:25:89:46 | impl ... | | closure.rs:89:56:91:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:90:9:90:9 | f | | closure.rs:89:25:89:46 | impl ... | | closure.rs:90:9:90:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:90:10:90:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:90:10:90:12 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | | closure.rs:90:11:90:11 | 2 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:90:11:90:11 | 2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:93:15:105:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:94:13:94:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:94:13:94:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:94:13:94:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:94:13:94:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:94:13:94:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:94:17:100:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:94:17:100:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:94:17:100:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:94:17:100:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:94:17:100:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:94:18:94:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:94:34:100:9 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:94:34:100:9 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:95:13:99:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i32 | -| closure.rs:95:13:99:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i64 | | closure.rs:95:16:95:16 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:95:18:97:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:95:18:97:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:96:17:96:17 | 1 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:96:17:96:17 | 1 | | {EXTERNAL LOCATION} | i64 | | closure.rs:97:20:99:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:97:20:99:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:98:17:98:17 | 0 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:98:17:98:17 | 0 | | {EXTERNAL LOCATION} | i64 | -| closure.rs:101:13:101:14 | _r | | {EXTERNAL LOCATION} | i32 | | closure.rs:101:13:101:14 | _r | | {EXTERNAL LOCATION} | i64 | -| closure.rs:101:18:101:31 | apply(...) | | {EXTERNAL LOCATION} | i32 | | closure.rs:101:18:101:31 | apply(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:101:24:101:24 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:101:24:101:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:101:24:101:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:101:24:101:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:101:24:101:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:101:27:101:30 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:103:13:103:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:103:13:103:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:103:13:103:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:103:17:103:25 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:103:17:103:25 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:103:17:103:25 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:103:18:103:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:103:21:103:21 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:103:25:103:25 | 1 | | {EXTERNAL LOCATION} | i32 | | closure.rs:104:13:104:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:104:19:104:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:104:29:104:29 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:104:29:104:29 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:104:29:104:29 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:109:40:109:40 | f | | closure.rs:109:20:109:37 | F | | closure.rs:109:46:111:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:110:13:110:19 | _return | | {EXTERNAL LOCATION} | i64 | | closure.rs:110:23:110:23 | f | | closure.rs:109:20:109:37 | F | | closure.rs:110:23:110:29 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:110:24:110:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:110:24:110:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:110:25:110:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:113:41:113:41 | f | | closure.rs:113:28:113:38 | F | | closure.rs:113:47:115:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:114:13:114:19 | _return | | {EXTERNAL LOCATION} | () | | closure.rs:114:23:114:23 | f | | closure.rs:113:28:113:38 | F | | closure.rs:114:23:114:29 | f(...) | | {EXTERNAL LOCATION} | () | +| closure.rs:114:24:114:29 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:114:24:114:29 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:114:25:114:28 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:117:42:117:42 | f | | closure.rs:117:22:117:39 | F | | closure.rs:117:48:120:5 | { ... } | | {EXTERNAL LOCATION} | () | @@ -6285,63 +6583,62 @@ inferType | closure.rs:118:19:118:36 | ...::default(...) | | {EXTERNAL LOCATION} | bool | | closure.rs:119:9:119:9 | f | | closure.rs:117:22:117:39 | F | | closure.rs:119:9:119:14 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:119:10:119:14 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:119:10:119:14 | ArgList | T0 | {EXTERNAL LOCATION} | bool | | closure.rs:119:11:119:13 | arg | | {EXTERNAL LOCATION} | bool | | closure.rs:122:35:122:35 | f | | closure.rs:122:20:122:32 | F | | closure.rs:122:41:122:41 | a | | closure.rs:122:14:122:14 | A | | closure.rs:122:52:124:5 | { ... } | | closure.rs:122:17:122:17 | B | | closure.rs:123:9:123:9 | f | | closure.rs:122:20:122:32 | F | | closure.rs:123:9:123:12 | f(...) | | closure.rs:122:17:122:17 | B | +| closure.rs:123:10:123:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:123:10:123:12 | ArgList | T0 | closure.rs:122:14:122:14 | A | | closure.rs:123:11:123:11 | a | | closure.rs:122:14:122:14 | A | | closure.rs:126:18:126:18 | f | | closure.rs:126:21:126:39 | impl ... | | closure.rs:126:49:128:5 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:127:9:127:9 | f | | closure.rs:126:21:126:39 | impl ... | | closure.rs:127:9:127:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:127:10:127:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:127:10:127:12 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | | closure.rs:127:11:127:11 | 2 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:127:11:127:11 | 2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:130:15:142:5 | { ... } | | {EXTERNAL LOCATION} | () | | closure.rs:131:13:131:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:131:13:131:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:131:13:131:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:131:13:131:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:131:13:131:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:131:17:137:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:131:17:137:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:131:17:137:9 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:131:17:137:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:131:17:137:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:131:18:131:18 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:131:34:137:9 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:131:34:137:9 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:132:13:136:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i32 | -| closure.rs:132:13:136:13 | if x {...} else {...} | | {EXTERNAL LOCATION} | i64 | | closure.rs:132:16:132:16 | x | | {EXTERNAL LOCATION} | bool | | closure.rs:132:18:134:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:132:18:134:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:133:17:133:17 | 1 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:133:17:133:17 | 1 | | {EXTERNAL LOCATION} | i64 | | closure.rs:134:20:136:13 | { ... } | | {EXTERNAL LOCATION} | i32 | -| closure.rs:134:20:136:13 | { ... } | | {EXTERNAL LOCATION} | i64 | | closure.rs:135:17:135:17 | 0 | | {EXTERNAL LOCATION} | i32 | -| closure.rs:135:17:135:17 | 0 | | {EXTERNAL LOCATION} | i64 | -| closure.rs:138:13:138:14 | _r | | {EXTERNAL LOCATION} | i32 | | closure.rs:138:13:138:14 | _r | | {EXTERNAL LOCATION} | i64 | -| closure.rs:138:18:138:31 | apply(...) | | {EXTERNAL LOCATION} | i32 | | closure.rs:138:18:138:31 | apply(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:138:24:138:24 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:138:24:138:24 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | | closure.rs:138:24:138:24 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | bool | -| closure.rs:138:24:138:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i32 | | closure.rs:138:24:138:24 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | | closure.rs:138:27:138:30 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:140:13:140:13 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:140:13:140:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:140:13:140:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:140:17:140:25 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:140:17:140:25 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:140:17:140:25 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:140:18:140:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:140:21:140:21 | x | | {EXTERNAL LOCATION} | i64 | | closure.rs:140:25:140:25 | 1 | | {EXTERNAL LOCATION} | i32 | | closure.rs:141:13:141:15 | _r2 | | {EXTERNAL LOCATION} | i64 | | closure.rs:141:19:141:30 | apply_two(...) | | {EXTERNAL LOCATION} | i64 | | closure.rs:141:29:141:29 | f | | {EXTERNAL LOCATION} | dyn Fn | | closure.rs:141:29:141:29 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:141:29:141:29 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | | closure.rs:146:54:146:54 | f | | {EXTERNAL LOCATION} | Box | | closure.rs:146:54:146:54 | f | A | {EXTERNAL LOCATION} | Global | | closure.rs:146:54:146:54 | f | T | closure.rs:146:26:146:51 | F | @@ -6351,7 +6648,8 @@ inferType | closure.rs:147:9:147:9 | f | A | {EXTERNAL LOCATION} | Global | | closure.rs:147:9:147:9 | f | T | closure.rs:146:26:146:51 | F | | closure.rs:147:9:147:14 | f(...) | | closure.rs:146:23:146:23 | B | -| closure.rs:147:9:147:14 | f(...) | | {EXTERNAL LOCATION} | F::Output[FnOnce] | +| closure.rs:147:10:147:14 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:147:10:147:14 | ArgList | T0 | closure.rs:146:20:146:20 | A | | closure.rs:147:11:147:13 | arg | | closure.rs:146:20:146:20 | A | | closure.rs:150:30:150:30 | f | | {EXTERNAL LOCATION} | Box | | closure.rs:150:30:150:30 | f | A | {EXTERNAL LOCATION} | Global | @@ -6385,6 +6683,287 @@ inferType | closure.rs:152:41:152:41 | _ | | {EXTERNAL LOCATION} | i64 | | closure.rs:152:49:152:52 | true | | {EXTERNAL LOCATION} | bool | | closure.rs:152:56:152:56 | 3 | | {EXTERNAL LOCATION} | i32 | +| closure.rs:157:34:157:34 | f | | closure.rs:157:15:157:31 | F | +| closure.rs:157:40:157:40 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:157:55:159:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:158:9:158:9 | f | | closure.rs:157:15:157:31 | F | +| closure.rs:158:9:158:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:158:10:158:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:158:10:158:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:158:11:158:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:161:15:161:15 | f | | closure.rs:161:18:161:36 | impl ... | +| closure.rs:161:39:161:39 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:161:54:163:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:162:9:162:9 | f | | closure.rs:161:18:161:36 | impl ... | +| closure.rs:162:9:162:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:162:10:162:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:162:10:162:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:162:11:162:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:15:165:15 | f | | {EXTERNAL LOCATION} | & | +| closure.rs:165:15:165:15 | f | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:165:15:165:15 | f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:165:15:165:15 | f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:15:165:15 | f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:39:165:39 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:165:54:167:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:9:166:9 | f | | {EXTERNAL LOCATION} | & | +| closure.rs:166:9:166:9 | f | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:166:9:166:9 | f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:166:9:166:9 | f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:9:166:9 | f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:9:166:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:10:166:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:166:10:166:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:166:11:166:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:169:41:169:41 | f | | closure.rs:169:15:169:34 | F | +| closure.rs:169:47:169:47 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:169:62:171:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:170:9:170:9 | f | | closure.rs:169:15:169:34 | F | +| closure.rs:170:9:170:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:170:10:170:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:170:10:170:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:170:11:170:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:15:173:15 | f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:173:15:173:15 | f | TRefMut | {EXTERNAL LOCATION} | dyn FnMut | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:15:173:15 | f | TRefMut.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:46:173:46 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:173:61:175:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:9:174:9 | f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:174:9:174:9 | f | TRefMut | {EXTERNAL LOCATION} | dyn FnMut | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:9:174:9 | f | TRefMut.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:9:174:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:10:174:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:174:10:174:12 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:174:11:174:11 | a | | {EXTERNAL LOCATION} | i64 | +| closure.rs:177:18:177:18 | f | | closure.rs:177:21:177:37 | impl ... | +| closure.rs:177:40:177:40 | a | | closure.rs:177:15:177:15 | T | +| closure.rs:177:53:179:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:178:9:178:9 | f | | closure.rs:177:21:177:37 | impl ... | +| closure.rs:178:9:178:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:178:10:178:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:178:10:178:12 | ArgList | T0 | closure.rs:177:15:177:15 | T | +| closure.rs:178:11:178:11 | a | | closure.rs:177:15:177:15 | T | +| closure.rs:181:42:181:42 | f | | closure.rs:181:18:181:35 | F | +| closure.rs:181:48:181:48 | a | | closure.rs:181:15:181:15 | T | +| closure.rs:181:61:183:5 | { ... } | | {EXTERNAL LOCATION} | i64 | +| closure.rs:182:9:182:9 | f | | closure.rs:181:18:181:35 | F | +| closure.rs:182:9:182:12 | f(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:182:10:182:12 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:182:10:182:12 | ArgList | T0 | closure.rs:181:15:181:15 | T | +| closure.rs:182:11:182:11 | a | | closure.rs:181:15:181:15 | T | +| closure.rs:185:15:206:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:186:13:186:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:186:13:186:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:186:13:186:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:186:13:186:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:186:17:186:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:186:17:186:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:186:17:186:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:186:17:186:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:186:18:186:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:186:21:186:21 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:13:187:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:18:187:32 | apply1(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:25:187:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:187:25:187:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:187:25:187:25 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:25:187:25 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:187:28:187:31 | 1i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:13:189:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:189:13:189:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:189:13:189:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:13:189:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:17:189:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:189:17:189:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:189:17:189:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:17:189:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:18:189:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:189:21:189:21 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:13:190:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:18:190:32 | apply2(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:25:190:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:190:25:190:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:190:25:190:25 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:25:190:25 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:190:28:190:31 | 2i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:13:192:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:192:13:192:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:192:13:192:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:13:192:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:17:192:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:192:17:192:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:192:17:192:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:17:192:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:18:192:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:192:21:192:21 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:13:193:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:18:193:33 | apply3(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:25:193:26 | &f | | {EXTERNAL LOCATION} | & | +| closure.rs:193:25:193:26 | &f | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:193:25:193:26 | &f | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:193:25:193:26 | &f | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:25:193:26 | &f | TRef.dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:26:193:26 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:193:26:193:26 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:193:26:193:26 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:26:193:26 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:193:29:193:32 | 3i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:13:195:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:195:13:195:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:195:13:195:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:13:195:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:17:195:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:195:17:195:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:195:17:195:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:17:195:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:18:195:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:195:21:195:21 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:13:196:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:18:196:32 | apply4(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:25:196:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:196:25:196:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:196:25:196:25 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:25:196:25 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:196:28:196:31 | 4i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:198:17:198:17 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:198:17:198:17 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:198:21:198:25 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:198:21:198:25 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:199:13:199:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:199:18:199:37 | apply5(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:199:25:199:30 | &mut f | | {EXTERNAL LOCATION} | &mut | +| closure.rs:199:25:199:30 | &mut f | TRefMut | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:199:25:199:30 | &mut f | TRefMut.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:199:30:199:30 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:199:30:199:30 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:199:33:199:36 | 5i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:13:201:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:201:13:201:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:201:13:201:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:13:201:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:17:201:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:201:17:201:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:201:17:201:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:17:201:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:18:201:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:201:21:201:21 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:13:202:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:18:202:32 | apply6(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:25:202:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:202:25:202:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:202:25:202:25 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:25:202:25 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:202:28:202:31 | 6i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:13:204:13 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:204:13:204:13 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:204:13:204:13 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:13:204:13 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:17:204:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:204:17:204:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:204:17:204:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:17:204:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:18:204:18 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:204:21:204:21 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:13:205:14 | _r | | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:18:205:32 | apply7(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:25:205:25 | f | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:205:25:205:25 | f | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:205:25:205:25 | f | dyn(Args).T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:25:205:25 | f | dyn(Output) | {EXTERNAL LOCATION} | i64 | +| closure.rs:205:28:205:31 | 7i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:217:18:217:22 | SelfParam | | {EXTERNAL LOCATION} | & | +| closure.rs:217:18:217:22 | SelfParam | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:217:18:217:22 | SelfParam | TRef.T | closure.rs:214:10:214:10 | T | +| closure.rs:217:42:219:9 | { ... } | | {EXTERNAL LOCATION} | & | +| closure.rs:217:42:219:9 | { ... } | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Args).T0 | closure.rs:214:10:214:10 | T | +| closure.rs:217:42:219:9 | { ... } | TRef.dyn(Output) | {EXTERNAL LOCATION} | bool | +| closure.rs:218:13:218:22 | &... | | {EXTERNAL LOCATION} | & | +| closure.rs:218:13:218:22 | &... | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:218:13:218:22 | &... | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:218:13:218:22 | &... | TRef.dyn(Args).T0 | closure.rs:214:10:214:10 | T | +| closure.rs:218:13:218:22 | &... | TRef.dyn(Output) | {EXTERNAL LOCATION} | bool | +| closure.rs:218:14:218:22 | \|...\| false | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:218:14:218:22 | \|...\| false | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:218:14:218:22 | \|...\| false | dyn(Args).T0 | closure.rs:214:10:214:10 | T | +| closure.rs:218:14:218:22 | \|...\| false | dyn(Output) | {EXTERNAL LOCATION} | bool | +| closure.rs:218:15:218:15 | _ | | closure.rs:214:10:214:10 | T | +| closure.rs:218:18:218:22 | false | | {EXTERNAL LOCATION} | bool | +| closure.rs:222:19:240:5 | { ... } | | {EXTERNAL LOCATION} | () | +| closure.rs:223:13:223:13 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:223:17:223:20 | 0i64 | | {EXTERNAL LOCATION} | i64 | +| closure.rs:224:13:224:13 | v | | {EXTERNAL LOCATION} | i64 | +| closure.rs:224:17:224:34 | ...::default(...) | | {EXTERNAL LOCATION} | i64 | +| closure.rs:225:13:225:13 | s | | closure.rs:212:5:212:19 | S | +| closure.rs:225:13:225:13 | s | T | {EXTERNAL LOCATION} | i64 | +| closure.rs:225:17:225:20 | S(...) | | closure.rs:212:5:212:19 | S | +| closure.rs:225:17:225:20 | S(...) | T | {EXTERNAL LOCATION} | i64 | +| closure.rs:225:19:225:19 | v | | {EXTERNAL LOCATION} | i64 | +| closure.rs:226:13:226:16 | _ret | | {EXTERNAL LOCATION} | bool | +| closure.rs:226:20:226:20 | s | | closure.rs:212:5:212:19 | S | +| closure.rs:226:20:226:20 | s | T | {EXTERNAL LOCATION} | i64 | +| closure.rs:226:20:226:23 | s(...) | | {EXTERNAL LOCATION} | bool | +| closure.rs:226:21:226:23 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:226:21:226:23 | ArgList | T0 | {EXTERNAL LOCATION} | i64 | +| closure.rs:226:22:226:22 | x | | {EXTERNAL LOCATION} | i64 | +| closure.rs:228:13:228:13 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:228:17:228:20 | 0i32 | | {EXTERNAL LOCATION} | i32 | +| closure.rs:229:13:229:13 | v | | {EXTERNAL LOCATION} | i32 | +| closure.rs:229:17:229:34 | ...::default(...) | | {EXTERNAL LOCATION} | i32 | +| closure.rs:230:13:230:13 | s | | closure.rs:212:5:212:19 | S | +| closure.rs:230:13:230:13 | s | T | {EXTERNAL LOCATION} | i32 | +| closure.rs:230:17:230:20 | S(...) | | closure.rs:212:5:212:19 | S | +| closure.rs:230:17:230:20 | S(...) | T | {EXTERNAL LOCATION} | i32 | +| closure.rs:230:19:230:19 | v | | {EXTERNAL LOCATION} | i32 | +| closure.rs:231:13:231:17 | s_ref | | {EXTERNAL LOCATION} | & | +| closure.rs:231:13:231:17 | s_ref | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:231:13:231:17 | s_ref | TRef.T | {EXTERNAL LOCATION} | i32 | +| closure.rs:231:21:231:22 | &s | | {EXTERNAL LOCATION} | & | +| closure.rs:231:21:231:22 | &s | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:231:21:231:22 | &s | TRef.T | {EXTERNAL LOCATION} | i32 | +| closure.rs:231:22:231:22 | s | | closure.rs:212:5:212:19 | S | +| closure.rs:231:22:231:22 | s | T | {EXTERNAL LOCATION} | i32 | +| closure.rs:232:13:232:16 | _ret | | {EXTERNAL LOCATION} | bool | +| closure.rs:232:20:232:24 | s_ref | | {EXTERNAL LOCATION} | & | +| closure.rs:232:20:232:24 | s_ref | TRef | closure.rs:212:5:212:19 | S | +| closure.rs:232:20:232:24 | s_ref | TRef.T | {EXTERNAL LOCATION} | i32 | +| closure.rs:232:20:232:27 | s_ref(...) | | {EXTERNAL LOCATION} | bool | +| closure.rs:232:25:232:27 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:232:25:232:27 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:232:26:232:26 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:13:238:13 | c | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:238:13:238:13 | c | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:238:13:238:13 | c | dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:13:238:13 | c | dyn(Output) | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:17:238:21 | \|...\| x | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:238:17:238:21 | \|...\| x | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:238:17:238:21 | \|...\| x | dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:17:238:21 | \|...\| x | dyn(Output) | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:18:238:18 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:238:21:238:21 | x | | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:9:239:12 | (...) | | {EXTERNAL LOCATION} | & | +| closure.rs:239:9:239:12 | (...) | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:239:9:239:12 | (...) | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:9:239:12 | (...) | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:9:239:12 | (...) | TRef.dyn(Output) | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:9:239:15 | ...(...) | | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:10:239:11 | &c | | {EXTERNAL LOCATION} | & | +| closure.rs:239:10:239:11 | &c | TRef | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:239:10:239:11 | &c | TRef.dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:10:239:11 | &c | TRef.dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:10:239:11 | &c | TRef.dyn(Output) | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:11:239:11 | c | | {EXTERNAL LOCATION} | dyn Fn | +| closure.rs:239:11:239:11 | c | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:11:239:11 | c | dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:11:239:11 | c | dyn(Output) | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:13:239:15 | ArgList | | {EXTERNAL LOCATION} | (T_1) | +| closure.rs:239:13:239:15 | ArgList | T0 | {EXTERNAL LOCATION} | i32 | +| closure.rs:239:14:239:14 | x | | {EXTERNAL LOCATION} | i32 | | dereference.rs:13:14:13:18 | SelfParam | | {EXTERNAL LOCATION} | & | | dereference.rs:13:14:13:18 | SelfParam | TRef | dereference.rs:5:1:7:1 | MyIntPointer | | dereference.rs:13:29:15:5 | { ... } | | {EXTERNAL LOCATION} | & | @@ -9458,14 +10037,21 @@ inferType | main.rs:1341:28:1341:41 | ...::Ok(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1341:28:1341:41 | ...::Ok(...) | T | main.rs:1317:5:1318:14 | S1 | | main.rs:1341:39:1341:40 | S1 | | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:13:1343:13 | y | | main.rs:1317:5:1318:14 | S1 | | main.rs:1343:17:1343:17 | x | | {EXTERNAL LOCATION} | Result | | main.rs:1343:17:1343:17 | x | T | {EXTERNAL LOCATION} | Result | | main.rs:1343:17:1343:17 | x | T.T | main.rs:1317:5:1318:14 | S1 | | main.rs:1343:17:1343:18 | TryExpr | | {EXTERNAL LOCATION} | Result | | main.rs:1343:17:1343:18 | TryExpr | T | main.rs:1317:5:1318:14 | S1 | | main.rs:1343:17:1343:29 | ... .map(...) | | {EXTERNAL LOCATION} | Result | +| main.rs:1343:17:1343:29 | ... .map(...) | T | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:17:1343:30 | TryExpr | | main.rs:1317:5:1318:14 | S1 | | main.rs:1343:24:1343:28 | \|...\| s | | {EXTERNAL LOCATION} | dyn Fn | | main.rs:1343:24:1343:28 | \|...\| s | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| main.rs:1343:24:1343:28 | \|...\| s | dyn(Args).T0 | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:24:1343:28 | \|...\| s | dyn(Output) | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:25:1343:25 | s | | main.rs:1317:5:1318:14 | S1 | +| main.rs:1343:28:1343:28 | s | | main.rs:1317:5:1318:14 | S1 | | main.rs:1344:9:1344:22 | ...::Ok(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1344:9:1344:22 | ...::Ok(...) | E | main.rs:1320:5:1321:14 | S2 | | main.rs:1344:9:1344:22 | ...::Ok(...) | T | main.rs:1317:5:1318:14 | S1 | @@ -9481,26 +10067,36 @@ inferType | main.rs:1350:21:1350:25 | input | E | main.rs:1317:5:1318:14 | S1 | | main.rs:1350:21:1350:25 | input | T | main.rs:1349:20:1349:27 | T | | main.rs:1350:21:1350:26 | TryExpr | | main.rs:1349:20:1349:27 | T | +| main.rs:1351:13:1351:18 | mapped | | main.rs:1349:20:1349:27 | T | | main.rs:1351:22:1351:38 | ...::Ok(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1351:22:1351:38 | ...::Ok(...) | E | main.rs:1317:5:1318:14 | S1 | | main.rs:1351:22:1351:38 | ...::Ok(...) | T | main.rs:1349:20:1349:27 | T | | main.rs:1351:22:1354:10 | ... .and_then(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1351:22:1354:10 | ... .and_then(...) | E | main.rs:1317:5:1318:14 | S1 | +| main.rs:1351:22:1354:10 | ... .and_then(...) | T | main.rs:1349:20:1349:27 | T | +| main.rs:1351:22:1354:11 | TryExpr | | main.rs:1349:20:1349:27 | T | | main.rs:1351:33:1351:37 | value | | main.rs:1349:20:1349:27 | T | | main.rs:1351:49:1354:9 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | main.rs:1351:49:1354:9 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| main.rs:1351:49:1354:9 | \|...\| ... | dyn(Args).T0 | main.rs:1349:20:1349:27 | T | | main.rs:1351:49:1354:9 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | Result | | main.rs:1351:49:1354:9 | \|...\| ... | dyn(Output).E | main.rs:1317:5:1318:14 | S1 | +| main.rs:1351:49:1354:9 | \|...\| ... | dyn(Output).T | main.rs:1349:20:1349:27 | T | +| main.rs:1351:50:1351:50 | v | | main.rs:1349:20:1349:27 | T | | main.rs:1351:53:1354:9 | { ... } | | {EXTERNAL LOCATION} | Result | | main.rs:1351:53:1354:9 | { ... } | E | main.rs:1317:5:1318:14 | S1 | +| main.rs:1351:53:1354:9 | { ... } | T | main.rs:1349:20:1349:27 | T | | main.rs:1352:13:1352:31 | MacroExpr | | {EXTERNAL LOCATION} | () | | main.rs:1352:22:1352:27 | "{:?}\\n" | | {EXTERNAL LOCATION} | & | | main.rs:1352:22:1352:27 | "{:?}\\n" | TRef | {EXTERNAL LOCATION} | str | | main.rs:1352:22:1352:30 | ...::_print(...) | | {EXTERNAL LOCATION} | () | | main.rs:1352:22:1352:30 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:1352:22:1352:30 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:1352:30:1352:30 | v | | main.rs:1349:20:1349:27 | T | | main.rs:1353:13:1353:34 | ...::Ok::<...>(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1353:13:1353:34 | ...::Ok::<...>(...) | E | main.rs:1317:5:1318:14 | S1 | +| main.rs:1353:13:1353:34 | ...::Ok::<...>(...) | T | main.rs:1349:20:1349:27 | T | +| main.rs:1353:33:1353:33 | v | | main.rs:1349:20:1349:27 | T | | main.rs:1355:9:1355:23 | ...::Err(...) | | {EXTERNAL LOCATION} | Result | | main.rs:1355:9:1355:23 | ...::Err(...) | E | main.rs:1317:5:1318:14 | S1 | | main.rs:1355:9:1355:23 | ...::Err(...) | T | main.rs:1349:20:1349:27 | T | @@ -11071,14 +11667,21 @@ inferType | main.rs:2261:25:2261:25 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:2261:28:2261:29 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2262:9:2262:44 | for ... in ... { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2262:13:2262:13 | i | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:18:2262:26 | [...] | | {EXTERNAL LOCATION} | [;] | | main.rs:2262:18:2262:26 | [...] | TArray | {EXTERNAL LOCATION} | i32 | | main.rs:2262:18:2262:41 | ... .map(...) | | {EXTERNAL LOCATION} | [;] | +| main.rs:2262:18:2262:41 | ... .map(...) | TArray | {EXTERNAL LOCATION} | i32 | | main.rs:2262:19:2262:19 | 1 | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:22:2262:22 | 2 | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:25:2262:25 | 3 | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:32:2262:40 | \|...\| ... | | {EXTERNAL LOCATION} | dyn Fn | | main.rs:2262:32:2262:40 | \|...\| ... | dyn(Args) | {EXTERNAL LOCATION} | (T_1) | +| main.rs:2262:32:2262:40 | \|...\| ... | dyn(Args).T0 | {EXTERNAL LOCATION} | i32 | +| main.rs:2262:32:2262:40 | \|...\| ... | dyn(Output) | {EXTERNAL LOCATION} | i32 | +| main.rs:2262:33:2262:33 | x | | {EXTERNAL LOCATION} | i32 | +| main.rs:2262:36:2262:36 | x | | {EXTERNAL LOCATION} | i32 | +| main.rs:2262:36:2262:40 | ... + ... | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:40:2262:40 | 1 | | {EXTERNAL LOCATION} | i32 | | main.rs:2262:43:2262:44 | { ... } | | {EXTERNAL LOCATION} | () | | main.rs:2263:9:2263:41 | for ... in ... { ... } | | {EXTERNAL LOCATION} | () | @@ -12316,48 +12919,81 @@ inferType | main.rs:2751:17:2751:17 | x | | {EXTERNAL LOCATION} | i32 | | main.rs:2751:17:2751:24 | x.max(...) | | {EXTERNAL LOCATION} | i32 | | main.rs:2751:23:2751:23 | y | | {EXTERNAL LOCATION} | usize | -| main.rs:2762:11:2797:1 | { ... } | | {EXTERNAL LOCATION} | () | -| main.rs:2763:5:2763:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2764:5:2764:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:5:2765:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:20:2765:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2765:41:2765:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | -| main.rs:2766:5:2766:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2767:5:2767:41 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2768:5:2768:45 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2769:5:2769:30 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2770:5:2770:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2771:5:2771:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2772:5:2772:32 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2773:5:2773:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2774:5:2774:36 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2775:5:2775:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2776:5:2776:29 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2777:5:2777:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2778:5:2778:24 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2779:5:2779:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2780:5:2780:18 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2781:5:2781:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future | -| main.rs:2781:5:2781:15 | ...::f(...) | dyn(Output) | {EXTERNAL LOCATION} | () | -| main.rs:2782:5:2782:19 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2783:5:2783:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2784:5:2784:14 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2785:5:2785:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2786:5:2786:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2787:5:2787:43 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2788:5:2788:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2789:5:2789:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2790:5:2790:28 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2791:5:2791:23 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2792:5:2792:41 | ...::test_all_patterns(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2793:5:2793:49 | ...::box_patterns(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2794:5:2794:20 | ...::test(...) | | {EXTERNAL LOCATION} | () | -| main.rs:2795:5:2795:20 | ...::f(...) | | {EXTERNAL LOCATION} | Box | -| main.rs:2795:5:2795:20 | ...::f(...) | A | {EXTERNAL LOCATION} | Global | -| main.rs:2795:5:2795:20 | ...::f(...) | T | main.rs:2547:5:2549:5 | dyn MyTrait | -| main.rs:2795:5:2795:20 | ...::f(...) | T.dyn(T) | {EXTERNAL LOCATION} | i32 | -| main.rs:2795:16:2795:19 | true | | {EXTERNAL LOCATION} | bool | -| main.rs:2796:5:2796:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2766:22:2766:26 | SelfParam | | {EXTERNAL LOCATION} | & | +| main.rs:2766:22:2766:26 | SelfParam | TRef | main.rs:2765:5:2767:5 | Self [trait Container] | +| main.rs:2769:34:2769:34 | c | | {EXTERNAL LOCATION} | & | +| main.rs:2769:34:2769:34 | c | TRef | main.rs:2769:15:2769:31 | T | +| main.rs:2769:49:2771:5 | { ... } | | {EXTERNAL LOCATION} | bool | +| main.rs:2770:9:2770:9 | c | | {EXTERNAL LOCATION} | & | +| main.rs:2770:9:2770:9 | c | TRef | main.rs:2769:15:2769:31 | T | +| main.rs:2770:9:2770:21 | c.get_input() | | {EXTERNAL LOCATION} | i64 | +| main.rs:2770:9:2770:27 | ... == ... | | {EXTERNAL LOCATION} | bool | +| main.rs:2770:26:2770:27 | 42 | | {EXTERNAL LOCATION} | i32 | +| main.rs:2774:22:2774:26 | SelfParam | | {EXTERNAL LOCATION} | & | +| main.rs:2774:22:2774:26 | SelfParam | TRef | main.rs:2763:5:2763:21 | Gen | +| main.rs:2774:22:2774:26 | SelfParam | TRef.T | main.rs:2773:10:2773:17 | GT | +| main.rs:2774:35:2776:9 | { ... } | | main.rs:2773:10:2773:17 | GT | +| main.rs:2775:13:2775:16 | self | | {EXTERNAL LOCATION} | & | +| main.rs:2775:13:2775:16 | self | TRef | main.rs:2763:5:2763:21 | Gen | +| main.rs:2775:13:2775:16 | self | TRef.T | main.rs:2773:10:2773:17 | GT | +| main.rs:2775:13:2775:18 | self.0 | | main.rs:2773:10:2773:17 | GT | +| main.rs:2779:15:2783:5 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2780:13:2780:13 | v | | {EXTERNAL LOCATION} | i64 | +| main.rs:2780:17:2780:34 | ...::default(...) | | {EXTERNAL LOCATION} | i64 | +| main.rs:2781:13:2781:13 | g | | main.rs:2763:5:2763:21 | Gen | +| main.rs:2781:13:2781:13 | g | T | {EXTERNAL LOCATION} | i64 | +| main.rs:2781:17:2781:22 | Gen(...) | | main.rs:2763:5:2763:21 | Gen | +| main.rs:2781:17:2781:22 | Gen(...) | T | {EXTERNAL LOCATION} | i64 | +| main.rs:2781:21:2781:21 | v | | {EXTERNAL LOCATION} | i64 | +| main.rs:2782:13:2782:13 | _ | | {EXTERNAL LOCATION} | bool | +| main.rs:2782:17:2782:26 | my_get(...) | | {EXTERNAL LOCATION} | bool | +| main.rs:2782:24:2782:25 | &g | | {EXTERNAL LOCATION} | & | +| main.rs:2782:24:2782:25 | &g | TRef | main.rs:2763:5:2763:21 | Gen | +| main.rs:2782:24:2782:25 | &g | TRef.T | {EXTERNAL LOCATION} | i64 | +| main.rs:2782:25:2782:25 | g | | main.rs:2763:5:2763:21 | Gen | +| main.rs:2782:25:2782:25 | g | T | {EXTERNAL LOCATION} | i64 | +| main.rs:2786:11:2821:1 | { ... } | | {EXTERNAL LOCATION} | () | +| main.rs:2787:5:2787:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2788:5:2788:20 | ...::f(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:5:2789:60 | ...::g(...) | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:20:2789:38 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2789:41:2789:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo | +| main.rs:2790:5:2790:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2791:5:2791:41 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2792:5:2792:45 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2793:5:2793:30 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2794:5:2794:21 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2795:5:2795:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2796:5:2796:32 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2797:5:2797:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2798:5:2798:36 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2799:5:2799:35 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2800:5:2800:29 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2801:5:2801:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2802:5:2802:24 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2803:5:2803:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2804:5:2804:18 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2805:5:2805:15 | ...::f(...) | | {EXTERNAL LOCATION} | dyn Future | +| main.rs:2805:5:2805:15 | ...::f(...) | dyn(Output) | {EXTERNAL LOCATION} | () | +| main.rs:2806:5:2806:19 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2807:5:2807:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2808:5:2808:14 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2809:5:2809:27 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2810:5:2810:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2811:5:2811:43 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2812:5:2812:15 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2813:5:2813:17 | ...::f(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2814:5:2814:28 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2815:5:2815:23 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2816:5:2816:41 | ...::test_all_patterns(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2817:5:2817:49 | ...::box_patterns(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2818:5:2818:20 | ...::test(...) | | {EXTERNAL LOCATION} | () | +| main.rs:2819:5:2819:20 | ...::f(...) | | {EXTERNAL LOCATION} | Box | +| main.rs:2819:5:2819:20 | ...::f(...) | A | {EXTERNAL LOCATION} | Global | +| main.rs:2819:5:2819:20 | ...::f(...) | T | main.rs:2547:5:2549:5 | dyn MyTrait | +| main.rs:2819:5:2819:20 | ...::f(...) | T.dyn(T) | {EXTERNAL LOCATION} | i32 | +| main.rs:2819:16:2819:19 | true | | {EXTERNAL LOCATION} | bool | +| main.rs:2820:5:2820:23 | ...::f(...) | | {EXTERNAL LOCATION} | () | | overloading.rs:4:19:4:23 | SelfParam | | {EXTERNAL LOCATION} | & | | overloading.rs:4:19:4:23 | SelfParam | TRef | overloading.rs:2:5:11:5 | Self [trait FirstTrait] | | overloading.rs:4:34:6:9 | { ... } | | {EXTERNAL LOCATION} | bool | @@ -15158,4 +15794,62 @@ inferType | regressions.rs:128:24:128:27 | self | T | regressions.rs:123:10:123:10 | T | | regressions.rs:129:13:129:13 | s | | regressions.rs:123:10:123:10 | T | | regressions.rs:129:13:129:17 | s.m() | | {EXTERNAL LOCATION} | () | +| regressions.rs:139:17:139:17 | _ | | {EXTERNAL LOCATION} | & | +| regressions.rs:139:17:139:17 | _ | TRef | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:139:33:141:9 | { ... } | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:139:33:141:9 | { ... } | T2 | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:140:13:140:18 | S2(...) | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:140:13:140:18 | S2(...) | T2 | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:140:16:140:17 | S1 | | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:145:17:145:17 | t | | regressions.rs:144:10:144:10 | T | +| regressions.rs:145:31:147:9 | { ... } | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:145:31:147:9 | { ... } | T2 | regressions.rs:144:10:144:10 | T | +| regressions.rs:146:13:146:17 | S2(...) | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:146:13:146:17 | S2(...) | T2 | regressions.rs:144:10:144:10 | T | +| regressions.rs:146:16:146:16 | t | | regressions.rs:144:10:144:10 | T | +| regressions.rs:150:24:153:5 | { ... } | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:150:24:153:5 | { ... } | T2 | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:151:13:151:13 | x | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:151:13:151:13 | x | T2 | {EXTERNAL LOCATION} | & | +| regressions.rs:151:13:151:13 | x | T2 | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:151:13:151:13 | x | T2.TRef | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:151:17:151:18 | S1 | | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:151:17:151:25 | S1.into() | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:151:17:151:25 | S1.into() | T2 | {EXTERNAL LOCATION} | & | +| regressions.rs:151:17:151:25 | S1.into() | T2 | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:151:17:151:25 | S1.into() | T2.TRef | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:152:9:152:9 | x | | regressions.rs:136:5:136:22 | S2 | +| regressions.rs:152:9:152:9 | x | T2 | {EXTERNAL LOCATION} | & | +| regressions.rs:152:9:152:9 | x | T2 | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:152:9:152:9 | x | T2.TRef | regressions.rs:135:5:135:14 | S1 | +| regressions.rs:164:16:164:19 | SelfParam | | regressions.rs:158:5:158:19 | S | +| regressions.rs:164:16:164:19 | SelfParam | T | regressions.rs:160:10:160:10 | T | +| regressions.rs:164:22:164:25 | _rhs | | regressions.rs:158:5:158:19 | S | +| regressions.rs:164:22:164:25 | _rhs | T | regressions.rs:160:10:160:10 | T | +| regressions.rs:164:50:166:9 | { ... } | | regressions.rs:158:5:158:19 | S | +| regressions.rs:164:50:166:9 | { ... } | T | regressions.rs:160:10:160:10 | T | +| regressions.rs:165:13:165:16 | self | | regressions.rs:158:5:158:19 | S | +| regressions.rs:165:13:165:16 | self | T | regressions.rs:160:10:160:10 | T | +| regressions.rs:173:16:173:19 | SelfParam | | regressions.rs:158:5:158:19 | S | +| regressions.rs:173:16:173:19 | SelfParam | T | regressions.rs:169:10:169:10 | T | +| regressions.rs:173:22:173:25 | _rhs | | regressions.rs:169:10:169:10 | T | +| regressions.rs:173:47:175:9 | { ... } | | regressions.rs:158:5:158:19 | S | +| regressions.rs:173:47:175:9 | { ... } | T | regressions.rs:169:10:169:10 | T | +| regressions.rs:174:13:174:16 | self | | regressions.rs:158:5:158:19 | S | +| regressions.rs:174:13:174:16 | self | T | regressions.rs:169:10:169:10 | T | +| regressions.rs:178:14:180:5 | { ... } | | {EXTERNAL LOCATION} | () | +| regressions.rs:179:13:179:13 | x | | regressions.rs:158:5:158:19 | S | +| regressions.rs:179:13:179:13 | x | T | {EXTERNAL LOCATION} | i32 | +| regressions.rs:179:13:179:13 | x | T | regressions.rs:158:5:158:19 | S | +| regressions.rs:179:13:179:13 | x | T.T | {EXTERNAL LOCATION} | i32 | +| regressions.rs:179:17:179:20 | S(...) | | regressions.rs:158:5:158:19 | S | +| regressions.rs:179:17:179:20 | S(...) | T | {EXTERNAL LOCATION} | i32 | +| regressions.rs:179:17:179:27 | ... + ... | | regressions.rs:158:5:158:19 | S | +| regressions.rs:179:17:179:27 | ... + ... | T | {EXTERNAL LOCATION} | i32 | +| regressions.rs:179:17:179:27 | ... + ... | T | regressions.rs:158:5:158:19 | S | +| regressions.rs:179:17:179:27 | ... + ... | T.T | {EXTERNAL LOCATION} | i32 | +| regressions.rs:179:19:179:19 | 0 | | {EXTERNAL LOCATION} | i32 | +| regressions.rs:179:24:179:27 | S(...) | | regressions.rs:158:5:158:19 | S | +| regressions.rs:179:24:179:27 | S(...) | T | {EXTERNAL LOCATION} | i32 | +| regressions.rs:179:26:179:26 | 1 | | {EXTERNAL LOCATION} | i32 | testFailures diff --git a/rust/ql/test/utils-tests/modelgenerator/option.rs b/rust/ql/test/utils-tests/modelgenerator/option.rs index 701073564b1..afe76e2088e 100644 --- a/rust/ql/test/utils-tests/modelgenerator/option.rs +++ b/rust/ql/test/utils-tests/modelgenerator/option.rs @@ -149,6 +149,8 @@ impl MyOption { // summary=::map;Argument[0].ReturnValue;ReturnValue.Field[test::option::MyOption::MySome(0)];value;dfc-generated // summary=::map;Argument[self].Field[test::option::MyOption::MySome(0)];Argument[0].Parameter[0];value;dfc-generated + // The spurious model below happens because `f` incorrectly resolves to the closure passed in from `as_deref` + // SPURIOUS-summary=::map;Argument[self].Field[test::option::MyOption::MySome(0)].Reference;ReturnValue.Field[test::option::MyOption::MySome(0)].Reference;taint;dfc-generated pub fn map(self, f: F) -> MyOption where F: FnOnce(T) -> U, @@ -217,7 +219,7 @@ impl MyOption { } } - // MISSING: `Deref` trait + // summary=::as_deref;Argument[self].Reference.Field[test::option::MyOption::MySome(0)];ReturnValue.Field[test::option::MyOption::MySome(0)].Reference;taint;dfc-generated pub fn as_deref(&self) -> MyOption<&T::Target> where T: Deref, diff --git a/shared/dataflow/codeql/dataflow/DataFlow.qll b/shared/dataflow/codeql/dataflow/DataFlow.qll index 7f9c0194374..cacd52cf839 100644 --- a/shared/dataflow/codeql/dataflow/DataFlow.qll +++ b/shared/dataflow/codeql/dataflow/DataFlow.qll @@ -63,6 +63,35 @@ signature module InputSig { DataFlowType getNodeType(Node node); + /** + * Gets a special type to use for parameter node `p` belonging to callables with a + * source node where a source call context `FlowFeature` is used, if any. + * + * This can be used to prevent lambdas from being resolved, when a concrete call + * context is needed. Example: + * + * ```csharp + * void Foo(Action a) + * { + * var x = Source(); + * a(x); // (1) + * a = s => Sink(s); // (2) + * a(x); // (3) + * } + * + * void Bar() + * { + * Foo(s => Sink(s)); // (4) + * } + * ``` + * + * If a source call context flow feature is used, `a` can be assigned a special + * type that is incompatible with the type of _any_ lambda expression, which will + * prevent the call edge from (1) to (4). Note that the call edge from (3) to (2) + * will still be valid. + */ + default DataFlowType getSourceContextParameterNodeType(Node p) { none() } + predicate nodeIsHidden(Node node); class DataFlowExpr; diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index 506774857d8..ed0412d1cd4 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -1103,6 +1103,16 @@ module MakeImpl Lang> { private module FwdTypeFlowInput implements TypeFlowInput { predicate enableTypeFlow = Param::enableTypeFlow/0; + pragma[nomagic] + predicate isParameterNodeInSourceCallContext(ParamNode p) { + hasSourceCallCtx() and + exists(Node source, DataFlowCallable c | + Config::isSource(pragma[only_bind_into](source), _) and + nodeEnclosingCallable(source, c) and + nodeEnclosingCallable(p, c) + ) + } + predicate relevantCallEdgeIn = PrevStage::relevantCallEdgeIn/2; predicate relevantCallEdgeOut = PrevStage::relevantCallEdgeOut/2; @@ -1410,6 +1420,8 @@ module MakeImpl Lang> { private module RevTypeFlowInput implements TypeFlowInput { predicate enableTypeFlow = Param::enableTypeFlow/0; + predicate isParameterNodeInSourceCallContext(ParamNode p) { none() } + predicate relevantCallEdgeIn(Call call, Callable c) { flowOutOfCallAp(call, c, _, _, _, _, _) } diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll index 51ebb3f8a73..962a58c26f9 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll @@ -1893,6 +1893,9 @@ module MakeImplCommon Lang> { signature module TypeFlowInput { predicate enableTypeFlow(); + /** Holds if `p` is a parameter of a callable with a source node that has a call context. */ + predicate isParameterNodeInSourceCallContext(ParamNode p); + /** Holds if the edge is possibly needed in the direction `call` to `c`. */ predicate relevantCallEdgeIn(Call call, Callable c); @@ -1953,6 +1956,9 @@ module MakeImplCommon Lang> { /** * Holds if a sequence of calls may propagate the value of `arg` to some * argument-to-parameter call edge that strengthens the static type. + * + * This predicate is a reverse flow computation, starting at calls that + * strengthen the type and then following relevant call edges backwards. */ pragma[nomagic] private predicate trackedArgTypeCand(ArgNode arg) { @@ -1987,6 +1993,9 @@ module MakeImplCommon Lang> { * Holds if `p` is part of a value-propagating call path where the * end-points have stronger types than the intermediate parameter and * argument nodes. + * + * This predicate is a forward flow computation, intersecting with the + * reverse flow computation done in `trackedArgTypeCand`. */ private predicate trackedParamType(ParamNode p) { exists(Call call1, Callable c1, ArgNode argOut, Call call2, Callable c2, ArgNode argIn | @@ -2013,6 +2022,8 @@ module MakeImplCommon Lang> { typeStrongerThanFilter(at, pt) ) or + Input::isParameterNodeInSourceCallContext(p) + or exists(ArgNode arg | trackedArgType(arg) and relevantCallEdge(_, _, arg, p) and @@ -2104,8 +2115,12 @@ module MakeImplCommon Lang> { * context. */ private predicate typeFlowParamType(ParamNode p, Type t, boolean cc) { - exists(Callable c | - Input::dataFlowNonCallEntry(c, cc) and + exists(Callable c | Input::dataFlowNonCallEntry(c, cc) | + cc = true and + nodeEnclosingCallable(p, c) and + t = getSourceContextParameterNodeType(p) + or + (cc = false or not exists(getSourceContextParameterNodeType(p))) and trackedParamWithType(p, t, c) ) or diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll index 426576d3ace..b7a45a67b56 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll @@ -86,6 +86,8 @@ module MakeImplStage1 Lang> { bindingset[p, kind] predicate parameterFlowThroughAllowed(ParamNd p, ReturnKindExt kind); + predicate fwdFlow(Nd node); + // begin StageSig class Ap; @@ -634,7 +636,7 @@ module MakeImplStage1 Lang> { ) } - private predicate fwdFlow(NodeEx node) { fwdFlow(node, _) } + predicate fwdFlow(NodeEx node) { fwdFlow(node, _) } pragma[nomagic] private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc) { @@ -1291,6 +1293,8 @@ module MakeImplStage1 Lang> { import Stage1 import Stage1Common + predicate fwdFlow(Nd node) { Stage1::fwdFlow(node) } + predicate revFlow(NodeEx node, Ap ap) { Stage1::revFlow(node) and exists(ap) } predicate toNormalSinkNode = toNormalSinkNodeEx/1; @@ -1395,6 +1399,8 @@ module MakeImplStage1 Lang> { import Stage1Common + predicate fwdFlow(Nd node) { Stage1::fwdFlow(node.getNodeEx()) } + predicate revFlow(Nd node) { Stage1::revFlow(node.getNodeEx()) } predicate revFlow(Nd node, Ap ap) { Stage1::revFlow(node.getNodeEx()) and exists(ap) } diff --git a/shared/mad/codeql/mad/ModelValidation.qll b/shared/mad/codeql/mad/ModelValidation.qll index 042fb4200dd..5eaa78626ab 100644 --- a/shared/mad/codeql/mad/ModelValidation.qll +++ b/shared/mad/codeql/mad/ModelValidation.qll @@ -48,7 +48,7 @@ module KindValidation { // CPP-only currently "remote-sink", // Python-only currently, but may be shared in the future - "prompt-injection" + "bind-socket-all-interfaces", "prompt-injection" ] or this.matches([ diff --git a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll index 0b23b08aad6..888ca65fa98 100644 --- a/shared/typeinference/codeql/typeinference/internal/TypeInference.qll +++ b/shared/typeinference/codeql/typeinference/internal/TypeInference.qll @@ -964,7 +964,7 @@ module Make1 Input1> { /** * Holds if `term` does not satisfy `constraint`. * - * This predicate is an approximation of `not hasConstraintMention(term, constraint)`. + * This predicate is an approximation of `not hasConstraintMention(term, _, _, constraint, _, _)`. */ pragma[nomagic] private predicate hasNotConstraintMention( @@ -1072,7 +1072,7 @@ module Make1 Input1> { } pragma[nomagic] - private predicate satisfiesConstraintTypeMention1( + private predicate satisfiesConstraint0( Term term, Constraint constraint, TypeAbstraction abs, TypeMention sub, TypePath path, Type t ) { @@ -1100,37 +1100,55 @@ module Make1 Input1> { } pragma[inline] - private predicate satisfiesConstraintTypeMentionInline( - Term term, Constraint constraint, TypeAbstraction abs, TypePath path, - TypePath pathToTypeParamInSub + private predicate satisfiesConstraintInline( + Term term, Constraint constraint, TypeAbstraction abs, TypePath pathToTypeParamInConstraint, + TypePath pathToTypeParamInSub, TypeParameter tp ) { - exists(TypeMention sub, TypeParameter tp | - satisfiesConstraintTypeMention1(term, constraint, abs, sub, path, tp) and + exists(TypeMention sub | + satisfiesConstraint0(term, constraint, abs, sub, pathToTypeParamInConstraint, tp) and tp = abs.getATypeParameter() and sub.getTypeAt(pathToTypeParamInSub) = tp ) } + /** + * Holds if `term` satisfies the constraint `constraint` with _some_ type + * parameter at `pathToTypeParamInConstraint`, and the type parameter occurs + * at `pathToTypeParamInSub` in a satisfying condition. + * + * Example: + * + * ```rust + * struct MyThing { ... } + * + * trait MyTrait { ... } + * + * impl MyTrait for MyThing { ... } + * + * fn foo>(x: T) { ... } + * + * let x = MyThing(Default::default()); + * foo(x); + * ``` + * + * At `term` = `foo(x)`, we have `constraint = MyTrait`, and because of the + * `impl` block, `pathToTypeParamInConstraint` = `"B"`, and + * `pathToTypeParamInSub` = `"A"`. + */ pragma[nomagic] - private predicate satisfiesConstraintTypeMention( - Term term, Constraint constraint, TypePath path, TypePath pathToTypeParamInSub - ) { - satisfiesConstraintTypeMentionInline(term, constraint, _, path, pathToTypeParamInSub) - } - - pragma[nomagic] - private predicate satisfiesConstraintTypeMentionThrough( - Term term, Constraint constraint, TypeAbstraction abs, TypePath path, + predicate satisfiesConstraintAtTypeParameter( + Term term, Constraint constraint, TypePath pathToTypeParamInConstraint, TypePath pathToTypeParamInSub ) { - satisfiesConstraintTypeMentionInline(term, constraint, abs, path, pathToTypeParamInSub) + satisfiesConstraintInline(term, constraint, _, pathToTypeParamInConstraint, + pathToTypeParamInSub, _) } pragma[inline] - private predicate satisfiesConstraintTypeNonTypeParamInline( + private predicate satisfiesConstraintNonTypeParamInline( Term term, TypeAbstraction abs, Constraint constraint, TypePath path, Type t ) { - satisfiesConstraintTypeMention1(term, constraint, abs, _, path, t) and + satisfiesConstraint0(term, constraint, abs, _, path, t) and not t = abs.getATypeParameter() } @@ -1142,15 +1160,14 @@ module Make1 Input1> { } /** - * Holds if the type tree at `term` satisfies the constraint `constraint` - * with the type `t` at `path`. + * Holds if `term` satisfies the constraint `constraint` with the type `t` at `path`. */ pragma[nomagic] - predicate satisfiesConstraintType(Term term, Constraint constraint, TypePath path, Type t) { - satisfiesConstraintTypeNonTypeParamInline(term, _, constraint, path, t) + predicate satisfiesConstraint(Term term, Constraint constraint, TypePath path, Type t) { + satisfiesConstraintNonTypeParamInline(term, _, constraint, path, t) or exists(TypePath prefix0, TypePath pathToTypeParamInSub, TypePath suffix | - satisfiesConstraintTypeMention(term, constraint, prefix0, pathToTypeParamInSub) and + satisfiesConstraintAtTypeParameter(term, constraint, prefix0, pathToTypeParamInSub) and getTypeAt(term, pathToTypeParamInSub.appendInverse(suffix)) = t and path = prefix0.append(suffix) ) @@ -1159,25 +1176,34 @@ module Make1 Input1> { t = getTypeAt(term, path) } + pragma[nomagic] + private predicate satisfiesConstraintThrough0( + Term term, Constraint constraint, TypeAbstraction abs, TypePath pathToTypeParamInConstraint, + TypePath pathToTypeParamInSub + ) { + satisfiesConstraintInline(term, constraint, abs, pathToTypeParamInConstraint, + pathToTypeParamInSub, _) + } + /** - * Holds if the type tree at `term` satisfies the constraint `constraint` - * through `abs` with the type `t` at `path`. + * Holds if `term` satisfies the constraint `constraint` through `abs` with + * the type `t` at `path`. */ pragma[nomagic] - predicate satisfiesConstraintTypeThrough( + predicate satisfiesConstraintThrough( Term term, TypeAbstraction abs, Constraint constraint, TypePath path, Type t ) { - satisfiesConstraintTypeNonTypeParamInline(term, abs, constraint, path, t) + satisfiesConstraintNonTypeParamInline(term, abs, constraint, path, t) or exists(TypePath prefix0, TypePath pathToTypeParamInSub, TypePath suffix | - satisfiesConstraintTypeMentionThrough(term, constraint, abs, prefix0, pathToTypeParamInSub) and + satisfiesConstraintThrough0(term, constraint, abs, prefix0, pathToTypeParamInSub) and getTypeAt(term, pathToTypeParamInSub.appendInverse(suffix)) = t and path = prefix0.append(suffix) ) } /** - * Holds if the type tree at `term` does _not_ satisfy the constraint `constraint`. + * Holds if `term` does _not_ satisfy the constraint `constraint`. * * This is an approximation of `not satisfiesConstraintType(term, constraint, _, _)`, * but defined without a negative occurrence of `satisfiesConstraintType`. @@ -1495,7 +1521,7 @@ module Make1 Input1> { TypeMention constraint ) { target = a.getTarget(e) and - typeParameterConstraintHasTypeParameter(target, apos, path, constraint, _, _) + typeParameterHasConstraint(target, apos, _, path, constraint) } private newtype TRelevantAccess = @@ -1556,13 +1582,40 @@ module Make1 Input1> { SatisfiesTypeParameterConstraintInput>; pragma[nomagic] - predicate satisfiesConstraintType( + predicate satisfiesConstraintAtTypeParameter( + Access a, AccessEnvironment e, Declaration target, AccessPosition apos, TypePath prefix, + TypeMention constraint, TypePath pathToTypeParamInConstraint, + TypePath pathToTypeParamInSub + ) { + exists(RelevantAccess ra | + ra = MkRelevantAccess(a, apos, e, prefix) and + SatisfiesTypeParameterConstraint::satisfiesConstraintAtTypeParameter(ra, constraint, + pathToTypeParamInConstraint, pathToTypeParamInSub) and + constraint = ra.getConstraint(target) + ) + } + + pragma[nomagic] + predicate satisfiesConstraint( Access a, AccessEnvironment e, Declaration target, AccessPosition apos, TypePath prefix, TypeMention constraint, TypePath path, Type t ) { exists(RelevantAccess ra | ra = MkRelevantAccess(a, apos, e, prefix) and - SatisfiesTypeParameterConstraint::satisfiesConstraintType(ra, constraint, path, t) and + SatisfiesTypeParameterConstraint::satisfiesConstraint(ra, constraint, path, t) and + constraint = ra.getConstraint(target) + ) + } + + pragma[nomagic] + predicate satisfiesConstraintThrough( + Access a, AccessEnvironment e, Declaration target, AccessPosition apos, TypePath prefix, + TypeAbstraction abs, TypeMention constraint, TypePath path, Type t + ) { + exists(RelevantAccess ra | + ra = MkRelevantAccess(a, apos, e, prefix) and + SatisfiesTypeParameterConstraint::satisfiesConstraintThrough(ra, abs, constraint, path, + t) and constraint = ra.getConstraint(target) ) } @@ -1707,7 +1760,7 @@ module Make1 Input1> { not exists(getTypeArgument(a, target, tp, _)) and exists(TypeMention constraint, AccessPosition apos, TypePath pathToTp, TypePath pathToTp2 | typeParameterConstraintHasTypeParameter(target, apos, pathToTp2, constraint, pathToTp, tp) and - AccessConstraint::satisfiesConstraintType(a, e, target, apos, pathToTp2, constraint, + AccessConstraint::satisfiesConstraint(a, e, target, apos, pathToTp2, constraint, pathToTp.appendInverse(path), t) ) } @@ -1785,6 +1838,82 @@ module Make1 Input1> { not result instanceof TypeParameter ) ) + or + exists( + Declaration target, TypePath prefix, TypeMention constraint, + TypePath pathToTypeParamInConstraint, TypePath pathToTypeParamInSub + | + AccessConstraint::satisfiesConstraintAtTypeParameter(a, e, target, apos, prefix, + constraint, pathToTypeParamInConstraint, pathToTypeParamInSub) + | + exists(TypePath suffix | + /* + * Example: + * + * ```rust + * struct MyThing { ... } + * + * trait MyTrait { ... } + * + * impl MyTrait for MyThing { ... } + * + * fn foo>(x: T) { ... } + * + * let x = MyThing(Default::default()); + * foo(x); + * ``` + * + * At `term` = `foo(x)`, we have + * - `constraint = MyTrait`, + * - `pathToTypeParamInConstraint` = `"B"`, + * - `pathToTypeParamInSub` = `"A"`, + * - `prefix` = `suffix` = `""`, and + * - `result` = `i32`. + * + * That is, it allows us to infer that the type of `x` is `MyThing`. + */ + + result = constraint.getTypeAt(pathToTypeParamInConstraint.appendInverse(suffix)) and + not result instanceof TypeParameter and + path = prefix.append(pathToTypeParamInSub.append(suffix)) + ) + or + exists(TypeParameter tp, TypePath suffix, TypePath mid, TypePath pathToTp | + /* + * Example: + * + * ```rust + * struct MyThing { ... } + * + * trait MyTrait { ... } + * + * impl MyTrait for MyThing { ... } + * + * fn bar>(x: T1, y: T2) {} + * + * let x : i32 = ...; + * let y = MyThing(Default::default()); + * bar(x, y); + * ``` + * + * At `term` = `bar(x, y)`, we have + * - `constraint = MyTrait`, + * - `pathToTypeParamInConstraint` = `"B"`, + * - `pathToTypeParamInSub` = `"A"`, + * - `prefix` = `suffix` = `mid` = `""`, + * - `tp = T1`, + * - `pathToTp` = `"B"`, and + * - `result` = `i32`. + * + * That is, it allows us to infer that the type of `y` is `MyThing`. + */ + + typeMatch(a, e, target, suffix, result, tp) and + typeParameterConstraintHasTypeParameter(target, apos, _, constraint, pathToTp, tp) and + pathToTp = pathToTypeParamInConstraint.appendInverse(mid) and + path = prefix.append(pathToTypeParamInSub.append(mid).append(suffix)) + ) + ) } }