mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge branch 'main' into copilot/add-ecb-cbc-test-cases
This commit is contained in:
@@ -1 +1 @@
|
||||
8.1.1
|
||||
8.4.2
|
||||
|
||||
5
.github/dependabot.yml
vendored
5
.github/dependabot.yml
vendored
@@ -40,3 +40,8 @@ updates:
|
||||
- dependency-name: "*"
|
||||
reviewers:
|
||||
- "github/codeql-go"
|
||||
|
||||
- package-ecosystem: bazel
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
|
||||
12
MODULE.bazel
12
MODULE.bazel
@@ -23,7 +23,7 @@ bazel_dep(name = "rules_shell", version = "0.5.0")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.8.1")
|
||||
bazel_dep(name = "abseil-cpp", version = "20240116.1", repo_name = "absl")
|
||||
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
|
||||
bazel_dep(name = "fmt", version = "10.0.0")
|
||||
bazel_dep(name = "fmt", version = "12.1.0-codeql.1")
|
||||
bazel_dep(name = "rules_kotlin", version = "2.1.3-codeql.1")
|
||||
bazel_dep(name = "gazelle", version = "0.40.0")
|
||||
bazel_dep(name = "rules_dotnet", version = "0.19.2-codeql.1")
|
||||
@@ -274,11 +274,11 @@ ripunzip_archive = use_repo_rule("//misc/ripunzip:ripunzip.bzl", "ripunzip_archi
|
||||
# go to https://github.com/GoogleChrome/ripunzip/releases to find latest version and corresponding sha256s
|
||||
ripunzip_archive(
|
||||
name = "ripunzip",
|
||||
sha256_linux = "ee0e8a957687a5dc3a66b2a4b25883bf762df4c9c07f0651af527a32a405054b",
|
||||
sha256_macos_arm = "8a88eea54eac232d162a72a42065e0429b82dbf4f05e9642915dff9d7a81f846",
|
||||
sha256_macos_intel = "4457a18bfcc5feabe09f5ea3d1157128e07b4873392cb404a870e611924abf64",
|
||||
sha256_windows = "66d0c1375301bf5ab815348048f43b110631d3fa7200acd50d50a8ed8655ca62",
|
||||
version = "2.0.3",
|
||||
sha256_linux = "71482d7a7e4ea9176d5596161c49250c34b136b157c45f632b1111323fbfc0de",
|
||||
sha256_macos_arm = "604194ab13f0aba3972995d995f11002b8fc285c8170401fcd46655065df20c9",
|
||||
sha256_macos_intel = "65367b94fd579d93d46f2d2595cc4c9a60cfcf497e3c824f9d1a7b80fa8bd38a",
|
||||
sha256_windows = "ac3874075def2b9e5074a3b5945005ab082cc6e689e1de658da8965bc23e643e",
|
||||
version = "2.0.4",
|
||||
)
|
||||
|
||||
register_toolchains(
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
## 0.4.23
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.4.22
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.4.21
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: majorAnalysis
|
||||
---
|
||||
* The query `actions/code-injection/medium` has been updated to include results which were incorrectly excluded while filtering out results that are reported by `actions/code-injection/critical`.
|
||||
3
actions/ql/lib/change-notes/released/0.4.22.md
Normal file
3
actions/ql/lib/change-notes/released/0.4.22.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.4.22
|
||||
|
||||
No user-facing changes.
|
||||
3
actions/ql/lib/change-notes/released/0.4.23.md
Normal file
3
actions/ql/lib/change-notes/released/0.4.23.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.4.23
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.4.21
|
||||
lastReleaseVersion: 0.4.23
|
||||
|
||||
@@ -19,12 +19,7 @@ class CodeInjectionSink extends DataFlow::Node {
|
||||
Event getRelevantCriticalEventForSink(DataFlow::Node sink) {
|
||||
inPrivilegedContext(sink.asExpr(), result) and
|
||||
not exists(ControlCheck check | check.protects(sink.asExpr(), result, "code-injection")) and
|
||||
// exclude cases where the sink is a JS script and the expression uses toJson
|
||||
not exists(UsesStep script |
|
||||
script.getCallee() = "actions/github-script" and
|
||||
script.getArgumentExpr("script") = sink.asExpr() and
|
||||
exists(getAToJsonReferenceExpression(sink.asExpr().(Expression).getExpression(), _))
|
||||
)
|
||||
not isGithubScriptUsingToJson(sink.asExpr())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,3 +86,38 @@ private module CodeInjectionConfig implements DataFlow::ConfigSig {
|
||||
|
||||
/** Tracks flow of unsafe user input that is used to construct and evaluate a code script. */
|
||||
module CodeInjectionFlow = TaintTracking::Global<CodeInjectionConfig>;
|
||||
|
||||
/**
|
||||
* Holds if there is a code injection flow from `source` to `sink` with
|
||||
* critical severity, linked by `event`.
|
||||
*/
|
||||
predicate criticalSeverityCodeInjection(
|
||||
CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink, Event event
|
||||
) {
|
||||
CodeInjectionFlow::flowPath(source, sink) and
|
||||
event = getRelevantCriticalEventForSink(sink.getNode()) and
|
||||
source.getNode().(RemoteFlowSource).getEventName() = event.getName()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a code injection flow from `source` to `sink` with medium severity.
|
||||
*/
|
||||
predicate mediumSeverityCodeInjection(
|
||||
CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink
|
||||
) {
|
||||
CodeInjectionFlow::flowPath(source, sink) and
|
||||
not criticalSeverityCodeInjection(source, sink, _) and
|
||||
not isGithubScriptUsingToJson(sink.getNode().asExpr())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `expr` is the `script` input to `actions/github-script` and it uses
|
||||
* `toJson`.
|
||||
*/
|
||||
predicate isGithubScriptUsingToJson(Expression expr) {
|
||||
exists(UsesStep script |
|
||||
script.getCallee() = "actions/github-script" and
|
||||
script.getArgumentExpr("script") = expr and
|
||||
exists(getAToJsonReferenceExpression(expr.getExpression(), _))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/actions-all
|
||||
version: 0.4.22-dev
|
||||
version: 0.4.24-dev
|
||||
library: true
|
||||
warnOnImplicitThis: true
|
||||
dependencies:
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
## 0.6.15
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.6.14
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.6.13
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -20,10 +20,7 @@ import CodeInjectionFlow::PathGraph
|
||||
import codeql.actions.security.ControlChecks
|
||||
|
||||
from CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink, Event event
|
||||
where
|
||||
CodeInjectionFlow::flowPath(source, sink) and
|
||||
event = getRelevantCriticalEventForSink(sink.getNode()) and
|
||||
source.getNode().(RemoteFlowSource).getEventName() = event.getName()
|
||||
where criticalSeverityCodeInjection(source, sink, event)
|
||||
select sink.getNode(), source, sink,
|
||||
"Potential code injection in $@, which may be controlled by an external user ($@).", sink,
|
||||
sink.getNode().asExpr().(Expression).getRawExpression(), event, event.getName()
|
||||
|
||||
@@ -19,15 +19,7 @@ import codeql.actions.security.CodeInjectionQuery
|
||||
import CodeInjectionFlow::PathGraph
|
||||
|
||||
from CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink
|
||||
where
|
||||
CodeInjectionFlow::flowPath(source, sink) and
|
||||
inNonPrivilegedContext(sink.getNode().asExpr()) and
|
||||
// exclude cases where the sink is a JS script and the expression uses toJson
|
||||
not exists(UsesStep script |
|
||||
script.getCallee() = "actions/github-script" and
|
||||
script.getArgumentExpr("script") = sink.getNode().asExpr() and
|
||||
exists(getAToJsonReferenceExpression(sink.getNode().asExpr().(Expression).getExpression(), _))
|
||||
)
|
||||
where mediumSeverityCodeInjection(source, sink)
|
||||
select sink.getNode(), source, sink,
|
||||
"Potential code injection in $@, which may be controlled by an external user.", sink,
|
||||
sink.getNode().asExpr().(Expression).getRawExpression()
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
If a GitHub Actions job or workflow has no explicit permissions set, then the repository permissions are used. Repositories created under organizations inherit the organization permissions. The organizations or repositories created before February 2023 have the default permissions set to read-write. Often these permissions do not adhere to the principle of least privilege and can be reduced to read-only, leaving the `write` permission only to a specific types as `issues: write` or `pull-requests: write`.
|
||||
|
||||
Note that this query cannot check whether the organization or repository token settings are set to read-only. However, even if they are, it is recommended to define explicit permissions (`contents: read` and `packages: read` are equivalent to the read-only default) so that (a) the actual needs of the workflow are documented, and (b) the permissions will remain restricted if the default is subsequently changed, or the workflow is copied to a different repository or organization.
|
||||
|
||||
## Recommendation
|
||||
|
||||
Add the `permissions` key to the job or the root of workflow (in this case it is applied to all jobs in the workflow that do not have their own `permissions` key) and assign the least privileges required to complete the task.
|
||||
|
||||
3
actions/ql/src/change-notes/released/0.6.14.md
Normal file
3
actions/ql/src/change-notes/released/0.6.14.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.6.14
|
||||
|
||||
No user-facing changes.
|
||||
3
actions/ql/src/change-notes/released/0.6.15.md
Normal file
3
actions/ql/src/change-notes/released/0.6.15.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.6.15
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.6.13
|
||||
lastReleaseVersion: 0.6.15
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @name Artifact Poisoning (Path Traversal).
|
||||
* @name Artifact Poisoning (Path Traversal)
|
||||
* @description An attacker may be able to poison the workflow's artifacts and influence on consequent steps.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/actions-queries
|
||||
version: 0.6.14-dev
|
||||
version: 0.6.16-dev
|
||||
library: false
|
||||
warnOnImplicitThis: true
|
||||
groups: [actions, queries]
|
||||
|
||||
18
actions/ql/test/query-tests/Security/CWE-094/.github/workflows/push_and_workflow_dispatch.yml
vendored
Normal file
18
actions/ql/test/query-tests/Security/CWE-094/.github/workflows/push_and_workflow_dispatch.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
on:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
echo-chamber:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo '${{ github.event.commits[11].message }}'
|
||||
- run: echo '${{ github.event.commits[11].author.email }}'
|
||||
- run: echo '${{ github.event.commits[11].author.name }}'
|
||||
- run: echo '${{ github.event.head_commit.message }}'
|
||||
- run: echo '${{ github.event.head_commit.author.email }}'
|
||||
- run: echo '${{ github.event.head_commit.author.name }}'
|
||||
- run: echo '${{ github.event.head_commit.committer.email }}'
|
||||
- run: echo '${{ github.event.head_commit.committer.name }}'
|
||||
- run: echo '${{ github.event.commits[11].committer.email }}'
|
||||
- run: echo '${{ github.event.commits[11].committer.name }}'
|
||||
@@ -435,6 +435,16 @@ nodes
|
||||
| .github/workflows/push.yml:14:19:14:64 | github.event.head_commit.committer.name | semmle.label | github.event.head_commit.committer.name |
|
||||
| .github/workflows/push.yml:15:19:15:65 | github.event.commits[11].committer.email | semmle.label | github.event.commits[11].committer.email |
|
||||
| .github/workflows/push.yml:16:19:16:64 | github.event.commits[11].committer.name | semmle.label | github.event.commits[11].committer.name |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:9:19:9:57 | github.event.commits[11].message | semmle.label | github.event.commits[11].message |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:10:19:10:62 | github.event.commits[11].author.email | semmle.label | github.event.commits[11].author.email |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:11:19:11:61 | github.event.commits[11].author.name | semmle.label | github.event.commits[11].author.name |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:12:19:12:57 | github.event.head_commit.message | semmle.label | github.event.head_commit.message |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:13:19:13:62 | github.event.head_commit.author.email | semmle.label | github.event.head_commit.author.email |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:14:19:14:61 | github.event.head_commit.author.name | semmle.label | github.event.head_commit.author.name |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:15:19:15:65 | github.event.head_commit.committer.email | semmle.label | github.event.head_commit.committer.email |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:16:19:16:64 | github.event.head_commit.committer.name | semmle.label | github.event.head_commit.committer.name |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:17:19:17:65 | github.event.commits[11].committer.email | semmle.label | github.event.commits[11].committer.email |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:18:19:18:64 | github.event.commits[11].committer.name | semmle.label | github.event.commits[11].committer.name |
|
||||
| .github/workflows/reusable-workflow-1.yml:6:7:6:11 | input taint | semmle.label | input taint |
|
||||
| .github/workflows/reusable-workflow-1.yml:36:21:36:39 | inputs.taint | semmle.label | inputs.taint |
|
||||
| .github/workflows/reusable-workflow-1.yml:44:19:44:56 | github.event.pull_request.title | semmle.label | github.event.pull_request.title |
|
||||
|
||||
@@ -435,6 +435,16 @@ nodes
|
||||
| .github/workflows/push.yml:14:19:14:64 | github.event.head_commit.committer.name | semmle.label | github.event.head_commit.committer.name |
|
||||
| .github/workflows/push.yml:15:19:15:65 | github.event.commits[11].committer.email | semmle.label | github.event.commits[11].committer.email |
|
||||
| .github/workflows/push.yml:16:19:16:64 | github.event.commits[11].committer.name | semmle.label | github.event.commits[11].committer.name |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:9:19:9:57 | github.event.commits[11].message | semmle.label | github.event.commits[11].message |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:10:19:10:62 | github.event.commits[11].author.email | semmle.label | github.event.commits[11].author.email |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:11:19:11:61 | github.event.commits[11].author.name | semmle.label | github.event.commits[11].author.name |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:12:19:12:57 | github.event.head_commit.message | semmle.label | github.event.head_commit.message |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:13:19:13:62 | github.event.head_commit.author.email | semmle.label | github.event.head_commit.author.email |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:14:19:14:61 | github.event.head_commit.author.name | semmle.label | github.event.head_commit.author.name |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:15:19:15:65 | github.event.head_commit.committer.email | semmle.label | github.event.head_commit.committer.email |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:16:19:16:64 | github.event.head_commit.committer.name | semmle.label | github.event.head_commit.committer.name |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:17:19:17:65 | github.event.commits[11].committer.email | semmle.label | github.event.commits[11].committer.email |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:18:19:18:64 | github.event.commits[11].committer.name | semmle.label | github.event.commits[11].committer.name |
|
||||
| .github/workflows/reusable-workflow-1.yml:6:7:6:11 | input taint | semmle.label | input taint |
|
||||
| .github/workflows/reusable-workflow-1.yml:36:21:36:39 | inputs.taint | semmle.label | inputs.taint |
|
||||
| .github/workflows/reusable-workflow-1.yml:44:19:44:56 | github.event.pull_request.title | semmle.label | github.event.pull_request.title |
|
||||
@@ -719,6 +729,16 @@ subpaths
|
||||
| .github/workflows/push.yml:14:19:14:64 | github.event.head_commit.committer.name | .github/workflows/push.yml:14:19:14:64 | github.event.head_commit.committer.name | .github/workflows/push.yml:14:19:14:64 | github.event.head_commit.committer.name | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/push.yml:14:19:14:64 | github.event.head_commit.committer.name | ${{ github.event.head_commit.committer.name }} |
|
||||
| .github/workflows/push.yml:15:19:15:65 | github.event.commits[11].committer.email | .github/workflows/push.yml:15:19:15:65 | github.event.commits[11].committer.email | .github/workflows/push.yml:15:19:15:65 | github.event.commits[11].committer.email | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/push.yml:15:19:15:65 | github.event.commits[11].committer.email | ${{ github.event.commits[11].committer.email }} |
|
||||
| .github/workflows/push.yml:16:19:16:64 | github.event.commits[11].committer.name | .github/workflows/push.yml:16:19:16:64 | github.event.commits[11].committer.name | .github/workflows/push.yml:16:19:16:64 | github.event.commits[11].committer.name | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/push.yml:16:19:16:64 | github.event.commits[11].committer.name | ${{ github.event.commits[11].committer.name }} |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:9:19:9:57 | github.event.commits[11].message | .github/workflows/push_and_workflow_dispatch.yml:9:19:9:57 | github.event.commits[11].message | .github/workflows/push_and_workflow_dispatch.yml:9:19:9:57 | github.event.commits[11].message | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/push_and_workflow_dispatch.yml:9:19:9:57 | github.event.commits[11].message | ${{ github.event.commits[11].message }} |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:10:19:10:62 | github.event.commits[11].author.email | .github/workflows/push_and_workflow_dispatch.yml:10:19:10:62 | github.event.commits[11].author.email | .github/workflows/push_and_workflow_dispatch.yml:10:19:10:62 | github.event.commits[11].author.email | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/push_and_workflow_dispatch.yml:10:19:10:62 | github.event.commits[11].author.email | ${{ github.event.commits[11].author.email }} |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:11:19:11:61 | github.event.commits[11].author.name | .github/workflows/push_and_workflow_dispatch.yml:11:19:11:61 | github.event.commits[11].author.name | .github/workflows/push_and_workflow_dispatch.yml:11:19:11:61 | github.event.commits[11].author.name | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/push_and_workflow_dispatch.yml:11:19:11:61 | github.event.commits[11].author.name | ${{ github.event.commits[11].author.name }} |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:12:19:12:57 | github.event.head_commit.message | .github/workflows/push_and_workflow_dispatch.yml:12:19:12:57 | github.event.head_commit.message | .github/workflows/push_and_workflow_dispatch.yml:12:19:12:57 | github.event.head_commit.message | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/push_and_workflow_dispatch.yml:12:19:12:57 | github.event.head_commit.message | ${{ github.event.head_commit.message }} |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:13:19:13:62 | github.event.head_commit.author.email | .github/workflows/push_and_workflow_dispatch.yml:13:19:13:62 | github.event.head_commit.author.email | .github/workflows/push_and_workflow_dispatch.yml:13:19:13:62 | github.event.head_commit.author.email | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/push_and_workflow_dispatch.yml:13:19:13:62 | github.event.head_commit.author.email | ${{ github.event.head_commit.author.email }} |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:14:19:14:61 | github.event.head_commit.author.name | .github/workflows/push_and_workflow_dispatch.yml:14:19:14:61 | github.event.head_commit.author.name | .github/workflows/push_and_workflow_dispatch.yml:14:19:14:61 | github.event.head_commit.author.name | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/push_and_workflow_dispatch.yml:14:19:14:61 | github.event.head_commit.author.name | ${{ github.event.head_commit.author.name }} |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:15:19:15:65 | github.event.head_commit.committer.email | .github/workflows/push_and_workflow_dispatch.yml:15:19:15:65 | github.event.head_commit.committer.email | .github/workflows/push_and_workflow_dispatch.yml:15:19:15:65 | github.event.head_commit.committer.email | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/push_and_workflow_dispatch.yml:15:19:15:65 | github.event.head_commit.committer.email | ${{ github.event.head_commit.committer.email }} |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:16:19:16:64 | github.event.head_commit.committer.name | .github/workflows/push_and_workflow_dispatch.yml:16:19:16:64 | github.event.head_commit.committer.name | .github/workflows/push_and_workflow_dispatch.yml:16:19:16:64 | github.event.head_commit.committer.name | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/push_and_workflow_dispatch.yml:16:19:16:64 | github.event.head_commit.committer.name | ${{ github.event.head_commit.committer.name }} |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:17:19:17:65 | github.event.commits[11].committer.email | .github/workflows/push_and_workflow_dispatch.yml:17:19:17:65 | github.event.commits[11].committer.email | .github/workflows/push_and_workflow_dispatch.yml:17:19:17:65 | github.event.commits[11].committer.email | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/push_and_workflow_dispatch.yml:17:19:17:65 | github.event.commits[11].committer.email | ${{ github.event.commits[11].committer.email }} |
|
||||
| .github/workflows/push_and_workflow_dispatch.yml:18:19:18:64 | github.event.commits[11].committer.name | .github/workflows/push_and_workflow_dispatch.yml:18:19:18:64 | github.event.commits[11].committer.name | .github/workflows/push_and_workflow_dispatch.yml:18:19:18:64 | github.event.commits[11].committer.name | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/push_and_workflow_dispatch.yml:18:19:18:64 | github.event.commits[11].committer.name | ${{ github.event.commits[11].committer.name }} |
|
||||
| .github/workflows/reusable-workflow-1.yml:36:21:36:39 | inputs.taint | .github/workflows/reusable-workflow-caller-1.yml:11:15:11:52 | github.event.pull_request.title | .github/workflows/reusable-workflow-1.yml:36:21:36:39 | inputs.taint | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/reusable-workflow-1.yml:36:21:36:39 | inputs.taint | ${{ inputs.taint }} |
|
||||
| .github/workflows/reusable-workflow-1.yml:53:26:53:39 | env.log | .github/workflows/reusable-workflow-1.yml:44:19:44:56 | github.event.pull_request.title | .github/workflows/reusable-workflow-1.yml:53:26:53:39 | env.log | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/reusable-workflow-1.yml:53:26:53:39 | env.log | ${{ env.log }} |
|
||||
| .github/workflows/reusable-workflow-1.yml:66:34:66:52 | env.prev_log | .github/workflows/reusable-workflow-1.yml:45:24:45:61 | github.event.changes.title.from | .github/workflows/reusable-workflow-1.yml:66:34:66:52 | env.prev_log | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/reusable-workflow-1.yml:66:34:66:52 | env.prev_log | ${{ env.prev_log }} |
|
||||
@@ -729,6 +749,10 @@ subpaths
|
||||
| .github/workflows/test10.yml:333:34:333:77 | github.event.workflow_run.head_branch | .github/workflows/test10.yml:333:34:333:77 | github.event.workflow_run.head_branch | .github/workflows/test10.yml:333:34:333:77 | github.event.workflow_run.head_branch | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test10.yml:333:34:333:77 | github.event.workflow_run.head_branch | ${{ github.event.workflow_run.head_branch }} |
|
||||
| .github/workflows/test10.yml:423:34:423:77 | github.event.workflow_run.head_branch | .github/workflows/test10.yml:423:34:423:77 | github.event.workflow_run.head_branch | .github/workflows/test10.yml:423:34:423:77 | github.event.workflow_run.head_branch | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test10.yml:423:34:423:77 | github.event.workflow_run.head_branch | ${{ github.event.workflow_run.head_branch }} |
|
||||
| .github/workflows/test10.yml:518:34:518:77 | github.event.workflow_run.head_branch | .github/workflows/test10.yml:518:34:518:77 | github.event.workflow_run.head_branch | .github/workflows/test10.yml:518:34:518:77 | github.event.workflow_run.head_branch | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test10.yml:518:34:518:77 | github.event.workflow_run.head_branch | ${{ github.event.workflow_run.head_branch }} |
|
||||
| .github/workflows/test20.yml:15:54:15:94 | github.event.pull_request.head.ref | .github/workflows/test20.yml:15:54:15:94 | github.event.pull_request.head.ref | .github/workflows/test20.yml:15:54:15:94 | github.event.pull_request.head.ref | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test20.yml:15:54:15:94 | github.event.pull_request.head.ref | ${{ github.event.pull_request.head.ref }} |
|
||||
| .github/workflows/test21.yml:22:35:22:73 | github.event.head_commit.message | .github/workflows/test21.yml:22:35:22:73 | github.event.head_commit.message | .github/workflows/test21.yml:22:35:22:73 | github.event.head_commit.message | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test21.yml:22:35:22:73 | github.event.head_commit.message | ${{ github.event.head_commit.message }} |
|
||||
| .github/workflows/test21.yml:23:36:23:74 | github.event.head_commit.message | .github/workflows/test21.yml:23:36:23:74 | github.event.head_commit.message | .github/workflows/test21.yml:23:36:23:74 | github.event.head_commit.message | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test21.yml:23:36:23:74 | github.event.head_commit.message | ${{ github.event.head_commit.message }} |
|
||||
| .github/workflows/test21.yml:24:50:24:88 | github.event.head_commit.message | .github/workflows/test21.yml:24:50:24:88 | github.event.head_commit.message | .github/workflows/test21.yml:24:50:24:88 | github.event.head_commit.message | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/test21.yml:24:50:24:88 | github.event.head_commit.message | ${{ github.event.head_commit.message }} |
|
||||
| .github/workflows/workflow_run_branches1.yml:13:20:13:63 | github.event.workflow_run.head_branch | .github/workflows/workflow_run_branches1.yml:13:20:13:63 | github.event.workflow_run.head_branch | .github/workflows/workflow_run_branches1.yml:13:20:13:63 | github.event.workflow_run.head_branch | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/workflow_run_branches1.yml:13:20:13:63 | github.event.workflow_run.head_branch | ${{ github.event.workflow_run.head_branch }} |
|
||||
| .github/workflows/workflow_run_branches2.yml:13:20:13:63 | github.event.workflow_run.head_branch | .github/workflows/workflow_run_branches2.yml:13:20:13:63 | github.event.workflow_run.head_branch | .github/workflows/workflow_run_branches2.yml:13:20:13:63 | github.event.workflow_run.head_branch | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/workflow_run_branches2.yml:13:20:13:63 | github.event.workflow_run.head_branch | ${{ github.event.workflow_run.head_branch }} |
|
||||
| .github/workflows/workflow_run_branches4.yml:13:20:13:63 | github.event.workflow_run.head_branch | .github/workflows/workflow_run_branches4.yml:13:20:13:63 | github.event.workflow_run.head_branch | .github/workflows/workflow_run_branches4.yml:13:20:13:63 | github.event.workflow_run.head_branch | Potential code injection in $@, which may be controlled by an external user. | .github/workflows/workflow_run_branches4.yml:13:20:13:63 | github.event.workflow_run.head_branch | ${{ github.event.workflow_run.head_branch }} |
|
||||
|
||||
@@ -276,5 +276,12 @@
|
||||
"Python model summaries test extension": [
|
||||
"python/ql/test/library-tests/dataflow/model-summaries/InlineTaintTest.ext.yml",
|
||||
"python/ql/test/library-tests/dataflow/model-summaries/NormalDataflowTest.ext.yml"
|
||||
],
|
||||
"XML discard predicates": [
|
||||
"javascript/ql/lib/semmle/javascript/internal/OverlayXml.qll",
|
||||
"java/ql/lib/semmle/code/java/internal/OverlayXml.qll",
|
||||
"go/ql/lib/semmle/go/internal/OverlayXml.qll",
|
||||
"python/ql/lib/semmle/python/internal/OverlayXml.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/internal/OverlayXml.qll"
|
||||
]
|
||||
}
|
||||
|
||||
2469
cpp/downgrades/a42ce5fc943254097f85471b94ae2247e819104a/old.dbscheme
Normal file
2469
cpp/downgrades/a42ce5fc943254097f85471b94ae2247e819104a/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
description: Add databaseMetadata and overlayChangedFiles relations
|
||||
compatibility: full
|
||||
databaseMetadata.rel: delete
|
||||
overlayChangedFiles.rel: delete
|
||||
@@ -1,3 +1,13 @@
|
||||
## 6.1.2
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 6.1.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The class `DataFlow::FieldContent` now covers both `union` and `struct`/`class` types. A new predicate `FieldContent.getAField` has been added to access the union members associated with the `FieldContent`. The old `FieldContent` has been renamed to `NonUnionFieldContent`.
|
||||
|
||||
## 6.1.0
|
||||
|
||||
### New Features
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The class `DataFlow::FieldContent` now covers both `union` and `struct`/`class` types. A new predicate `FieldContent.getAField` has been added to access the union members associated with the `FieldContent`. The old `FieldContent` has been renamed to `NonUnionFieldContent`.
|
||||
## 6.1.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The class `DataFlow::FieldContent` now covers both `union` and `struct`/`class` types. A new predicate `FieldContent.getAField` has been added to access the union members associated with the `FieldContent`. The old `FieldContent` has been renamed to `NonUnionFieldContent`.
|
||||
3
cpp/ql/lib/change-notes/released/6.1.2.md
Normal file
3
cpp/ql/lib/change-notes/released/6.1.2.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 6.1.2
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 6.1.0
|
||||
lastReleaseVersion: 6.1.2
|
||||
|
||||
@@ -74,3 +74,4 @@ import semmle.code.cpp.Preprocessor
|
||||
import semmle.code.cpp.Iteration
|
||||
import semmle.code.cpp.NameQualifiers
|
||||
import DefaultOptions
|
||||
private import semmle.code.cpp.internal.Overlay
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 6.1.1-dev
|
||||
version: 6.1.3-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
@@ -21,3 +21,4 @@ dataExtensions:
|
||||
- ext/deallocation/*.model.yml
|
||||
- ext/allocation/*.model.yml
|
||||
warnOnImplicitThis: true
|
||||
compileForOverlayEval: true
|
||||
|
||||
@@ -15,16 +15,17 @@
|
||||
* reading.
|
||||
* 1. The `namespace` column selects a namespace.
|
||||
* 2. The `type` column selects a type within that namespace. This column can
|
||||
* introduce template names that can be mentioned in the `signature` column.
|
||||
* introduce template type names that can be mentioned in the `signature` column.
|
||||
* For example, `vector<T,Allocator>` introduces the template names `T` and
|
||||
* `Allocator`.
|
||||
* `Allocator`. Non-type template parameters cannot be specified.
|
||||
* 3. The `subtypes` is a boolean that indicates whether to jump to an
|
||||
* arbitrary subtype of that type. Set this to `false` if leaving the `type`
|
||||
* blank (for example, a free function).
|
||||
* 4. The `name` column optionally selects a specific named member of the type.
|
||||
* Like the `type` column, this column can introduce template names that can
|
||||
* be mentioned in the `signature` column. For example, `insert<InputIt>`
|
||||
* introduces the template name `InputIt`.
|
||||
* Like the `type` column, this column can introduce template type names
|
||||
* that can be mentioned in the `signature` column. For example,
|
||||
* `insert<InputIt>` introduces the template name `InputIt`. Non-type
|
||||
* template parameters cannot be specified.
|
||||
* 5. The `signature` column optionally restricts the named member. If
|
||||
* `signature` is blank then no such filtering is done. The format of the
|
||||
* signature is a comma-separated list of types enclosed in parentheses. The
|
||||
@@ -633,6 +634,28 @@ string getParameterTypeWithoutTemplateArguments(Function f, int n, boolean canon
|
||||
canonical = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the largest index of a template parameter of `templateFunction` that
|
||||
* is a type template parameter.
|
||||
*/
|
||||
private int getLastTypeTemplateFunctionParameterIndex(Function templateFunction) {
|
||||
result =
|
||||
max(int index | templateFunction.getTemplateArgument(index) instanceof TypeTemplateParameter)
|
||||
}
|
||||
|
||||
/** Gets the number of supported template parameters for `templateFunction`. */
|
||||
private int getNumberOfSupportedFunctionTemplateArguments(Function templateFunction) {
|
||||
result = count(int i | exists(getSupportedFunctionTemplateArgument(templateFunction, i)) | i)
|
||||
}
|
||||
|
||||
/** Gets the `i`'th supported template parameter for `templateFunction`. */
|
||||
private Locatable getSupportedFunctionTemplateArgument(Function templateFunction, int i) {
|
||||
result = templateFunction.getTemplateArgument(i) and
|
||||
// We don't yet support non-type template parameters in the middle of a
|
||||
// template parameter list
|
||||
i <= getLastTypeTemplateFunctionParameterIndex(templateFunction)
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the `n`'th parameter of `f` by replacing template names
|
||||
* with `func:N` (where `N` is the index of the template).
|
||||
@@ -640,18 +663,41 @@ string getParameterTypeWithoutTemplateArguments(Function f, int n, boolean canon
|
||||
private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remaining) {
|
||||
exists(Function templateFunction |
|
||||
templateFunction = getFullyTemplatedFunction(f) and
|
||||
remaining = templateFunction.getNumberOfTemplateArguments() and
|
||||
remaining = getNumberOfSupportedFunctionTemplateArguments(templateFunction) and
|
||||
result = getParameterTypeWithoutTemplateArguments(templateFunction, n, _)
|
||||
)
|
||||
or
|
||||
exists(string mid, TypeTemplateParameter tp, Function templateFunction |
|
||||
mid = getTypeNameWithoutFunctionTemplates(f, n, remaining + 1) and
|
||||
templateFunction = getFullyTemplatedFunction(f) and
|
||||
tp = templateFunction.getTemplateArgument(remaining) and
|
||||
tp = getSupportedFunctionTemplateArgument(templateFunction, remaining)
|
||||
|
|
||||
result = mid.replaceAll(tp.getName(), "func:" + remaining.toString())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the largest index of a template parameter of `templateClass` that
|
||||
* is a type template parameter.
|
||||
*/
|
||||
private int getLastTypeTemplateClassParameterIndex(Class templateClass) {
|
||||
result =
|
||||
max(int index | templateClass.getTemplateArgument(index) instanceof TypeTemplateParameter)
|
||||
}
|
||||
|
||||
/** Gets the `i`'th supported template parameter for `templateClass`. */
|
||||
private Locatable getSupportedClassTemplateArgument(Class templateClass, int i) {
|
||||
result = templateClass.getTemplateArgument(i) and
|
||||
// We don't yet support non-type template parameters in the middle of a
|
||||
// template parameter list
|
||||
i <= getLastTypeTemplateClassParameterIndex(templateClass)
|
||||
}
|
||||
|
||||
/** Gets the number of supported template parameters for `templateClass`. */
|
||||
private int getNumberOfSupportedClassTemplateArguments(Class templateClass) {
|
||||
result = count(int i | exists(getSupportedClassTemplateArgument(templateClass, i)) | i)
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the `n`'th parameter of `f` by replacing template names
|
||||
* with `class:N` (where `N` is the index of the template).
|
||||
@@ -661,7 +707,7 @@ private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining
|
||||
// If there is a declaring type then we start by expanding the function templates
|
||||
exists(Class template |
|
||||
isClassConstructedFrom(f.getDeclaringType(), template) and
|
||||
remaining = template.getNumberOfTemplateArguments() and
|
||||
remaining = getNumberOfSupportedClassTemplateArguments(template) and
|
||||
result = getTypeNameWithoutFunctionTemplates(f, n, 0)
|
||||
)
|
||||
or
|
||||
@@ -673,7 +719,8 @@ private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining
|
||||
exists(string mid, TypeTemplateParameter tp, Class template |
|
||||
mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and
|
||||
isClassConstructedFrom(f.getDeclaringType(), template) and
|
||||
tp = template.getTemplateArgument(remaining) and
|
||||
tp = getSupportedClassTemplateArgument(template, remaining)
|
||||
|
|
||||
result = mid.replaceAll(tp.getName(), "class:" + remaining.toString())
|
||||
)
|
||||
}
|
||||
|
||||
60
cpp/ql/lib/semmle/code/cpp/internal/Overlay.qll
Normal file
60
cpp/ql/lib/semmle/code/cpp/internal/Overlay.qll
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Defines entity discard predicates for C++ overlay analysis.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Holds always for the overlay variant and never for the base variant.
|
||||
* This local predicate is used to define local predicates that behave
|
||||
* differently for the base and overlay variant.
|
||||
*/
|
||||
overlay[local]
|
||||
predicate isOverlay() { databaseMetadata("isOverlay", "true") }
|
||||
|
||||
overlay[local]
|
||||
private string getLocationFilePath(@location_default loc) {
|
||||
exists(@file file | locations_default(loc, file, _, _, _, _) | files(file, result))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file path for an element with a single location.
|
||||
*/
|
||||
overlay[local]
|
||||
private string getSingleLocationFilePath(@element e) {
|
||||
// @var_decl has a direct location in the var_decls relation
|
||||
exists(@location_default loc | var_decls(e, _, _, _, loc) | result = getLocationFilePath(loc))
|
||||
//TODO: add other kinds of elements with single locations
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file path for an element with potentially multiple locations.
|
||||
*/
|
||||
overlay[local]
|
||||
private string getMultiLocationFilePath(@element e) {
|
||||
// @variable gets its location(s) from its @var_decl(s)
|
||||
exists(@var_decl vd, @location_default loc | var_decls(vd, e, _, _, loc) |
|
||||
result = getLocationFilePath(loc)
|
||||
)
|
||||
//TODO: add other kinds of elements with multiple locations
|
||||
}
|
||||
|
||||
/**
|
||||
* A local helper predicate that holds in the base variant and never in the
|
||||
* overlay variant.
|
||||
*/
|
||||
overlay[local]
|
||||
private predicate holdsInBase() { not isOverlay() }
|
||||
|
||||
/**
|
||||
* Discards an element from the base variant if:
|
||||
* - It has a single location in a changed file, or
|
||||
* - All of its locations are in changed files.
|
||||
*/
|
||||
overlay[discard_entity]
|
||||
private predicate discardElement(@element e) {
|
||||
holdsInBase() and
|
||||
(
|
||||
overlayChangedFiles(getSingleLocationFilePath(e))
|
||||
or
|
||||
forex(string path | path = getMultiLocationFilePath(e) | overlayChangedFiles(path))
|
||||
)
|
||||
}
|
||||
@@ -2078,38 +2078,151 @@ predicate localExprFlow(Expr e1, Expr e2) {
|
||||
localExprFlowPlus(e1, e2)
|
||||
}
|
||||
|
||||
/**
|
||||
* A canonical representation of a field.
|
||||
*
|
||||
* For performance reasons we want a unique `Content` that represents
|
||||
* a given field across any template instantiation of a class.
|
||||
*
|
||||
* This is possible in _almost_ all cases, but there are cases where it is
|
||||
* not possible to map between a field in the uninstantiated template to a
|
||||
* field in the instantiated template. This happens in the case of local class
|
||||
* definitions (because the local class is not the template that constructs
|
||||
* the instantiation - it is the enclosing function). So this abstract class
|
||||
* has two implementations: a non-local case (where we can represent a
|
||||
* canonical field as the field declaration from an uninstantiated class
|
||||
* template or a non-templated class), and a local case (where we simply use
|
||||
* the field from the instantiated class).
|
||||
*/
|
||||
abstract private class CanonicalField extends Field {
|
||||
/** Gets a field represented by this canonical field. */
|
||||
abstract Field getAField();
|
||||
|
||||
/**
|
||||
* Gets a class that declares a field represented by this canonical field.
|
||||
*/
|
||||
abstract Class getADeclaringType();
|
||||
|
||||
/**
|
||||
* Gets a type that this canonical field may have. Note that this may
|
||||
* not be a unique type. For example, consider this case:
|
||||
* ```
|
||||
* template<typename T>
|
||||
* struct S { T x; };
|
||||
*
|
||||
* S<int> s1;
|
||||
* S<char> s2;
|
||||
* ```
|
||||
* In this case the canonical field corresponding to `S::x` has two types:
|
||||
* `int` and `char`.
|
||||
*/
|
||||
Type getAType() { result = this.getAField().getType() }
|
||||
|
||||
Type getAnUnspecifiedType() { result = this.getAType().getUnspecifiedType() }
|
||||
}
|
||||
|
||||
private class NonLocalCanonicalField extends CanonicalField {
|
||||
Class declaringType;
|
||||
|
||||
NonLocalCanonicalField() {
|
||||
declaringType = this.getDeclaringType() and
|
||||
not declaringType.isFromTemplateInstantiation(_) and
|
||||
not declaringType.isLocal() // handled in LocalCanonicalField
|
||||
}
|
||||
|
||||
override Field getAField() {
|
||||
exists(Class c | result.getDeclaringType() = c |
|
||||
// Either the declaring class of the field is a template instantiation
|
||||
// that has been constructed from this canonical declaration
|
||||
c.isConstructedFrom(declaringType) and
|
||||
pragma[only_bind_out](result.getName()) = pragma[only_bind_out](this.getName())
|
||||
or
|
||||
// or this canonical declaration is not a template.
|
||||
not c.isConstructedFrom(_) and
|
||||
result = this
|
||||
)
|
||||
}
|
||||
|
||||
override Class getADeclaringType() {
|
||||
result = this.getDeclaringType()
|
||||
or
|
||||
result.isConstructedFrom(this.getDeclaringType())
|
||||
}
|
||||
}
|
||||
|
||||
private class LocalCanonicalField extends CanonicalField {
|
||||
Class declaringType;
|
||||
|
||||
LocalCanonicalField() {
|
||||
declaringType = this.getDeclaringType() and
|
||||
declaringType.isLocal()
|
||||
}
|
||||
|
||||
override Field getAField() { result = this }
|
||||
|
||||
override Class getADeclaringType() { result = declaringType }
|
||||
}
|
||||
|
||||
/**
|
||||
* A canonical representation of a `Union`. See `CanonicalField` for the explanation for
|
||||
* why we need a canonical representation.
|
||||
*/
|
||||
abstract private class CanonicalUnion extends Union {
|
||||
/** Gets a union represented by this canonical union. */
|
||||
abstract Union getAUnion();
|
||||
|
||||
/** Gets a canonical field of this canonical union. */
|
||||
CanonicalField getACanonicalField() { result.getDeclaringType() = this }
|
||||
}
|
||||
|
||||
private class NonLocalCanonicalUnion extends CanonicalUnion {
|
||||
NonLocalCanonicalUnion() { not this.isFromTemplateInstantiation(_) and not this.isLocal() }
|
||||
|
||||
override Union getAUnion() {
|
||||
result = this
|
||||
or
|
||||
result.isConstructedFrom(this)
|
||||
}
|
||||
}
|
||||
|
||||
private class LocalCanonicalUnion extends CanonicalUnion {
|
||||
LocalCanonicalUnion() { this.isLocal() }
|
||||
|
||||
override Union getAUnion() { result = this }
|
||||
}
|
||||
|
||||
bindingset[f]
|
||||
pragma[inline_late]
|
||||
private int getFieldSize(Field f) { result = f.getType().getSize() }
|
||||
private int getFieldSize(CanonicalField f) { result = max(f.getAType().getSize()) }
|
||||
|
||||
/**
|
||||
* Gets a field in the union `u` whose size
|
||||
* is `bytes` number of bytes.
|
||||
*/
|
||||
private Field getAFieldWithSize(Union u, int bytes) {
|
||||
result = u.getAField() and
|
||||
private CanonicalField getAFieldWithSize(CanonicalUnion u, int bytes) {
|
||||
result = u.getACanonicalField() and
|
||||
bytes = getFieldSize(result)
|
||||
}
|
||||
|
||||
cached
|
||||
private newtype TContent =
|
||||
TNonUnionContent(Field f, int indirectionIndex) {
|
||||
TNonUnionContent(CanonicalField f, int indirectionIndex) {
|
||||
// the indirection index for field content starts at 1 (because `TNonUnionContent` is thought of as
|
||||
// the address of the field, `FieldAddress` in the IR).
|
||||
indirectionIndex = [1 .. SsaImpl::getMaxIndirectionsForType(f.getUnspecifiedType())] and
|
||||
indirectionIndex = [1 .. max(SsaImpl::getMaxIndirectionsForType(f.getAnUnspecifiedType()))] and
|
||||
// Reads and writes of union fields are tracked using `UnionContent`.
|
||||
not f.getDeclaringType() instanceof Union
|
||||
} or
|
||||
TUnionContent(Union u, int bytes, int indirectionIndex) {
|
||||
exists(Field f |
|
||||
f = u.getAField() and
|
||||
TUnionContent(CanonicalUnion u, int bytes, int indirectionIndex) {
|
||||
exists(CanonicalField f |
|
||||
f = u.getACanonicalField() and
|
||||
bytes = getFieldSize(f) and
|
||||
// We key `UnionContent` by the union instead of its fields since a write to one
|
||||
// field can be read by any read of the union's fields. Again, the indirection index
|
||||
// is 1-based (because 0 is considered the address).
|
||||
indirectionIndex =
|
||||
[1 .. max(SsaImpl::getMaxIndirectionsForType(getAFieldWithSize(u, bytes)
|
||||
.getUnspecifiedType())
|
||||
.getAnUnspecifiedType())
|
||||
)]
|
||||
)
|
||||
} or
|
||||
@@ -2175,8 +2288,12 @@ class FieldContent extends Content, TFieldContent {
|
||||
|
||||
/**
|
||||
* Gets the field associated with this `Content`, if a unique one exists.
|
||||
*
|
||||
* For fields from template instantiations this predicate may still return
|
||||
* more than one field, but all the fields will be constructed from the same
|
||||
* template.
|
||||
*/
|
||||
final Field getField() { result = unique( | | this.getAField()) }
|
||||
Field getField() { none() } // overridden in subclasses
|
||||
|
||||
override int getIndirectionIndex() { none() } // overridden in subclasses
|
||||
|
||||
@@ -2187,32 +2304,33 @@ class FieldContent extends Content, TFieldContent {
|
||||
|
||||
/** A reference through a non-union instance field. */
|
||||
class NonUnionFieldContent extends FieldContent, TNonUnionContent {
|
||||
private Field f;
|
||||
private CanonicalField f;
|
||||
private int indirectionIndex;
|
||||
|
||||
NonUnionFieldContent() { this = TNonUnionContent(f, indirectionIndex) }
|
||||
|
||||
override string toString() { result = contentStars(this) + f.toString() }
|
||||
|
||||
override Field getAField() { result = f }
|
||||
final override Field getField() { result = f.getAField() }
|
||||
|
||||
override Field getAField() { result = this.getField() }
|
||||
|
||||
/** Gets the indirection index of this `FieldContent`. */
|
||||
override int getIndirectionIndex() { result = indirectionIndex }
|
||||
|
||||
override predicate impliesClearOf(Content c) {
|
||||
exists(FieldContent fc |
|
||||
fc = c and
|
||||
fc.getField() = f and
|
||||
exists(int i |
|
||||
c = TNonUnionContent(f, i) and
|
||||
// If `this` is `f` then `c` is cleared if it's of the
|
||||
// form `*f`, `**f`, etc.
|
||||
fc.getIndirectionIndex() >= indirectionIndex
|
||||
i >= indirectionIndex
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A reference through an instance field of a union. */
|
||||
class UnionContent extends FieldContent, TUnionContent {
|
||||
private Union u;
|
||||
private CanonicalUnion u;
|
||||
private int indirectionIndex;
|
||||
private int bytes;
|
||||
|
||||
@@ -2220,24 +2338,31 @@ class UnionContent extends FieldContent, TUnionContent {
|
||||
|
||||
override string toString() { result = contentStars(this) + u.toString() }
|
||||
|
||||
final override Field getField() { result = unique( | | u.getACanonicalField()).getAField() }
|
||||
|
||||
/** Gets a field of the underlying union of this `UnionContent`, if any. */
|
||||
override Field getAField() { result = u.getAField() and getFieldSize(result) = bytes }
|
||||
override Field getAField() {
|
||||
exists(CanonicalField cf |
|
||||
cf = u.getACanonicalField() and
|
||||
result = cf.getAField() and
|
||||
getFieldSize(cf) = bytes
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the underlying union of this `UnionContent`. */
|
||||
Union getUnion() { result = u }
|
||||
Union getUnion() { result = u.getAUnion() }
|
||||
|
||||
/** Gets the indirection index of this `UnionContent`. */
|
||||
override int getIndirectionIndex() { result = indirectionIndex }
|
||||
|
||||
override predicate impliesClearOf(Content c) {
|
||||
exists(UnionContent uc |
|
||||
uc = c and
|
||||
uc.getUnion() = u and
|
||||
exists(int i |
|
||||
c = TUnionContent(u, _, i) and
|
||||
// If `this` is `u` then `c` is cleared if it's of the
|
||||
// form `*u`, `**u`, etc. (and we ignore `bytes` because
|
||||
// we know the entire union is overwritten because it's a
|
||||
// union).
|
||||
uc.getIndirectionIndex() >= indirectionIndex
|
||||
i >= indirectionIndex
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
/*- Compilations -*/
|
||||
|
||||
/**
|
||||
@@ -2378,6 +2379,24 @@ link_parent(
|
||||
int link_target : @link_target ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The CLI will automatically emit applicable tuples for this table,
|
||||
* such as `databaseMetadata("isOverlay", "true")` when building an
|
||||
* overlay database.
|
||||
*/
|
||||
databaseMetadata(
|
||||
string metadataKey: string ref,
|
||||
string value: string ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The CLI will automatically emit tuples for each new/modified/deleted file
|
||||
* when building an overlay database.
|
||||
*/
|
||||
overlayChangedFiles(
|
||||
string path: string ref
|
||||
);
|
||||
|
||||
/*- XML Files -*/
|
||||
|
||||
xmlEncoding(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Add databaseMetadata and overlayChangedFiles relations
|
||||
compatibility: full
|
||||
@@ -1,3 +1,11 @@
|
||||
## 1.5.6
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.5.5
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.5.4
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -10,7 +10,7 @@ import ExternalAPIsSpecific
|
||||
|
||||
/** A node representing untrusted data being passed to an external API. */
|
||||
class UntrustedExternalApiDataNode extends ExternalApiDataNode {
|
||||
UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::flow(_, this) }
|
||||
UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::flowTo(this) }
|
||||
|
||||
/** Gets a source of untrusted data which is passed to this external API data node. */
|
||||
DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::flow(result, this) }
|
||||
|
||||
@@ -10,7 +10,7 @@ import ExternalAPIsSpecific
|
||||
|
||||
/** A node representing untrusted data being passed to an external API. */
|
||||
class UntrustedExternalApiDataNode extends ExternalApiDataNode {
|
||||
UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::flow(_, this) }
|
||||
UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::flowTo(this) }
|
||||
|
||||
/** Gets a source of untrusted data which is passed to this external API data node. */
|
||||
DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::flow(result, this) }
|
||||
|
||||
@@ -263,7 +263,7 @@ module FromSensitiveFlow = TaintTracking::Global<FromSensitiveConfig>;
|
||||
* A taint flow configuration for flow from a sensitive expression to an encryption operation.
|
||||
*/
|
||||
module ToEncryptionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { FromSensitiveFlow::flow(source, _) }
|
||||
predicate isSource(DataFlow::Node source) { FromSensitiveFlow::flowFrom(source) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isSinkEncrypt(sink, _) }
|
||||
|
||||
@@ -311,7 +311,7 @@ where
|
||||
FromSensitiveFlow::flowPath(source, sink) and
|
||||
isSinkSendRecv(sink.getNode(), networkSendRecv) and
|
||||
// no flow from sensitive -> evidence of encryption
|
||||
not ToEncryptionFlow::flow(source.getNode(), _) and
|
||||
not ToEncryptionFlow::flowFrom(source.getNode()) and
|
||||
not FromEncryptionFlow::flowTo(sink.getNode()) and
|
||||
// construct result
|
||||
if networkSendRecv instanceof NetworkSend
|
||||
|
||||
3
cpp/ql/src/change-notes/released/1.5.5.md
Normal file
3
cpp/ql/src/change-notes/released/1.5.5.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 1.5.5
|
||||
|
||||
No user-facing changes.
|
||||
3
cpp/ql/src/change-notes/released/1.5.6.md
Normal file
3
cpp/ql/src/change-notes/released/1.5.6.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 1.5.6
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.5.4
|
||||
lastReleaseVersion: 1.5.6
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @name Dangerous use convert function.
|
||||
* @name Dangerous use convert function
|
||||
* @description Using convert function with an invalid length argument can result in an out-of-bounds access error or unexpected result.
|
||||
* @kind problem
|
||||
* @id cpp/dangerous-use-convert-function
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @name Dangerous use of transformation after operation.
|
||||
* @name Dangerous use of transformation after operation
|
||||
* @description By using the transformation after the operation, you are doing a pointless and dangerous action.
|
||||
* @kind problem
|
||||
* @id cpp/dangerous-use-of-transformation-after-operation
|
||||
|
||||
@@ -129,7 +129,7 @@ module PointerArithmeticToDerefFlow = DataFlow::Global<PointerArithmeticToDerefC
|
||||
|
||||
predicate pointerArithOverflow(PointerArithmeticInstruction pai, int delta) {
|
||||
pointerArithOverflow0(pai, delta) and
|
||||
PointerArithmeticToDerefFlow::flow(DataFlow::instructionNode(pai), _)
|
||||
PointerArithmeticToDerefFlow::flowFrom(DataFlow::instructionNode(pai))
|
||||
}
|
||||
|
||||
bindingset[v]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @name Writing to a file without setting permissions.
|
||||
* @name Writing to a file without setting permissions
|
||||
* @description Lack of restriction on file access rights can be unsafe.
|
||||
* @kind problem
|
||||
* @id cpp/work-with-file-without-permissions-rights
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @name Find work with changing working directories, with security errors.
|
||||
* @name Find work with changing working directories, with security errors
|
||||
* @description Not validating the return value or pinning the directory can be unsafe.
|
||||
* @kind problem
|
||||
* @id cpp/work-with-changing-working-directories
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @name Find the wrong use of the umask function.
|
||||
* @name Find the wrong use of the umask function
|
||||
* @description Incorrectly evaluated argument to the umask function may have security implications.
|
||||
* @kind problem
|
||||
* @id cpp/wrong-use-of-the-umask
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @name Insecure generation of filenames.
|
||||
* @name Insecure generation of filenames
|
||||
* @description Using a predictable filename when creating a temporary file can lead to an attacker-controlled input.
|
||||
* @kind problem
|
||||
* @id cpp/insecure-generation-of-filename
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @name Dangerous use of exception blocks.
|
||||
* @name Dangerous use of exception blocks
|
||||
* @description When clearing the data in the catch block, you must be sure that the memory was allocated before the exception.
|
||||
* @kind problem
|
||||
* @id cpp/dangerous-use-of-exception-blocks
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @name Dangerous use SSL_shutdown.
|
||||
* @name Dangerous use SSL_shutdown
|
||||
* @description Incorrect closing of the connection leads to the creation of different states for the server and client, which can be exploited by an attacker.
|
||||
* @kind problem
|
||||
* @id cpp/dangerous-use-of-ssl-shutdown
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 1.5.5-dev
|
||||
version: 1.5.7-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @name Capture content based summary models.
|
||||
* @name Capture content based summary models
|
||||
* @description Finds applicable content based summary models to be used by other queries.
|
||||
* @kind diagnostic
|
||||
* @id cpp/utils/modelgenerator/contentbased-summary-models
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @name Capture neutral models.
|
||||
* @name Capture neutral models
|
||||
* @description Finds neutral models to be used by other queries.
|
||||
* @kind diagnostic
|
||||
* @id cpp/utils/modelgenerator/neutral-models
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @name Capture sink models.
|
||||
* @name Capture sink models
|
||||
* @description Finds public methods that act as sinks as they flow into a known sink.
|
||||
* @kind diagnostic
|
||||
* @id cpp/utils/modelgenerator/sink-models
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @name Capture source models.
|
||||
* @name Capture source models
|
||||
* @description Finds APIs that act as sources as they expose already known sources.
|
||||
* @kind diagnostic
|
||||
* @id cpp/utils/modelgenerator/source-models
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @name Capture summary models.
|
||||
* @name Capture summary models
|
||||
* @description Finds applicable summary models to be used by other queries.
|
||||
* @kind diagnostic
|
||||
* @id cpp/utils/modelgenerator/summary-models
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
| clang421.c:1:12:1:19 | clang421 | 0 |
|
||||
| clang450.c:1:12:1:19 | clang450 | 1 |
|
||||
| gcc421.c:1:12:1:17 | gcc421 | 0 |
|
||||
| gcc450.c:1:12:1:17 | gcc450 | 1 |
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
static int gcc421 = __has_feature(attribute_deprecated_with_message);
|
||||
// semmle-extractor-options: --gnu_version 40201
|
||||
@@ -1,2 +0,0 @@
|
||||
static int gcc450 = __has_feature(attribute_deprecated_with_message);
|
||||
// semmle-extractor-options: --gnu_version 40500
|
||||
@@ -30,13 +30,14 @@ models
|
||||
| 29 | Summary: ; ; false; RtlMoveMemory; ; ; Argument[*@1]; Argument[*@0]; value; manual |
|
||||
| 30 | Summary: ; ; false; RtlMoveVolatileMemory; ; ; Argument[*@1]; Argument[*@0]; value; manual |
|
||||
| 31 | Summary: ; ; false; callWithArgument; ; ; Argument[1]; Argument[0].Parameter[0]; value; manual |
|
||||
| 32 | Summary: ; ; false; pthread_create; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual |
|
||||
| 33 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
|
||||
| 34 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
|
||||
| 35 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
|
||||
| 36 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
|
||||
| 32 | Summary: ; ; false; callWithNonTypeTemplate<T>; (const T &); ; Argument[*0]; ReturnValue; value; manual |
|
||||
| 33 | Summary: ; ; false; pthread_create; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual |
|
||||
| 34 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
|
||||
| 35 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
|
||||
| 36 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
|
||||
| 37 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
|
||||
edges
|
||||
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:36 |
|
||||
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:37 |
|
||||
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:17 |
|
||||
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:17 Sink:MaD:2 |
|
||||
| asio_streams.cpp:97:37:97:44 | call to source | asio_streams.cpp:98:7:98:14 | send_str | provenance | TaintFunction |
|
||||
@@ -45,10 +46,10 @@ edges
|
||||
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | |
|
||||
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:2 |
|
||||
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | provenance | |
|
||||
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:36 |
|
||||
| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:34 |
|
||||
| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:33 |
|
||||
| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:35 |
|
||||
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:37 |
|
||||
| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:35 |
|
||||
| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:34 |
|
||||
| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:36 |
|
||||
| test.cpp:7:47:7:52 | value2 | test.cpp:7:64:7:69 | value2 | provenance | |
|
||||
| test.cpp:7:64:7:69 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | provenance | |
|
||||
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:10:10:10:18 | call to ymlSource | provenance | Src:MaD:16 |
|
||||
@@ -60,15 +61,15 @@ edges
|
||||
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | |
|
||||
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:18:10:18:10 | y | provenance | Sink:MaD:1 |
|
||||
| test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | provenance | |
|
||||
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:34 |
|
||||
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:35 |
|
||||
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | |
|
||||
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:22:10:22:10 | z | provenance | Sink:MaD:1 |
|
||||
| test.cpp:21:27:21:27 | x | test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | provenance | |
|
||||
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:33 |
|
||||
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:34 |
|
||||
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | |
|
||||
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:26:10:26:11 | y2 | provenance | Sink:MaD:1 |
|
||||
| test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | provenance | |
|
||||
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:35 |
|
||||
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:36 |
|
||||
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | provenance | |
|
||||
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:33:10:33:11 | z2 | provenance | Sink:MaD:1 |
|
||||
| test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | provenance | |
|
||||
@@ -76,7 +77,7 @@ edges
|
||||
| test.cpp:46:30:46:32 | *arg [x] | test.cpp:47:12:47:19 | *arg [x] | provenance | |
|
||||
| test.cpp:47:12:47:19 | *arg [x] | test.cpp:48:13:48:13 | *s [x] | provenance | |
|
||||
| test.cpp:48:13:48:13 | *s [x] | test.cpp:48:16:48:16 | x | provenance | Sink:MaD:1 |
|
||||
| test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | provenance | MaD:32 |
|
||||
| test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | provenance | MaD:33 |
|
||||
| test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | test.cpp:46:30:46:32 | *arg [x] | provenance | |
|
||||
| test.cpp:56:2:56:2 | *s [post update] [x] | test.cpp:59:55:59:64 | *& ... [x] | provenance | |
|
||||
| test.cpp:56:2:56:18 | ... = ... | test.cpp:56:2:56:2 | *s [post update] [x] | provenance | |
|
||||
@@ -103,6 +104,13 @@ edges
|
||||
| test.cpp:101:26:101:26 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | |
|
||||
| test.cpp:103:63:103:63 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | |
|
||||
| test.cpp:104:62:104:62 | x | test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | provenance | |
|
||||
| test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:111:3:111:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | provenance | MaD:32 |
|
||||
| test.cpp:114:10:114:18 | call to ymlSource | test.cpp:114:10:114:18 | call to ymlSource | provenance | Src:MaD:16 |
|
||||
| test.cpp:114:10:114:18 | call to ymlSource | test.cpp:118:44:118:44 | *x | provenance | |
|
||||
| test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | provenance | |
|
||||
| test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | test.cpp:119:10:119:11 | y2 | provenance | Sink:MaD:1 |
|
||||
| test.cpp:118:44:118:44 | *x | test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | provenance | |
|
||||
| test.cpp:118:44:118:44 | *x | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | provenance | MaD:32 |
|
||||
| windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | provenance | MaD:18 |
|
||||
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:22:15:22:29 | *call to GetCommandLineA | provenance | Src:MaD:3 |
|
||||
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | windows.cpp:24:8:24:11 | * ... | provenance | |
|
||||
@@ -314,6 +322,14 @@ nodes
|
||||
| test.cpp:101:26:101:26 | x | semmle.label | x |
|
||||
| test.cpp:103:63:103:63 | x | semmle.label | x |
|
||||
| test.cpp:104:62:104:62 | x | semmle.label | x |
|
||||
| test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | semmle.label | [summary param] *0 in callWithNonTypeTemplate |
|
||||
| test.cpp:111:3:111:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | semmle.label | [summary] to write: ReturnValue in callWithNonTypeTemplate |
|
||||
| test.cpp:114:10:114:18 | call to ymlSource | semmle.label | call to ymlSource |
|
||||
| test.cpp:114:10:114:18 | call to ymlSource | semmle.label | call to ymlSource |
|
||||
| test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate |
|
||||
| test.cpp:118:11:118:42 | call to callWithNonTypeTemplate | semmle.label | call to callWithNonTypeTemplate |
|
||||
| test.cpp:118:44:118:44 | *x | semmle.label | *x |
|
||||
| test.cpp:119:10:119:11 | y2 | semmle.label | y2 |
|
||||
| windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | semmle.label | [summary param] *0 in CommandLineToArgvA |
|
||||
| windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | semmle.label | [summary] to write: ReturnValue[**] in CommandLineToArgvA |
|
||||
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | semmle.label | *call to GetCommandLineA |
|
||||
@@ -472,6 +488,7 @@ subpaths
|
||||
| test.cpp:21:27:21:27 | x | test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | test.cpp:21:10:21:25 | call to ymlStepGenerated |
|
||||
| test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body |
|
||||
| test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body |
|
||||
| test.cpp:118:44:118:44 | *x | test.cpp:111:3:111:25 | [summary param] *0 in callWithNonTypeTemplate | test.cpp:111:3:111:25 | [summary] to write: ReturnValue in callWithNonTypeTemplate | test.cpp:118:11:118:42 | call to callWithNonTypeTemplate |
|
||||
| windows.cpp:27:36:27:38 | *cmd | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | windows.cpp:27:17:27:34 | **call to CommandLineToArgvA |
|
||||
| windows.cpp:537:40:537:41 | *& ... | windows.cpp:473:17:473:37 | [summary param] *1 in RtlCopyVolatileMemory | windows.cpp:473:17:473:37 | [summary param] *0 in RtlCopyVolatileMemory [Return] | windows.cpp:537:27:537:37 | RtlCopyVolatileMemory output argument |
|
||||
| windows.cpp:542:38:542:39 | *& ... | windows.cpp:479:17:479:35 | [summary param] *1 in RtlCopyDeviceMemory | windows.cpp:479:17:479:35 | [summary param] *0 in RtlCopyDeviceMemory [Return] | windows.cpp:542:25:542:35 | RtlCopyDeviceMemory output argument |
|
||||
|
||||
@@ -17,4 +17,5 @@ extensions:
|
||||
- ["", "", False, "ymlStepGenerated", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"]
|
||||
- ["", "", False, "ymlStepManual_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["", "", False, "ymlStepGenerated_with_body", "", "", "Argument[0]", "ReturnValue", "taint", "df-generated"]
|
||||
- ["", "", False, "callWithArgument", "", "", "Argument[1]", "Argument[0].Parameter[0]", "value", "manual"]
|
||||
- ["", "", False, "callWithArgument", "", "", "Argument[1]", "Argument[0].Parameter[0]", "value", "manual"]
|
||||
- ["", "", False, "callWithNonTypeTemplate<T>", "(const T &)", "", "Argument[*0]", "ReturnValue", "value", "manual"]
|
||||
@@ -13,3 +13,5 @@
|
||||
| test.cpp:75:11:75:11 | y | test-sink |
|
||||
| test.cpp:83:11:83:11 | y | test-sink |
|
||||
| test.cpp:89:11:89:11 | y | test-sink |
|
||||
| test.cpp:116:10:116:11 | y1 | test-sink |
|
||||
| test.cpp:119:10:119:11 | y2 | test-sink |
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
| test.cpp:10:10:10:18 | call to ymlSource | local |
|
||||
| test.cpp:56:8:56:16 | call to ymlSource | local |
|
||||
| test.cpp:94:10:94:18 | call to ymlSource | local |
|
||||
| test.cpp:114:10:114:18 | call to ymlSource | local |
|
||||
| windows.cpp:22:15:22:29 | *call to GetCommandLineA | local |
|
||||
| windows.cpp:34:17:34:38 | *call to GetEnvironmentStringsA | local |
|
||||
| windows.cpp:39:36:39:38 | GetEnvironmentVariableA output argument | local |
|
||||
|
||||
@@ -102,4 +102,19 @@ void test_callWithArgument() {
|
||||
}
|
||||
callWithArgument(StructWithOperatorCall_has_constructor_2(), x);
|
||||
callWithArgument(StructWithOperatorCall_no_constructor_2(), x);
|
||||
}
|
||||
}
|
||||
|
||||
template<int N, typename T>
|
||||
T callWithNonTypeTemplate(const T&);
|
||||
|
||||
template<typename T, int N>
|
||||
T callWithNonTypeTemplate(const T&);
|
||||
|
||||
void test_callWithNonTypeTemplate() {
|
||||
int x = ymlSource();
|
||||
int y1 = callWithNonTypeTemplate<10, int>(x);
|
||||
ymlSink(y1); // $ MISSING: ir
|
||||
|
||||
int y2 = callWithNonTypeTemplate<int, 10>(x);
|
||||
ymlSink(y2); // $ ir
|
||||
}
|
||||
|
||||
@@ -142,6 +142,7 @@ postWithInFlow
|
||||
| simple.cpp:92:7:92:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| simple.cpp:118:7:118:7 | i [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| simple.cpp:124:5:124:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| simple.cpp:167:9:167:9 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
viableImplInCallContextTooLarge
|
||||
uniqueParameterNodeAtPosition
|
||||
uniqueParameterNodePosition
|
||||
|
||||
@@ -308,3 +308,5 @@ WARNING: module 'DataFlow' has been deprecated and may be removed in future (par
|
||||
| simple.cpp:124:5:124:6 | * ... | AST only |
|
||||
| simple.cpp:131:14:131:14 | a | IR only |
|
||||
| simple.cpp:136:10:136:10 | a | IR only |
|
||||
| simple.cpp:167:9:167:9 | x | AST only |
|
||||
| simple.cpp:168:8:168:12 | u_int | IR only |
|
||||
|
||||
@@ -670,6 +670,8 @@
|
||||
| simple.cpp:131:14:131:14 | a |
|
||||
| simple.cpp:135:20:135:20 | q |
|
||||
| simple.cpp:136:10:136:10 | a |
|
||||
| simple.cpp:167:3:167:7 | u_int |
|
||||
| simple.cpp:168:8:168:12 | u_int |
|
||||
| struct_init.c:15:8:15:9 | ab |
|
||||
| struct_init.c:15:12:15:12 | a |
|
||||
| struct_init.c:16:8:16:9 | ab |
|
||||
|
||||
@@ -597,6 +597,8 @@ WARNING: module 'DataFlow' has been deprecated and may be removed in future (par
|
||||
| simple.cpp:118:7:118:7 | i |
|
||||
| simple.cpp:124:5:124:6 | * ... |
|
||||
| simple.cpp:135:20:135:20 | q |
|
||||
| simple.cpp:167:3:167:7 | u_int |
|
||||
| simple.cpp:167:9:167:9 | x |
|
||||
| struct_init.c:15:8:15:9 | ab |
|
||||
| struct_init.c:15:12:15:12 | a |
|
||||
| struct_init.c:16:8:16:9 | ab |
|
||||
|
||||
@@ -136,4 +136,36 @@ void alias_with_fields(bool b) {
|
||||
sink(a.i); // $ MISSING: ast,ir
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
union U_with_two_instantiations_of_different_size {
|
||||
int x;
|
||||
T y;
|
||||
};
|
||||
|
||||
struct LargeStruct {
|
||||
int data[64];
|
||||
};
|
||||
|
||||
void test_union_with_two_instantiations_of_different_sizes() {
|
||||
// A union's fields is partitioned into "chunks" for field-flow in order to
|
||||
// improve performance (so that a write to a field of a union does not flow
|
||||
// to too many reads that don't happen at runtime). The partitioning is based
|
||||
// the size of the types in the union. So a write to a field of size k only
|
||||
// flows to a read of size k.
|
||||
// Since field-flow is based on uninstantiated types a field can have
|
||||
// multiple sizes if the union is instantiated with types of
|
||||
// different sizes. So to compute the partition we pick the maximum size.
|
||||
// Because of this there are `Content`s corresponding to the union
|
||||
// `U_with_two_instantiations_of_different_size<T>`: The one for size
|
||||
// `sizeof(int)`, and the one for size `sizeof(LargeStruct)` (because
|
||||
// `LargeStruct` is larger than `int`). So the write to `x` writes to the
|
||||
// `Content` for size `sizeof(int)`, and the read of `y` reads from the
|
||||
// `Content` for size `sizeof(LargeStruct)`.
|
||||
U_with_two_instantiations_of_different_size<int> u_int;
|
||||
U_with_two_instantiations_of_different_size<LargeStruct> u_very_large;
|
||||
|
||||
u_int.x = user_input();
|
||||
sink(u_int.y); // $ MISSING: ir
|
||||
}
|
||||
|
||||
} // namespace Simple
|
||||
@@ -26843,6 +26843,24 @@ getParameterTypeName
|
||||
| atl.cpp:71:5:71:17 | _U_STRINGorID | 0 | unsigned int |
|
||||
| atl.cpp:72:5:72:17 | _U_STRINGorID | 0 | LPCTSTR |
|
||||
| atl.cpp:72:5:72:17 | _U_STRINGorID | 0 | const char * |
|
||||
| atl.cpp:96:5:96:10 | CA2AEX | 0 | LPCSTR |
|
||||
| atl.cpp:96:5:96:10 | CA2AEX | 0 | const char * |
|
||||
| atl.cpp:96:5:96:10 | CA2AEX | 1 | UINT |
|
||||
| atl.cpp:96:5:96:10 | CA2AEX | 1 | unsigned int |
|
||||
| atl.cpp:97:5:97:10 | CA2AEX | 0 | LPCSTR |
|
||||
| atl.cpp:97:5:97:10 | CA2AEX | 0 | const char * |
|
||||
| atl.cpp:124:5:124:11 | CA2CAEX | 0 | LPCSTR |
|
||||
| atl.cpp:124:5:124:11 | CA2CAEX | 0 | const char * |
|
||||
| atl.cpp:124:5:124:11 | CA2CAEX | 1 | UINT |
|
||||
| atl.cpp:124:5:124:11 | CA2CAEX | 1 | unsigned int |
|
||||
| atl.cpp:125:5:125:11 | CA2CAEX | 0 | LPCSTR |
|
||||
| atl.cpp:125:5:125:11 | CA2CAEX | 0 | const char * |
|
||||
| atl.cpp:149:5:149:10 | CA2WEX | 0 | LPCSTR |
|
||||
| atl.cpp:149:5:149:10 | CA2WEX | 0 | const char * |
|
||||
| atl.cpp:149:5:149:10 | CA2WEX | 1 | UINT |
|
||||
| atl.cpp:149:5:149:10 | CA2WEX | 1 | unsigned int |
|
||||
| atl.cpp:150:5:150:10 | CA2WEX | 0 | LPCSTR |
|
||||
| atl.cpp:150:5:150:10 | CA2WEX | 0 | const char * |
|
||||
| atl.cpp:196:12:196:14 | Add | 0 | INARGTYPclass:0 |
|
||||
| atl.cpp:198:12:198:17 | Append | 0 | const CAtlArray & |
|
||||
| atl.cpp:199:10:199:13 | Copy | 0 | const CAtlArray & |
|
||||
@@ -27083,6 +27101,10 @@ getParameterTypeName
|
||||
| atl.cpp:940:10:940:18 | SetString | 0 | PCXSTR |
|
||||
| atl.cpp:940:10:940:18 | SetString | 0 | const class:0 * |
|
||||
| atl.cpp:942:11:942:20 | operator[] | 0 | int |
|
||||
| atl.cpp:1018:10:1018:10 | operator= | 0 | MakeOther && |
|
||||
| atl.cpp:1018:10:1018:10 | operator= | 0 | const MakeOther & |
|
||||
| atl.cpp:1023:10:1023:10 | operator= | 0 | MakeOther && |
|
||||
| atl.cpp:1023:10:1023:10 | operator= | 0 | const MakeOther & |
|
||||
| atl.cpp:1036:5:1036:12 | CStringT | 0 | const VARIANT & |
|
||||
| atl.cpp:1036:5:1036:12 | CStringT | 0 | const tagVARIANT & |
|
||||
| atl.cpp:1037:5:1037:12 | CStringT | 0 | const VARIANT & |
|
||||
@@ -27286,6 +27308,8 @@ getParameterTypeName
|
||||
| standalone_iterators.cpp:20:7:20:7 | operator= | 0 | const int_iterator_by_trait & |
|
||||
| standalone_iterators.cpp:20:7:20:7 | operator= | 0 | int_iterator_by_trait && |
|
||||
| standalone_iterators.cpp:23:27:23:36 | operator++ | 0 | int |
|
||||
| standalone_iterators.cpp:28:13:28:13 | operator= | 0 | const iterator_traits & |
|
||||
| standalone_iterators.cpp:28:13:28:13 | operator= | 0 | iterator_traits && |
|
||||
| standalone_iterators.cpp:36:7:36:7 | operator= | 0 | const non_iterator & |
|
||||
| standalone_iterators.cpp:36:7:36:7 | operator= | 0 | non_iterator && |
|
||||
| standalone_iterators.cpp:39:18:39:27 | operator++ | 0 | int |
|
||||
@@ -27297,6 +27321,8 @@ getParameterTypeName
|
||||
| standalone_iterators.cpp:66:30:66:39 | operator++ | 0 | int |
|
||||
| standalone_iterators.cpp:68:30:68:39 | operator-- | 0 | int |
|
||||
| standalone_iterators.cpp:70:31:70:39 | operator= | 0 | int |
|
||||
| standalone_iterators.cpp:74:13:74:13 | operator= | 0 | const iterator_traits & |
|
||||
| standalone_iterators.cpp:74:13:74:13 | operator= | 0 | iterator_traits && |
|
||||
| standalone_iterators.cpp:82:7:82:7 | container | 0 | const container & |
|
||||
| standalone_iterators.cpp:82:7:82:7 | container | 0 | container && |
|
||||
| standalone_iterators.cpp:82:7:82:7 | operator= | 0 | const container & |
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | address && | SemanticStackVariable | | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | const __va_list_tag & | SemanticStackVariable | | |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | const address & | SemanticStackVariable | | |
|
||||
| file://:0:0:0:0 | fp_offset | file://:0:0:0:0 | unsigned int | Field | | |
|
||||
| file://:0:0:0:0 | gp_offset | file://:0:0:0:0 | unsigned int | Field | | |
|
||||
| file://:0:0:0:0 | overflow_arg_area | file://:0:0:0:0 | void * | Field | | |
|
||||
| file://:0:0:0:0 | reg_save_area | file://:0:0:0:0 | void * | Field | | |
|
||||
| file://:0:0:0:0 | fp_offset | file://:0:0:0:0 | unsigned int | NonLocalCanonicalField | | |
|
||||
| file://:0:0:0:0 | gp_offset | file://:0:0:0:0 | unsigned int | NonLocalCanonicalField | | |
|
||||
| file://:0:0:0:0 | overflow_arg_area | file://:0:0:0:0 | void * | NonLocalCanonicalField | | |
|
||||
| file://:0:0:0:0 | reg_save_area | file://:0:0:0:0 | void * | NonLocalCanonicalField | | |
|
||||
| variables.cpp:1:12:1:12 | i | file://:0:0:0:0 | int | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
|
||||
| variables.cpp:2:12:2:12 | i | file://:0:0:0:0 | int | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
|
||||
| variables.cpp:3:12:3:12 | i | file://:0:0:0:0 | int | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
|
||||
@@ -33,10 +33,10 @@
|
||||
| variables.cpp:37:6:37:8 | ap3 | file://:0:0:0:0 | int * | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
|
||||
| variables.cpp:41:7:41:11 | local | file://:0:0:0:0 | char[] | LocalVariable, SemanticStackVariable | | |
|
||||
| variables.cpp:43:14:43:18 | local | file://:0:0:0:0 | int | GlobalLikeVariable, StaticLocalVariable | | static |
|
||||
| variables.cpp:48:9:48:12 | name | file://:0:0:0:0 | char * | Field | | |
|
||||
| variables.cpp:49:12:49:17 | number | file://:0:0:0:0 | long | Field | | |
|
||||
| variables.cpp:50:9:50:14 | street | file://:0:0:0:0 | char * | Field | | |
|
||||
| variables.cpp:51:9:51:12 | town | file://:0:0:0:0 | char * | Field | | |
|
||||
| variables.cpp:48:9:48:12 | name | file://:0:0:0:0 | char * | NonLocalCanonicalField | | |
|
||||
| variables.cpp:49:12:49:17 | number | file://:0:0:0:0 | long | NonLocalCanonicalField | | |
|
||||
| variables.cpp:50:9:50:14 | street | file://:0:0:0:0 | char * | NonLocalCanonicalField | | |
|
||||
| variables.cpp:51:9:51:12 | town | file://:0:0:0:0 | char * | NonLocalCanonicalField | | |
|
||||
| variables.cpp:52:16:52:22 | country | file://:0:0:0:0 | char * | MemberVariable, StaticStorageDurationVariable | | static |
|
||||
| variables.cpp:56:14:56:29 | externInFunction | file://:0:0:0:0 | int | GlobalLikeVariable, GlobalVariable, StaticStorageDurationVariable | | |
|
||||
| variables.cpp:60:10:60:17 | __func__ | file://:0:0:0:0 | const char[9] | GlobalLikeVariable, StaticInitializedStaticLocalVariable | | static |
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
| overflowdestination.cpp:46:2:46:7 | call to memcpy | This 'memcpy' operation accesses 128 bytes but the $@ is only 64 bytes. | overflowdestination.cpp:40:7:40:10 | dest | destination buffer |
|
||||
| tests.cpp:23:2:23:7 | call to memcpy | This 'memcpy' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:19:7:19:17 | smallbuffer | source buffer |
|
||||
| tests.cpp:25:2:25:7 | call to memcpy | This 'memcpy' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:19:7:19:17 | smallbuffer | destination buffer |
|
||||
| tests.cpp:34:2:34:7 | call to memcpy | This 'memcpy' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:30:30:30:35 | call to malloc | source buffer |
|
||||
| tests.cpp:36:2:36:7 | call to memcpy | This 'memcpy' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:30:30:30:35 | call to malloc | destination buffer |
|
||||
| tests.cpp:50:2:50:7 | call to memcpy | This 'memcpy' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:46:16:46:27 | new[] | source buffer |
|
||||
| tests.cpp:52:2:52:7 | call to memcpy | This 'memcpy' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:46:16:46:27 | new[] | destination buffer |
|
||||
| tests.cpp:172:23:172:31 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:170:17:170:41 | {...} | array |
|
||||
| tests.cpp:176:23:176:30 | access to array | This array indexing operation accesses byte offset 31 but the $@ is only 24 bytes. | tests.cpp:170:17:170:41 | {...} | array |
|
||||
| tests.cpp:222:3:222:8 | call to memset | This 'memset' operation accesses 33 bytes but the $@ is only 32 bytes. | tests.cpp:214:8:214:14 | buffer1 | destination buffer |
|
||||
|
||||
@@ -30,10 +30,10 @@ void test2()
|
||||
char *smallbuffer = (char *)malloc(sizeof(char) * 10);
|
||||
char *bigbuffer = (char *)malloc(sizeof(char) * 20);
|
||||
|
||||
memcpy(bigbuffer, smallbuffer, sizeof(smallbuffer)); // GOOD
|
||||
memcpy(bigbuffer, smallbuffer, sizeof(bigbuffer)); // BAD: over-read [NOT DETECTED]
|
||||
memcpy(smallbuffer, bigbuffer, sizeof(smallbuffer)); // GOOD
|
||||
memcpy(smallbuffer, bigbuffer, sizeof(bigbuffer)); // BAD: over-write [NOT DETECTED]
|
||||
memcpy(bigbuffer, smallbuffer, sizeof(char) * 10); // GOOD
|
||||
memcpy(bigbuffer, smallbuffer, sizeof(char) * 20); // BAD: over-read
|
||||
memcpy(smallbuffer, bigbuffer, sizeof(char) * 10); // GOOD
|
||||
memcpy(smallbuffer, bigbuffer, sizeof(char) * 20); // BAD: over-write
|
||||
|
||||
free(bigbuffer);
|
||||
free(smallbuffer);
|
||||
@@ -46,10 +46,10 @@ void test3()
|
||||
smallbuffer = new char[10];
|
||||
bigbuffer = new char[20];
|
||||
|
||||
memcpy(bigbuffer, smallbuffer, sizeof(smallbuffer)); // GOOD
|
||||
memcpy(bigbuffer, smallbuffer, sizeof(bigbuffer)); // BAD: over-read [NOT DETECTED]
|
||||
memcpy(smallbuffer, bigbuffer, sizeof(smallbuffer)); // GOOD
|
||||
memcpy(smallbuffer, bigbuffer, sizeof(bigbuffer)); // BAD: over-write [NOT DETECTED]
|
||||
memcpy(bigbuffer, smallbuffer, sizeof(char[10])); // GOOD
|
||||
memcpy(bigbuffer, smallbuffer, sizeof(char[20])); // BAD: over-read
|
||||
memcpy(smallbuffer, bigbuffer, sizeof(char[10])); // GOOD
|
||||
memcpy(smallbuffer, bigbuffer, sizeof(char[20])); // BAD: over-write
|
||||
|
||||
delete [] bigbuffer;
|
||||
delete [] smallbuffer;
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace Semmle.Autobuild.CSharp
|
||||
{
|
||||
// When a custom .NET CLI has been installed, `dotnet --info` has already been executed
|
||||
// to verify the installation.
|
||||
var ret = dotNetPath is null ? GetInfoCommand(builder.Actions, dotNetPath, environment) : BuildScript.Success;
|
||||
var ret = dotNetPath is null ? DotNet.InfoScript(builder.Actions, DotNetCommand(builder.Actions, dotNetPath), environment, builder.Logger) : BuildScript.Success;
|
||||
foreach (var projectOrSolution in builder.ProjectsOrSolutionsToBuild)
|
||||
{
|
||||
var cleanCommand = GetCleanCommand(builder.Actions, dotNetPath, environment);
|
||||
@@ -111,14 +111,6 @@ namespace Semmle.Autobuild.CSharp
|
||||
private static string DotNetCommand(IBuildActions actions, string? dotNetPath) =>
|
||||
dotNetPath is not null ? actions.PathCombine(dotNetPath, "dotnet") : "dotnet";
|
||||
|
||||
private static BuildScript GetInfoCommand(IBuildActions actions, string? dotNetPath, IDictionary<string, string>? environment)
|
||||
{
|
||||
var info = new CommandBuilder(actions, null, environment).
|
||||
RunCommand(DotNetCommand(actions, dotNetPath)).
|
||||
Argument("--info");
|
||||
return info.Script;
|
||||
}
|
||||
|
||||
private static CommandBuilder GetCleanCommand(IBuildActions actions, string? dotNetPath, IDictionary<string, string>? environment)
|
||||
{
|
||||
var clean = new CommandBuilder(actions, null, environment).
|
||||
|
||||
@@ -16,5 +16,6 @@ codeql_csharp_library(
|
||||
"//csharp/extractor/Semmle.Extraction.CSharp",
|
||||
"//csharp/extractor/Semmle.Util",
|
||||
"@paket.main//newtonsoft.json",
|
||||
"@paket.main//nuget.versioning",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -283,7 +283,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
{
|
||||
foreach (var fp in frameworkPaths)
|
||||
{
|
||||
dotnetFrameworkVersionVariantCount += NugetPackageRestorer.GetOrderedPackageVersionSubDirectories(fp.Path!).Length;
|
||||
dotnetFrameworkVersionVariantCount += nugetPackageRestorer.GetOrderedPackageVersionSubDirectories(fp.Path!).Length;
|
||||
}
|
||||
|
||||
var folder = nugetPackageRestorer.GetNewestNugetPackageVersionFolder(frameworkPath.Path, ".NET Framework");
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using Semmle.Util;
|
||||
@@ -36,12 +37,29 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
|
||||
public static IDotNet Make(ILogger logger, string? dotNetPath, TemporaryDirectory tempWorkingDirectory, DependabotProxy? dependabotProxy) => new DotNet(logger, dotNetPath, tempWorkingDirectory, dependabotProxy);
|
||||
|
||||
private static void HandleRetryExitCode143(string dotnet, int attempt, ILogger logger)
|
||||
{
|
||||
logger.LogWarning($"Running '{dotnet} --info' failed with exit code 143. Retrying...");
|
||||
var sleep = Math.Pow(2, attempt) * 1000;
|
||||
Thread.Sleep((int)sleep);
|
||||
}
|
||||
|
||||
private void Info()
|
||||
{
|
||||
var res = dotnetCliInvoker.RunCommand("--info", silent: false);
|
||||
if (!res)
|
||||
// Allow up to four attempts (with up to three retries) to run `dotnet --info`, to mitigate transient issues
|
||||
for (int attempt = 0; attempt < 4; attempt++)
|
||||
{
|
||||
throw new Exception($"{dotnetCliInvoker.Exec} --info failed.");
|
||||
var exitCode = dotnetCliInvoker.RunCommandExitCode("--info", silent: false);
|
||||
switch (exitCode)
|
||||
{
|
||||
case 0:
|
||||
return;
|
||||
case 143 when attempt < 3:
|
||||
HandleRetryExitCode143(dotnetCliInvoker.Exec, attempt, logger);
|
||||
continue;
|
||||
default:
|
||||
throw new Exception($"{dotnetCliInvoker.Exec} --info failed with exit code {exitCode}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +77,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
args += $" /p:TargetFrameworkRootPath=\"{path}\" /p:NetCoreTargetingPackRoot=\"{path}\"";
|
||||
args += $" /p:TargetFrameworkRootPath=\"{path}\" /p:NetCoreTargetingPackRoot=\"{path}\" /p:AllowMissingPrunePackageData=true";
|
||||
}
|
||||
|
||||
if (restoreSettings.PathToNugetConfig != null)
|
||||
@@ -193,6 +211,35 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
return BuildScript.Failure;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a script for running `dotnet --info`, with retries on exit code 143.
|
||||
/// </summary>
|
||||
public static BuildScript InfoScript(IBuildActions actions, string dotnet, IDictionary<string, string>? environment, ILogger logger)
|
||||
{
|
||||
var info = new CommandBuilder(actions, null, environment).
|
||||
RunCommand(dotnet).
|
||||
Argument("--info");
|
||||
var script = info.Script;
|
||||
for (var attempt = 0; attempt < 4; attempt++)
|
||||
{
|
||||
var attemptCopy = attempt; // Capture in local variable
|
||||
script = BuildScript.Bind(script, ret =>
|
||||
{
|
||||
switch (ret)
|
||||
{
|
||||
case 0:
|
||||
return BuildScript.Success;
|
||||
case 143 when attemptCopy < 3:
|
||||
HandleRetryExitCode143(dotnet, attemptCopy, logger);
|
||||
return info.Script;
|
||||
default:
|
||||
return BuildScript.Failure;
|
||||
}
|
||||
});
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a script for downloading specific .NET SDK versions, if the
|
||||
/// versions are not already installed.
|
||||
@@ -292,9 +339,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
};
|
||||
}
|
||||
|
||||
var dotnetInfo = new CommandBuilder(actions, environment: MinimalEnvironment).
|
||||
RunCommand(actions.PathCombine(path, "dotnet")).
|
||||
Argument("--info").Script;
|
||||
var dotnetInfo = InfoScript(actions, actions.PathCombine(path, "dotnet"), MinimalEnvironment.ToDictionary(), logger);
|
||||
|
||||
Func<string, BuildScript> getInstallAndVerify = version =>
|
||||
// run `dotnet --info` after install, to check that it executes successfully
|
||||
|
||||
@@ -57,15 +57,21 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
return startInfo;
|
||||
}
|
||||
|
||||
private bool RunCommandAux(string args, string? workingDirectory, out IList<string> output, bool silent)
|
||||
private int RunCommandExitCodeAux(string args, string? workingDirectory, out IList<string> output, out string dirLog, bool silent)
|
||||
{
|
||||
var dirLog = string.IsNullOrWhiteSpace(workingDirectory) ? "" : $" in {workingDirectory}";
|
||||
dirLog = string.IsNullOrWhiteSpace(workingDirectory) ? "" : $" in {workingDirectory}";
|
||||
var pi = MakeDotnetStartInfo(args, workingDirectory);
|
||||
var threadId = Environment.CurrentManagedThreadId;
|
||||
void onOut(string s) => logger.Log(silent ? Severity.Debug : Severity.Info, s, threadId);
|
||||
void onError(string s) => logger.LogError(s, threadId);
|
||||
logger.LogInfo($"Running '{Exec} {args}'{dirLog}");
|
||||
var exitCode = pi.ReadOutput(out output, onOut, onError);
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
private bool RunCommandAux(string args, string? workingDirectory, out IList<string> output, bool silent)
|
||||
{
|
||||
var exitCode = RunCommandExitCodeAux(args, workingDirectory, out output, out var dirLog, silent);
|
||||
if (exitCode != 0)
|
||||
{
|
||||
logger.LogError($"Command '{Exec} {args}'{dirLog} failed with exit code {exitCode}");
|
||||
@@ -77,6 +83,9 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
public bool RunCommand(string args, bool silent = true) =>
|
||||
RunCommandAux(args, null, out _, silent);
|
||||
|
||||
public int RunCommandExitCode(string args, bool silent = true) =>
|
||||
RunCommandExitCodeAux(args, null, out _, out _, silent);
|
||||
|
||||
public bool RunCommand(string args, out IList<string> output, bool silent = true) =>
|
||||
RunCommandAux(args, null, out output, silent);
|
||||
|
||||
|
||||
@@ -1,24 +1,16 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using NuGet.Versioning;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
{
|
||||
internal record DotNetVersion : IComparable<DotNetVersion>
|
||||
{
|
||||
private readonly string dir;
|
||||
private readonly Version version;
|
||||
private readonly Version? preReleaseVersion;
|
||||
private readonly string? preReleaseVersionType;
|
||||
private bool IsPreRelease => preReleaseVersionType is not null && preReleaseVersion is not null;
|
||||
private readonly NuGetVersion version;
|
||||
|
||||
private string FullVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
var preRelease = IsPreRelease ? $"-{preReleaseVersionType}.{preReleaseVersion}" : "";
|
||||
return this.version + preRelease;
|
||||
}
|
||||
}
|
||||
private string FullVersion =>
|
||||
version.ToString();
|
||||
|
||||
public string FullPath => Path.Combine(dir, FullVersion);
|
||||
|
||||
@@ -48,37 +40,14 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
}
|
||||
|
||||
|
||||
public DotNetVersion(string dir, string version, string preReleaseVersionType, string preReleaseVersion)
|
||||
public DotNetVersion(string dir, NuGetVersion version)
|
||||
{
|
||||
this.dir = dir;
|
||||
this.version = Version.Parse(version);
|
||||
if (!string.IsNullOrEmpty(preReleaseVersion) && !string.IsNullOrEmpty(preReleaseVersionType))
|
||||
{
|
||||
this.preReleaseVersionType = preReleaseVersionType;
|
||||
this.preReleaseVersion = Version.Parse(preReleaseVersion);
|
||||
}
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public int CompareTo(DotNetVersion? other)
|
||||
{
|
||||
var c = version.CompareTo(other?.version);
|
||||
if (c == 0 && IsPreRelease)
|
||||
{
|
||||
if (!other!.IsPreRelease)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Both are pre-release like runtime versions.
|
||||
// The pre-release version types are sorted alphabetically (e.g. alpha, beta, preview, rc)
|
||||
// and the pre-release version types are more important that the pre-release version numbers.
|
||||
return preReleaseVersionType != other!.preReleaseVersionType
|
||||
? preReleaseVersionType!.CompareTo(other!.preReleaseVersionType)
|
||||
: preReleaseVersion!.CompareTo(other!.preReleaseVersion);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
public int CompareTo(DotNetVersion? other) =>
|
||||
version.CompareTo(other?.version);
|
||||
|
||||
public override string ToString() => FullPath;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,12 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
/// </summary>
|
||||
bool RunCommand(string args, bool silent = true);
|
||||
|
||||
/// <summary>
|
||||
/// Execute `dotnet <paramref name="args"/>` and return the exit code.
|
||||
/// If `silent` is true the output of the command is logged as `debug` otherwise as `info`.
|
||||
/// </summary>
|
||||
int RunCommandExitCode(string args, bool silent = true);
|
||||
|
||||
/// <summary>
|
||||
/// Execute `dotnet <paramref name="args"/>` and return true if the command succeeded, otherwise false.
|
||||
/// The output of the command is returned in `output`.
|
||||
|
||||
@@ -10,6 +10,7 @@ using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NuGet.Versioning;
|
||||
using Semmle.Util;
|
||||
using Semmle.Util.Logging;
|
||||
|
||||
@@ -87,11 +88,22 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
return selectedFrameworkFolder;
|
||||
}
|
||||
|
||||
public static DirectoryInfo[] GetOrderedPackageVersionSubDirectories(string packagePath)
|
||||
public DirectoryInfo[] GetOrderedPackageVersionSubDirectories(string packagePath)
|
||||
{
|
||||
// Only consider directories with valid NuGet version names.
|
||||
return new DirectoryInfo(packagePath)
|
||||
.EnumerateDirectories("*", new EnumerationOptions { MatchCasing = MatchCasing.CaseInsensitive, RecurseSubdirectories = false })
|
||||
.OrderByDescending(d => d.Name) // TODO: Improve sorting to handle pre-release versions.
|
||||
.SelectMany(d =>
|
||||
{
|
||||
if (NuGetVersion.TryParse(d.Name, out var version))
|
||||
{
|
||||
return new[] { new { Directory = d, NuGetVersion = version } };
|
||||
}
|
||||
logger.LogInfo($"Ignoring package directory '{d.FullName}' as it does not have a valid NuGet version name.");
|
||||
return [];
|
||||
})
|
||||
.OrderByDescending(dw => dw.NuGetVersion)
|
||||
.Select(dw => dw.Directory)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using NuGet.Versioning;
|
||||
using Semmle.Util;
|
||||
using Semmle.Util.Logging;
|
||||
|
||||
@@ -27,7 +28,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
this.newestRuntimes = new(GetNewestRuntimes);
|
||||
}
|
||||
|
||||
[GeneratedRegex(@"^(\S+)\s(\d+\.\d+\.\d+)(-([a-z]+)\.(\d+\.\d+\.\d+))?\s\[(.+)\]$")]
|
||||
[GeneratedRegex(@"^(\S+)\s(\d+\.\d+\.\d+(-[a-z]+\.\d+\.\d+\.\d+)?)\s\[(.+)\]$")]
|
||||
private static partial Regex RuntimeRegex();
|
||||
|
||||
/// <summary>
|
||||
@@ -44,9 +45,9 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
listed.ForEach(r =>
|
||||
{
|
||||
var match = regex.Match(r);
|
||||
if (match.Success)
|
||||
if (match.Success && NuGetVersion.TryParse(match.Groups[2].Value, out var version))
|
||||
{
|
||||
runtimes.AddOrUpdateToLatest(match.Groups[1].Value, new DotNetVersion(match.Groups[6].Value, match.Groups[2].Value, match.Groups[4].Value, match.Groups[5].Value));
|
||||
runtimes.AddOrUpdateToLatest(match.Groups[1].Value, new DotNetVersion(match.Groups[4].Value, version));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using NuGet.Versioning;
|
||||
using Semmle.Util;
|
||||
using Semmle.Util.Logging;
|
||||
|
||||
@@ -27,7 +28,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
cscPath = new Lazy<string?>(GetCscPath);
|
||||
}
|
||||
|
||||
[GeneratedRegex(@"^(\d+\.\d+\.\d+)(-([a-z]+)\.(\d+\.\d+\.\d+))?\s\[(.+)\]$")]
|
||||
[GeneratedRegex(@"^(\d+\.\d+\.\d+(-[a-z]+\.\d+\.\d+\.\d+)?)\s\[(.+)\]$")]
|
||||
private static partial Regex SdkRegex();
|
||||
|
||||
private static HashSet<DotNetVersion> ParseSdks(IList<string> listed)
|
||||
@@ -37,9 +38,9 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
listed.ForEach(r =>
|
||||
{
|
||||
var match = regex.Match(r);
|
||||
if (match.Success)
|
||||
if (match.Success && NuGetVersion.TryParse(match.Groups[1].Value, out var version))
|
||||
{
|
||||
sdks.Add(new DotNetVersion(match.Groups[5].Value, match.Groups[1].Value, match.Groups[3].Value, match.Groups[4].Value));
|
||||
sdks.Add(new DotNetVersion(match.Groups[3].Value, version));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -73,4 +74,4 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
Newtonsoft.Json
|
||||
NuGet.Versioning
|
||||
|
||||
@@ -74,6 +74,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
case SyntaxKind.BaseConstructorInitializer:
|
||||
initializerType = Symbol.ContainingType.BaseType!;
|
||||
ExtractObjectInitCall(trapFile);
|
||||
break;
|
||||
case SyntaxKind.ThisConstructorInitializer:
|
||||
initializerType = Symbol.ContainingType;
|
||||
@@ -90,10 +91,12 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
var primaryInfo = Context.GetSymbolInfo(primaryInitializer);
|
||||
var primarySymbol = primaryInfo.Symbol;
|
||||
|
||||
ExtractObjectInitCall(trapFile);
|
||||
ExtractSourceInitializer(trapFile, primarySymbol?.ContainingType, (IMethodSymbol?)primarySymbol, primaryInitializer.ArgumentList, primaryInitializer.GetLocation());
|
||||
}
|
||||
else if (Symbol.MethodKind is MethodKind.Constructor)
|
||||
{
|
||||
ExtractObjectInitCall(trapFile);
|
||||
var baseType = Symbol.ContainingType.BaseType;
|
||||
if (baseType is null)
|
||||
{
|
||||
@@ -127,6 +130,27 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
}
|
||||
|
||||
private void ExtractObjectInitCall(TextWriter trapFile)
|
||||
{
|
||||
var target = ObjectInitMethod.Create(Context, ContainingType!);
|
||||
|
||||
var type = Context.Compilation.GetSpecialType(SpecialType.System_Void);
|
||||
|
||||
var info = new ExpressionInfo(Context,
|
||||
AnnotatedTypeSymbol.CreateNotAnnotated(type),
|
||||
Location,
|
||||
Kinds.ExprKind.METHOD_INVOCATION,
|
||||
this,
|
||||
-2,
|
||||
isCompilerGenerated: true,
|
||||
null);
|
||||
var obinitCall = new Expression(info);
|
||||
|
||||
trapFile.expr_call(obinitCall, target);
|
||||
|
||||
Expressions.This.CreateImplicit(Context, Symbol.ContainingType, Location, obinitCall, -1);
|
||||
}
|
||||
|
||||
private void ExtractSourceInitializer(TextWriter trapFile, ITypeSymbol? type, IMethodSymbol? symbol, ArgumentListSyntax arguments, Microsoft.CodeAnalysis.Location location)
|
||||
{
|
||||
var initInfo = new ExpressionInfo(Context,
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// Marker interface for method entities.
|
||||
/// </summary>
|
||||
public interface IMethodEntity : IEntity
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ using Semmle.Extraction.CSharp.Populators;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
internal abstract class Method : CachedSymbol<IMethodSymbol>, IExpressionParentEntity, IStatementParentEntity
|
||||
internal abstract class Method : CachedSymbol<IMethodSymbol>, IExpressionParentEntity, IStatementParentEntity, IMethodEntity
|
||||
{
|
||||
protected Method(Context cx, IMethodSymbol init)
|
||||
: base(cx, init) { }
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
using System.IO;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
internal sealed class ObjectInitMethod : CachedEntity, IMethodEntity
|
||||
{
|
||||
private Type ContainingType { get; }
|
||||
|
||||
private ObjectInitMethod(Context cx, Type containingType)
|
||||
: base(cx)
|
||||
{
|
||||
this.ContainingType = containingType;
|
||||
}
|
||||
|
||||
private static readonly string Name = "<object initializer>";
|
||||
|
||||
public static ObjectInitMethod Create(Context cx, Type containingType)
|
||||
{
|
||||
return ObjectInitMethodFactory.Instance.CreateEntity(cx, (typeof(ObjectInitMethod), containingType), containingType);
|
||||
}
|
||||
|
||||
public override void Populate(TextWriter trapFile)
|
||||
{
|
||||
var returnType = Type.Create(Context, Context.Compilation.GetSpecialType(SpecialType.System_Void));
|
||||
|
||||
trapFile.methods(this, Name, ContainingType, returnType.TypeRef, this);
|
||||
|
||||
trapFile.compiler_generated(this);
|
||||
|
||||
trapFile.method_location(this, Context.CreateLocation(ReportingLocation));
|
||||
}
|
||||
|
||||
public override void WriteId(EscapingTextWriter trapFile)
|
||||
{
|
||||
trapFile.WriteSubId(ContainingType);
|
||||
trapFile.Write(".");
|
||||
trapFile.Write(Name);
|
||||
trapFile.Write(";method");
|
||||
}
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location? ReportingLocation => ContainingType.ReportingLocation;
|
||||
|
||||
public override bool NeedsPopulation => true;
|
||||
|
||||
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
|
||||
|
||||
private class ObjectInitMethodFactory : CachedEntityFactory<Type, ObjectInitMethod>
|
||||
{
|
||||
public static ObjectInitMethodFactory Instance { get; } = new ObjectInitMethodFactory();
|
||||
|
||||
public override ObjectInitMethod Create(Context cx, Type containingType) =>
|
||||
new ObjectInitMethod(cx, containingType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,7 +175,7 @@ namespace Semmle.Extraction.CSharp
|
||||
internal static void expr_argument_name(this TextWriter trapFile, Expression expr, string name) =>
|
||||
trapFile.WriteTuple("expr_argument_name", expr, name);
|
||||
|
||||
internal static void expr_call(this TextWriter trapFile, Expression expr, Method target) =>
|
||||
internal static void expr_call(this TextWriter trapFile, Expression expr, IMethodEntity target) =>
|
||||
trapFile.WriteTuple("expr_call", expr, target);
|
||||
|
||||
internal static void expr_flowstate(this TextWriter trapFile, Expression expr, int flowState) =>
|
||||
@@ -247,10 +247,10 @@ namespace Semmle.Extraction.CSharp
|
||||
internal static void localvars(this TextWriter trapFile, LocalVariable key, VariableKind kind, string name, int @var, Type type, Expression expr) =>
|
||||
trapFile.WriteTuple("localvars", key, (int)kind, name, @var, type, expr);
|
||||
|
||||
internal static void method_location(this TextWriter trapFile, Method method, Location location) =>
|
||||
internal static void method_location(this TextWriter trapFile, IMethodEntity method, Location location) =>
|
||||
trapFile.WriteTuple("method_location", method, location);
|
||||
|
||||
internal static void methods(this TextWriter trapFile, Method method, string name, Type declType, Type retType, Method originalDefinition) =>
|
||||
internal static void methods(this TextWriter trapFile, IMethodEntity method, string name, Type declType, Type retType, IMethodEntity originalDefinition) =>
|
||||
trapFile.WriteTuple("methods", method, name, declType, retType, originalDefinition);
|
||||
|
||||
internal static void modifiers(this TextWriter trapFile, Label entity, string modifier) =>
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Semmle.Extraction.Tests
|
||||
private string lastArgs = "";
|
||||
public string WorkingDirectory { get; private set; } = "";
|
||||
public bool Success { get; set; } = true;
|
||||
public int ExitCode { get; set; } = 0;
|
||||
|
||||
public DotNetCliInvokerStub(IList<string> output)
|
||||
{
|
||||
@@ -26,6 +27,12 @@ namespace Semmle.Extraction.Tests
|
||||
return Success;
|
||||
}
|
||||
|
||||
public int RunCommandExitCode(string args, bool silent)
|
||||
{
|
||||
lastArgs = args;
|
||||
return ExitCode;
|
||||
}
|
||||
|
||||
public bool RunCommand(string args, out IList<string> output, bool silent)
|
||||
{
|
||||
lastArgs = args;
|
||||
@@ -83,7 +90,7 @@ namespace Semmle.Extraction.Tests
|
||||
public void TestDotnetInfoFailure()
|
||||
{
|
||||
// Setup
|
||||
var dotnetCliInvoker = new DotNetCliInvokerStub(new List<string>()) { Success = false };
|
||||
var dotnetCliInvoker = new DotNetCliInvokerStub(new List<string>()) { ExitCode = 1 };
|
||||
|
||||
// Execute
|
||||
try
|
||||
@@ -94,7 +101,7 @@ namespace Semmle.Extraction.Tests
|
||||
// Verify
|
||||
catch (Exception e)
|
||||
{
|
||||
Assert.Equal("dotnet --info failed.", e.Message);
|
||||
Assert.Equal("dotnet --info failed with exit code 1.", e.Message);
|
||||
return;
|
||||
}
|
||||
Assert.Fail("Expected exception");
|
||||
|
||||
@@ -7,6 +7,7 @@ strategy: max
|
||||
nuget Basic.CompilerLog.Util 0.9.21
|
||||
nuget Mono.Posix.NETStandard
|
||||
nuget Newtonsoft.Json
|
||||
nuget NuGet.Versioning
|
||||
nuget xunit
|
||||
nuget xunit.runner.visualstudio
|
||||
nuget xunit.runner.utility
|
||||
|
||||
1
csharp/paket.lock
generated
1
csharp/paket.lock
generated
@@ -123,6 +123,7 @@ NUGET
|
||||
System.Collections.Immutable (>= 8.0)
|
||||
NaturalSort.Extension (4.4)
|
||||
Newtonsoft.Json (13.0.4)
|
||||
NuGet.Versioning (7.0.1)
|
||||
System.Buffers (4.6.1)
|
||||
System.Collections.Immutable (9.0.10)
|
||||
System.Composition (9.0.10)
|
||||
|
||||
1
csharp/paket.main.bzl
generated
1
csharp/paket.main.bzl
generated
@@ -38,6 +38,7 @@ def main():
|
||||
{"name": "MSBuild.StructuredLogger", "id": "MSBuild.StructuredLogger", "version": "2.3.71", "sha512": "sha512-u2Tw1WLYy+2VdccrQWyN3AY8zcFj4evfwqWMd7aBiicX3eGfkWkME7lsh9K2XS/+S8KVkjGNPI/g78E2A7Zx0g==", "sources": ["https://api.nuget.org/v3/index.json"], "dependencies": {"net11": [], "net20": [], "net30": [], "net35": [], "net40": [], "net403": [], "net45": [], "net451": [], "net452": [], "net46": [], "net461": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable", "System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net462": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable", "System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net47": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable", "System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net471": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable", "System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net472": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable", "System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net48": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable", "System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net5.0": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable", "System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net6.0": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable", "System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net7.0": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable", "System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net8.0": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable"], "net9.0": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable"], "netcoreapp1.0": [], "netcoreapp1.1": [], "netcoreapp2.0": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable", "System.Memory", "System.Runtime.CompilerServices.Unsafe"], "netcoreapp2.1": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable", "System.Memory", "System.Runtime.CompilerServices.Unsafe"], "netcoreapp2.2": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable", "System.Memory", "System.Runtime.CompilerServices.Unsafe"], "netcoreapp3.0": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable", "System.Memory", "System.Runtime.CompilerServices.Unsafe"], "netcoreapp3.1": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable", "System.Memory", "System.Runtime.CompilerServices.Unsafe"], "netstandard": [], "netstandard1.0": [], "netstandard1.1": [], "netstandard1.2": [], "netstandard1.3": [], "netstandard1.4": [], "netstandard1.5": [], "netstandard1.6": [], "netstandard2.0": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable", "System.Memory", "System.Runtime.CompilerServices.Unsafe"], "netstandard2.1": ["Microsoft.Build.Framework", "Microsoft.Build.Utilities.Core", "System.Collections.Immutable", "System.Memory", "System.Runtime.CompilerServices.Unsafe"]}, "targeting_pack_overrides": [], "framework_list": []},
|
||||
{"name": "NaturalSort.Extension", "id": "NaturalSort.Extension", "version": "4.4.0", "sha512": "sha512-lcwYGJO2xZylcLW6B64tp6wE9UAt6fSn6el8MSAly5+6QG1vc/9uXQz+dsi69q1DxFv2TOaWrrheHNzg4yvy3Q==", "sources": ["https://api.nuget.org/v3/index.json"], "dependencies": {"net11": [], "net20": [], "net30": [], "net35": [], "net40": [], "net403": [], "net45": [], "net451": [], "net452": [], "net46": [], "net461": [], "net462": [], "net47": [], "net471": [], "net472": [], "net48": [], "net5.0": [], "net6.0": [], "net7.0": [], "net8.0": [], "net9.0": [], "netcoreapp1.0": [], "netcoreapp1.1": [], "netcoreapp2.0": [], "netcoreapp2.1": [], "netcoreapp2.2": [], "netcoreapp3.0": [], "netcoreapp3.1": [], "netstandard": [], "netstandard1.0": [], "netstandard1.1": [], "netstandard1.2": [], "netstandard1.3": [], "netstandard1.4": [], "netstandard1.5": [], "netstandard1.6": [], "netstandard2.0": [], "netstandard2.1": []}, "targeting_pack_overrides": [], "framework_list": []},
|
||||
{"name": "Newtonsoft.Json", "id": "Newtonsoft.Json", "version": "13.0.4", "sha512": "sha512-bR+v+E/yJ6g7GV2uXw2OrUSjYYfjLkOLC8JD4kCS23msLapnKtdJPBJA75fwHH++ErIffeIqzYITLxAur4KAXA==", "sources": ["https://api.nuget.org/v3/index.json"], "dependencies": {"net11": [], "net20": [], "net30": [], "net35": [], "net40": [], "net403": [], "net45": [], "net451": [], "net452": [], "net46": [], "net461": [], "net462": [], "net47": [], "net471": [], "net472": [], "net48": [], "net5.0": [], "net6.0": [], "net7.0": [], "net8.0": [], "net9.0": [], "netcoreapp1.0": [], "netcoreapp1.1": [], "netcoreapp2.0": [], "netcoreapp2.1": [], "netcoreapp2.2": [], "netcoreapp3.0": [], "netcoreapp3.1": [], "netstandard": [], "netstandard1.0": [], "netstandard1.1": [], "netstandard1.2": [], "netstandard1.3": [], "netstandard1.4": [], "netstandard1.5": [], "netstandard1.6": [], "netstandard2.0": [], "netstandard2.1": []}, "targeting_pack_overrides": [], "framework_list": []},
|
||||
{"name": "NuGet.Versioning", "id": "NuGet.Versioning", "version": "7.0.1", "sha512": "sha512-ibGcrpgA8foidKNcnf+AQ4zEaVZu4OyWjcPITii6mNgwt2uhd8VFsEq7/Mb0KDxrEJaew+nWJQb7Ju166SAyzw==", "sources": ["https://api.nuget.org/v3/index.json"], "dependencies": {"net11": [], "net20": [], "net30": [], "net35": [], "net40": [], "net403": [], "net45": [], "net451": [], "net452": [], "net46": [], "net461": [], "net462": [], "net47": [], "net471": [], "net472": [], "net48": [], "net5.0": [], "net6.0": [], "net7.0": [], "net8.0": [], "net9.0": [], "netcoreapp1.0": [], "netcoreapp1.1": [], "netcoreapp2.0": [], "netcoreapp2.1": [], "netcoreapp2.2": [], "netcoreapp3.0": [], "netcoreapp3.1": [], "netstandard": [], "netstandard1.0": [], "netstandard1.1": [], "netstandard1.2": [], "netstandard1.3": [], "netstandard1.4": [], "netstandard1.5": [], "netstandard1.6": [], "netstandard2.0": [], "netstandard2.1": []}, "targeting_pack_overrides": [], "framework_list": []},
|
||||
{"name": "System.Buffers", "id": "System.Buffers", "version": "4.6.1", "sha512": "sha512-qve/dFwECwehSWlZmpkrrlIeATCvo/Hw2koyMrUVcDBy5gXAQrnwX8pHEoqgj8DgkrWuWW1DrQbFqoMbo+Fvrg==", "sources": ["https://api.nuget.org/v3/index.json"], "dependencies": {"net11": [], "net20": [], "net30": [], "net35": [], "net40": [], "net403": [], "net45": [], "net451": [], "net452": [], "net46": [], "net461": [], "net462": [], "net47": [], "net471": [], "net472": [], "net48": [], "net5.0": [], "net6.0": [], "net7.0": [], "net8.0": [], "net9.0": [], "netcoreapp1.0": [], "netcoreapp1.1": [], "netcoreapp2.0": [], "netcoreapp2.1": [], "netcoreapp2.2": [], "netcoreapp3.0": [], "netcoreapp3.1": [], "netstandard": [], "netstandard1.0": [], "netstandard1.1": [], "netstandard1.2": [], "netstandard1.3": [], "netstandard1.4": [], "netstandard1.5": [], "netstandard1.6": [], "netstandard2.0": [], "netstandard2.1": []}, "targeting_pack_overrides": [], "framework_list": []},
|
||||
{"name": "System.Collections.Immutable", "id": "System.Collections.Immutable", "version": "9.0.10", "sha512": "sha512-00LI4a7blU063Z0lCdRVLlh0Mzl1yYLZaxlOZe0MiNH+TELklX0Mne/XKU7UuCZQQh6FHrcEUPDjxIsy2jZUxg==", "sources": ["https://api.nuget.org/v3/index.json"], "dependencies": {"net11": [], "net20": [], "net30": [], "net35": [], "net40": [], "net403": [], "net45": [], "net451": [], "net452": [], "net46": [], "net461": ["System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net462": ["System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net47": ["System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net471": ["System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net472": ["System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net48": ["System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net5.0": ["System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net6.0": ["System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net7.0": ["System.Memory", "System.Runtime.CompilerServices.Unsafe"], "net8.0": [], "net9.0": [], "netcoreapp1.0": [], "netcoreapp1.1": [], "netcoreapp2.0": ["System.Memory", "System.Runtime.CompilerServices.Unsafe"], "netcoreapp2.1": ["System.Memory", "System.Runtime.CompilerServices.Unsafe"], "netcoreapp2.2": ["System.Memory", "System.Runtime.CompilerServices.Unsafe"], "netcoreapp3.0": ["System.Memory", "System.Runtime.CompilerServices.Unsafe"], "netcoreapp3.1": ["System.Memory", "System.Runtime.CompilerServices.Unsafe"], "netstandard": [], "netstandard1.0": [], "netstandard1.1": [], "netstandard1.2": [], "netstandard1.3": [], "netstandard1.4": [], "netstandard1.5": [], "netstandard1.6": [], "netstandard2.0": ["System.Memory", "System.Runtime.CompilerServices.Unsafe"], "netstandard2.1": ["System.Memory", "System.Runtime.CompilerServices.Unsafe"]}, "targeting_pack_overrides": [], "framework_list": []},
|
||||
{"name": "System.Composition", "id": "System.Composition", "version": "9.0.10", "sha512": "sha512-PyUH0f6tdjlQBntP/73cqaR53fjAZkaqGRatIi1BgZIfQH/Z0k1rPHaklBZqFV5+wKUkL74+49TrFPnB/zw+2Q==", "sources": ["https://api.nuget.org/v3/index.json"], "dependencies": {"net11": [], "net20": [], "net30": [], "net35": [], "net40": [], "net403": [], "net45": [], "net451": [], "net452": [], "net46": [], "net461": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "net462": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "net47": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "net471": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "net472": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "net48": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "net5.0": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "net6.0": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "net7.0": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "net8.0": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "net9.0": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "netcoreapp1.0": [], "netcoreapp1.1": [], "netcoreapp2.0": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "netcoreapp2.1": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "netcoreapp2.2": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "netcoreapp3.0": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "netcoreapp3.1": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "netstandard": [], "netstandard1.0": [], "netstandard1.1": [], "netstandard1.2": [], "netstandard1.3": [], "netstandard1.4": [], "netstandard1.5": [], "netstandard1.6": [], "netstandard2.0": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"], "netstandard2.1": ["System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Hosting", "System.Composition.Runtime", "System.Composition.TypedParts"]}, "targeting_pack_overrides": [], "framework_list": []},
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
## 1.7.54
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.7.53
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.7.52
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user