Compare commits

..

1 Commits

Author SHA1 Message Date
Paolo Tranquilli
b2d9c58db9 Actions: improve improper access control query
Closes: https://github.com/github/codeql/issues/20706
2025-11-25 08:46:10 +01:00
2541 changed files with 116567 additions and 189016 deletions

View File

@@ -1 +1 @@
8.4.2
8.1.1

View File

@@ -40,8 +40,3 @@ updates:
- dependency-name: "*"
reviewers:
- "github/codeql-go"
- package-ecosystem: bazel
directory: "/"
schedule:
interval: weekly

View File

@@ -34,7 +34,7 @@ jobs:
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.100
dotnet-version: 9.0.300
- name: Checkout repository
uses: actions/checkout@v5

View File

@@ -43,14 +43,14 @@ jobs:
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.100
dotnet-version: 9.0.300
- name: Extractor unit tests
run: |
dotnet tool restore
dotnet test -p:RuntimeFrameworkVersion=10.0.0 extractor/Semmle.Util.Tests
dotnet test -p:RuntimeFrameworkVersion=10.0.0 extractor/Semmle.Extraction.Tests
dotnet test -p:RuntimeFrameworkVersion=10.0.0 autobuilder/Semmle.Autobuild.CSharp.Tests
dotnet test -p:RuntimeFrameworkVersion=10.0.0 autobuilder/Semmle.Autobuild.Cpp.Tests
dotnet test -p:RuntimeFrameworkVersion=9.0.5 extractor/Semmle.Util.Tests
dotnet test -p:RuntimeFrameworkVersion=9.0.5 extractor/Semmle.Extraction.Tests
dotnet test -p:RuntimeFrameworkVersion=9.0.5 autobuilder/Semmle.Autobuild.CSharp.Tests
dotnet test -p:RuntimeFrameworkVersion=9.0.5 autobuilder/Semmle.Autobuild.Cpp.Tests
shell: bash
stubgentest:
runs-on: ubuntu-latest

View File

@@ -23,10 +23,10 @@ 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 = "12.1.0-codeql.1")
bazel_dep(name = "fmt", version = "10.0.0")
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.21.5-codeql.1")
bazel_dep(name = "rules_dotnet", version = "0.19.2-codeql.1")
bazel_dep(name = "googletest", version = "1.14.0.bcr.1")
bazel_dep(name = "rules_rust", version = "0.66.0")
bazel_dep(name = "zstd", version = "1.5.5.bcr.1")
@@ -172,7 +172,7 @@ http_archive(
)
dotnet = use_extension("@rules_dotnet//dotnet:extensions.bzl", "dotnet")
dotnet.toolchain(dotnet_version = "10.0.100")
dotnet.toolchain(dotnet_version = "9.0.300")
use_repo(dotnet, "dotnet_toolchains")
register_toolchains("@dotnet_toolchains//:all")
@@ -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 = "71482d7a7e4ea9176d5596161c49250c34b136b157c45f632b1111323fbfc0de",
sha256_macos_arm = "604194ab13f0aba3972995d995f11002b8fc285c8170401fcd46655065df20c9",
sha256_macos_intel = "65367b94fd579d93d46f2d2595cc4c9a60cfcf497e3c824f9d1a7b80fa8bd38a",
sha256_windows = "ac3874075def2b9e5074a3b5945005ab082cc6e689e1de658da8965bc23e643e",
version = "2.0.4",
sha256_linux = "ee0e8a957687a5dc3a66b2a4b25883bf762df4c9c07f0651af527a32a405054b",
sha256_macos_arm = "8a88eea54eac232d162a72a42065e0429b82dbf4f05e9642915dff9d7a81f846",
sha256_macos_intel = "4457a18bfcc5feabe09f5ea3d1157128e07b4873392cb404a870e611924abf64",
sha256_windows = "66d0c1375301bf5ab815348048f43b110631d3fa7200acd50d50a8ed8655ca62",
version = "2.0.3",
)
register_toolchains(

View File

@@ -1,19 +1,3 @@
## 0.4.25
No user-facing changes.
## 0.4.24
No user-facing changes.
## 0.4.23
No user-facing changes.
## 0.4.22
No user-facing changes.
## 0.4.21
No user-facing changes.

View File

@@ -1,4 +0,0 @@
---
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`.

View File

@@ -1,3 +0,0 @@
## 0.4.22
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 0.4.23
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 0.4.24
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 0.4.25
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.4.25
lastReleaseVersion: 0.4.21

View File

@@ -19,7 +19,12 @@ 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
not isGithubScriptUsingToJson(sink.asExpr())
// 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(), _))
)
}
/**
@@ -86,38 +91,3 @@ 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(), _))
)
}

View File

@@ -1,5 +1,5 @@
name: codeql/actions-all
version: 0.4.26-dev
version: 0.4.22-dev
library: true
warnOnImplicitThis: true
dependencies:

View File

@@ -1,19 +1,3 @@
## 0.6.17
No user-facing changes.
## 0.6.16
No user-facing changes.
## 0.6.15
No user-facing changes.
## 0.6.14
No user-facing changes.
## 0.6.13
No user-facing changes.

View File

@@ -20,7 +20,10 @@ import CodeInjectionFlow::PathGraph
import codeql.actions.security.ControlChecks
from CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink, Event event
where criticalSeverityCodeInjection(source, sink, event)
where
CodeInjectionFlow::flowPath(source, sink) and
event = getRelevantCriticalEventForSink(sink.getNode()) and
source.getNode().(RemoteFlowSource).getEventName() = event.getName()
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()

View File

@@ -19,7 +19,15 @@ import codeql.actions.security.CodeInjectionQuery
import CodeInjectionFlow::PathGraph
from CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink
where mediumSeverityCodeInjection(source, 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(), _))
)
select sink.getNode(), source, sink,
"Potential code injection in $@, which may be controlled by an external user.", sink,
sink.getNode().asExpr().(Expression).getRawExpression()

View File

@@ -2,8 +2,6 @@
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.

View File

@@ -14,7 +14,7 @@
import codeql.actions.security.UntrustedCheckoutQuery
import codeql.actions.security.ControlChecks
from LocalJob job, LabelCheck check, MutableRefCheckoutStep checkout, Event event
from LocalJob job, LabelCheck check, PRHeadCheckoutStep checkout, Event event
where
job.isPrivileged() and
job.getAStep() = checkout and
@@ -25,6 +25,8 @@ where
event.getAnActivityType() = "synchronize"
or
not exists(job.getATriggerEvent())
or
checkout instanceof MutableRefCheckoutStep
)
select checkout, "The checked-out code can be modified after the authorization check $@.", check,
check.toString()

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* The `actions/improper-access-control` query has been improved to correctly detect cases where either the check
triggers or the checkout reference are unsafe, rather than only when both applied as was done previously.

View File

@@ -1,3 +0,0 @@
## 0.6.14
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 0.6.15
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 0.6.16
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 0.6.17
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.6.17
lastReleaseVersion: 0.6.13

View File

@@ -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

View File

@@ -1,5 +1,5 @@
name: codeql/actions-queries
version: 0.6.18-dev
version: 0.6.14-dev
library: false
warnOnImplicitThis: true
groups: [actions, queries]

View File

@@ -1,18 +0,0 @@
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 }}'

View File

@@ -435,16 +435,6 @@ 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 |

View File

@@ -435,16 +435,6 @@ 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 |
@@ -729,16 +719,6 @@ 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 }} |
@@ -749,10 +729,6 @@ 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 }} |

View File

@@ -16,5 +16,5 @@ jobs:
uses: actions/checkout@v3
if: contains(github.event.pull_request.labels.*.name, 'safe to test')
with:
ref: ${{ github.event.pull_request.head.ref }}
ref: ${{ github.event.pull_request.head.ref }} # BAD (mutable ref)
- run: ./cmd

View File

@@ -16,5 +16,5 @@ jobs:
uses: actions/checkout@v3
if: contains(github.event.pull_request.labels.*.name, 'safe to test')
with:
ref: ${{ github.event.pull_request.head.ref }}
ref: ${{ github.event.pull_request.head.sha }} # BAD (bad trigger)
- run: ./cmd

View File

@@ -0,0 +1,20 @@
name: Pull request feedback
on:
pull_request_target:
types: [ labeled ]
permissions: {}
jobs:
test:
permissions:
contents: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Checkout repo for OWNER TEST
uses: actions/checkout@v3
if: contains(github.event.pull_request.labels.*.name, 'safe to test')
with:
ref: ${{ github.event.pull_request.head.sha }} # GOOD (labeled event + immutable ref)
- run: ./cmd

View File

@@ -1 +1,2 @@
| .github/workflows/test1.yml:15:7:20:4 | Uses Step | The checked-out code can be modified after the authorization check $@. | .github/workflows/test1.yml:17:11:17:75 | contain ... test') | contain ... test') |
| .github/workflows/bad_checkout.yml:15:7:20:4 | Uses Step | The checked-out code can be modified after the authorization check $@. | .github/workflows/bad_checkout.yml:17:11:17:75 | contain ... test') | contain ... test') |
| .github/workflows/bad_triggers.yml:15:7:20:4 | Uses Step | The checked-out code can be modified after the authorization check $@. | .github/workflows/bad_triggers.yml:17:11:17:75 | contain ... test') | contain ... test') |

View File

@@ -276,13 +276,5 @@
"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",
"cpp/ql/lib/semmle/code/cpp/internal/OverlayXml.qll"
]
}

View File

@@ -1,21 +1,3 @@
## 6.1.4
No user-facing changes.
## 6.1.3
No user-facing changes.
## 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

View File

@@ -1,5 +1,4 @@
## 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`.
---
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`.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* Some constants will now be represented by their unfolded expression trees. The `isConstant` predicate of `Expr` will no longer yield a result for those constants.

View File

@@ -1,3 +0,0 @@
## 6.1.2
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 6.1.3
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 6.1.4
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 6.1.4
lastReleaseVersion: 6.1.0

View File

@@ -74,4 +74,3 @@ import semmle.code.cpp.Preprocessor
import semmle.code.cpp.Iteration
import semmle.code.cpp.NameQualifiers
import DefaultOptions
private import semmle.code.cpp.internal.Overlay

View File

@@ -9,14 +9,6 @@ extensions:
pack: codeql/cpp-all
extensible: sinkModel
data: []
- addsTo:
pack: codeql/cpp-all
extensible: barrierModel
data: []
- addsTo:
pack: codeql/cpp-all
extensible: barrierGuardModel
data: []
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 6.1.5-dev
version: 6.1.1-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

View File

@@ -15,17 +15,16 @@
* reading.
* 1. The `namespace` column selects a namespace.
* 2. The `type` column selects a type within that namespace. This column can
* introduce template type names that can be mentioned in the `signature` column.
* introduce template names that can be mentioned in the `signature` column.
* For example, `vector<T,Allocator>` introduces the template names `T` and
* `Allocator`. Non-type template parameters cannot be specified.
* `Allocator`.
* 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 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.
* 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`.
* 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
@@ -101,10 +100,9 @@ private import internal.FlowSummaryImpl
private import internal.FlowSummaryImpl::Public
private import internal.FlowSummaryImpl::Private
private import internal.FlowSummaryImpl::Private::External
private import internal.ExternalFlowExtensions::Extensions as Extensions
private import internal.ExternalFlowExtensions as Extensions
private import codeql.mad.ModelValidation as SharedModelVal
private import codeql.util.Unit
private import codeql.mad.static.ModelsAsData as SharedMaD
/**
* A unit class for adding additional source model rows.
@@ -145,81 +143,134 @@ predicate sinkModel(string row) { any(SinkModelCsv s).row(row) }
/** Holds if `row` is a summary model. */
predicate summaryModel(string row) { any(SummaryModelCsv s).row(row) }
private module MadInput implements SharedMaD::InputSig {
/** Holds if a source model exists for the given parameters. */
predicate additionalSourceModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string output, string kind, string provenance, string model
) {
exists(string row |
sourceModel(row) and
row.splitAt(";", 0) = namespace and
row.splitAt(";", 1) = type and
row.splitAt(";", 2) = subtypes.toString() and
subtypes = [true, false] and
row.splitAt(";", 3) = name and
row.splitAt(";", 4) = signature and
row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = output and
row.splitAt(";", 7) = kind
) and
provenance = "manual" and
model = ""
}
/** Holds if a sink model exists for the given parameters. */
predicate additionalSinkModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string kind, string provenance, string model
) {
exists(string row |
sinkModel(row) and
row.splitAt(";", 0) = namespace and
row.splitAt(";", 1) = type and
row.splitAt(";", 2) = subtypes.toString() and
subtypes = [true, false] and
row.splitAt(";", 3) = name and
row.splitAt(";", 4) = signature and
row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = input and
row.splitAt(";", 7) = kind
) and
provenance = "manual" and
model = ""
}
/**
* Holds if a summary model exists for the given parameters.
*
* This predicate does not expand `@` to `*`s.
*/
predicate additionalSummaryModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string output, string kind, string provenance, string model
) {
exists(string row |
summaryModel(row) and
row.splitAt(";", 0) = namespace and
row.splitAt(";", 1) = type and
row.splitAt(";", 2) = subtypes.toString() and
subtypes = [true, false] and
row.splitAt(";", 3) = name and
row.splitAt(";", 4) = signature and
row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = input and
row.splitAt(";", 7) = output and
row.splitAt(";", 8) = kind
) and
provenance = "manual" and
model = ""
}
string namespaceSegmentSeparator() { result = "::" }
/** Holds if a source model exists for the given parameters. */
predicate sourceModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string output, string kind, string provenance, string model
) {
exists(string row |
sourceModel(row) and
row.splitAt(";", 0) = namespace and
row.splitAt(";", 1) = type and
row.splitAt(";", 2) = subtypes.toString() and
subtypes = [true, false] and
row.splitAt(";", 3) = name and
row.splitAt(";", 4) = signature and
row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = output and
row.splitAt(";", 7) = kind
) and
provenance = "manual" and
model = ""
or
exists(QlBuiltins::ExtensionId madId |
Extensions::sourceModel(namespace, type, subtypes, name, signature, ext, output, kind,
provenance, madId) and
model = "MaD:" + madId.toString()
)
}
private module MaD = SharedMaD::ModelsAsData<Extensions, MadInput>;
/** Holds if a sink model exists for the given parameters. */
predicate sinkModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string kind, string provenance, string model
) {
exists(string row |
sinkModel(row) and
row.splitAt(";", 0) = namespace and
row.splitAt(";", 1) = type and
row.splitAt(";", 2) = subtypes.toString() and
subtypes = [true, false] and
row.splitAt(";", 3) = name and
row.splitAt(";", 4) = signature and
row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = input and
row.splitAt(";", 7) = kind
) and
provenance = "manual" and
model = ""
or
exists(QlBuiltins::ExtensionId madId |
Extensions::sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance,
madId) and
model = "MaD:" + madId.toString()
)
}
import MaD
/**
* Holds if a summary model exists for the given parameters.
*
* This predicate does not expand `@` to `*`s.
*/
private predicate summaryModel0(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string output, string kind, string provenance, string model
) {
exists(string row |
summaryModel(row) and
row.splitAt(";", 0) = namespace and
row.splitAt(";", 1) = type and
row.splitAt(";", 2) = subtypes.toString() and
subtypes = [true, false] and
row.splitAt(";", 3) = name and
row.splitAt(";", 4) = signature and
row.splitAt(";", 5) = ext and
row.splitAt(";", 6) = input and
row.splitAt(";", 7) = output and
row.splitAt(";", 8) = kind
) and
provenance = "manual" and
model = ""
or
exists(QlBuiltins::ExtensionId madId |
Extensions::summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind,
provenance, madId) and
model = "MaD:" + madId.toString()
)
}
/**
* Holds if the given extension tuple `madId` should pretty-print as `model`.
*
* This predicate should only be used in tests.
*/
predicate interpretModelForTest(QlBuiltins::ExtensionId madId, string model) {
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string output, string kind, string provenance
|
Extensions::sourceModel(namespace, type, subtypes, name, signature, ext, output, kind,
provenance, madId)
|
model =
"Source: " + namespace + "; " + type + "; " + subtypes + "; " + name + "; " + signature + "; "
+ ext + "; " + output + "; " + kind + "; " + provenance
)
or
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string kind, string provenance
|
Extensions::sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance,
madId)
|
model =
"Sink: " + namespace + "; " + type + "; " + subtypes + "; " + name + "; " + signature + "; " +
ext + "; " + input + "; " + kind + "; " + provenance
)
or
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string output, string kind, string provenance
|
Extensions::summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind,
provenance, madId)
|
model =
"Summary: " + namespace + "; " + type + "; " + subtypes + "; " + name + "; " + signature +
"; " + ext + "; " + input + "; " + output + "; " + kind + "; " + provenance
)
}
/**
* Holds if `input` is `input0`, but with all occurrences of `@` replaced
@@ -242,13 +293,69 @@ predicate summaryModel(
string input, string output, string kind, string provenance, string model
) {
exists(string input0, string output0 |
MaD::summaryModel(namespace, type, subtypes, name, signature, ext, input0, output0, kind,
summaryModel0(namespace, type, subtypes, name, signature, ext, input0, output0, kind,
provenance, model) and
expandInputAndOutput(input0, input, output0, output,
[0 .. Private::getMaxElementContentIndirectionIndex() - 1])
)
}
private predicate relevantNamespace(string namespace) {
sourceModel(namespace, _, _, _, _, _, _, _, _, _) or
sinkModel(namespace, _, _, _, _, _, _, _, _, _) or
summaryModel(namespace, _, _, _, _, _, _, _, _, _, _)
}
private predicate namespaceLink(string shortns, string longns) {
relevantNamespace(shortns) and
relevantNamespace(longns) and
longns.prefix(longns.indexOf("::")) = shortns
}
private predicate canonicalNamespace(string namespace) {
relevantNamespace(namespace) and not namespaceLink(_, namespace)
}
private predicate canonicalNamespaceLink(string namespace, string subns) {
canonicalNamespace(namespace) and
(subns = namespace or namespaceLink(namespace, subns))
}
/**
* Holds if MaD framework coverage of `namespace` is `n` api endpoints of the
* kind `(kind, part)`, and `namespaces` is the number of subnamespaces of
* `namespace` which have MaD framework coverage (including `namespace`
* itself).
*/
predicate modelCoverage(string namespace, int namespaces, string kind, string part, int n) {
namespaces = strictcount(string subns | canonicalNamespaceLink(namespace, subns)) and
(
part = "source" and
n =
strictcount(string subns, string type, boolean subtypes, string name, string signature,
string ext, string output, string provenance, string model |
canonicalNamespaceLink(namespace, subns) and
sourceModel(subns, type, subtypes, name, signature, ext, output, kind, provenance, model)
)
or
part = "sink" and
n =
strictcount(string subns, string type, boolean subtypes, string name, string signature,
string ext, string input, string provenance, string model |
canonicalNamespaceLink(namespace, subns) and
sinkModel(subns, type, subtypes, name, signature, ext, input, kind, provenance, model)
)
or
part = "summary" and
n =
strictcount(string subns, string type, boolean subtypes, string name, string signature,
string ext, string input, string output, string provenance |
canonicalNamespaceLink(namespace, subns) and
summaryModel(subns, type, subtypes, name, signature, ext, input, output, kind, provenance, _)
)
)
}
/** Provides a query predicate to check the CSV data for validation errors. */
module CsvValidation {
private string getInvalidModelInput() {
@@ -526,28 +633,6 @@ 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).
@@ -555,41 +640,18 @@ private Locatable getSupportedFunctionTemplateArgument(Function templateFunction
private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remaining) {
exists(Function templateFunction |
templateFunction = getFullyTemplatedFunction(f) and
remaining = getNumberOfSupportedFunctionTemplateArguments(templateFunction) and
remaining = templateFunction.getNumberOfTemplateArguments() 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 = getSupportedFunctionTemplateArgument(templateFunction, remaining)
|
tp = templateFunction.getTemplateArgument(remaining) and
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).
@@ -599,7 +661,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 = getNumberOfSupportedClassTemplateArguments(template) and
remaining = template.getNumberOfTemplateArguments() and
result = getTypeNameWithoutFunctionTemplates(f, n, 0)
)
or
@@ -611,8 +673,7 @@ 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 = getSupportedClassTemplateArgument(template, remaining)
|
tp = template.getTemplateArgument(remaining) and
result = mid.replaceAll(tp.getName(), "class:" + remaining.toString())
)
}

View File

@@ -2,8 +2,6 @@
* This module provides extensible predicates for defining MaD models.
*/
private import codeql.mad.static.ModelsAsData as SharedMaD
/**
* Holds if an external source model exists for the given parameters.
*/
@@ -20,22 +18,6 @@ extensible predicate sinkModel(
string input, string kind, string provenance, QlBuiltins::ExtensionId madId
);
/**
* Holds if a barrier model exists for the given parameters.
*/
extensible predicate barrierModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string output, string kind, string provenance, QlBuiltins::ExtensionId madId
);
/**
* Holds if a barrier guard model exists for the given parameters.
*/
extensible predicate barrierGuardModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string acceptingvalue, string kind, string provenance, QlBuiltins::ExtensionId madId
);
/**
* Holds if an external summary model exists for the given parameters.
*/
@@ -43,16 +25,3 @@ extensible predicate summaryModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string output, string kind, string provenance, QlBuiltins::ExtensionId madId
);
/**
* Holds if a neutral model exists for the given parameters.
*/
extensible predicate neutralModel(
string namespace, string type, string name, string signature, string kind, string provenance
);
module Extensions implements SharedMaD::ExtensionsSig {
import ExternalFlowExtensions
predicate namespaceGrouping(string group, string namespace) { none() }
}

View File

@@ -148,19 +148,6 @@ module SourceSinkInterpretationInput implements
)
}
predicate barrierElement(
Element n, string output, string kind, Public::Provenance provenance, string model
) {
none()
}
predicate barrierGuardElement(
Element n, string input, Public::AcceptingValue acceptingvalue, string kind,
Public::Provenance provenance, string model
) {
none()
}
private newtype TInterpretNode =
TElement_(Element n) or
TNode_(Node n)

View File

@@ -1,80 +0,0 @@
/**
* Defines entity discard predicates for C++ overlay analysis.
*/
private import OverlayXml
/**
* 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) {
exists(@location_default loc |
var_decls(e, _, _, _, loc)
or
fun_decls(e, _, _, _, loc)
or
type_decls(e, _, loc)
or
namespace_decls(e, _, loc, _)
or
macroinvocations(e, _, loc, _)
or
preprocdirects(e, _, loc)
|
result = getLocationFilePath(loc)
)
}
/**
* Gets the file path for an element with potentially multiple locations.
*/
overlay[local]
private string getMultiLocationFilePath(@element e) {
exists(@location_default loc |
exists(@var_decl vd | var_decls(vd, e, _, _, loc))
or
exists(@fun_decl fd | fun_decls(fd, e, _, _, loc))
or
exists(@type_decl td | type_decls(td, e, loc))
or
exists(@namespace_decl nd | namespace_decls(nd, e, loc, _))
|
result = getLocationFilePath(loc)
)
}
/**
* 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))
)
}

View File

@@ -1,46 +0,0 @@
overlay[local]
module;
/**
* A local predicate that always holds for the overlay variant and never holds for the base variant.
* This is used to define local predicates that behave differently for the base and overlay variant.
*/
private predicate isOverlay() { databaseMetadata("isOverlay", "true") }
private string getXmlFile(@xmllocatable locatable) {
exists(@location_default location, @file file | xmllocations(locatable, location) |
locations_default(location, file, _, _, _, _) and
files(file, result)
)
}
private string getXmlFileInBase(@xmllocatable locatable) {
not isOverlay() and
result = getXmlFile(locatable)
}
/**
* Holds if the given `file` was extracted as part of the overlay and was extracted by the HTML/XML
* extractor.
*/
private predicate overlayXmlExtracted(string file) {
isOverlay() and
exists(@xmllocatable locatable |
not files(locatable, _) and not xmlNs(locatable, _, _, _) and file = getXmlFile(locatable)
)
}
/**
* Holds if the given XML `locatable` should be discarded, because it is part of the overlay base
* and is in a file that was also extracted as part of the overlay database.
*/
overlay[discard_entity]
private predicate discardXmlLocatable(@xmllocatable locatable) {
exists(string file | file = getXmlFileInBase(locatable) |
overlayChangedFiles(file)
or
// The HTML/XML extractor is currently not incremental and may extract more files than those
// included in overlayChangedFiles.
overlayXmlExtracted(file)
)
}

View File

@@ -2078,151 +2078,38 @@ 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(CanonicalField f) { result = max(f.getAType().getSize()) }
private int getFieldSize(Field f) { result = f.getType().getSize() }
/**
* Gets a field in the union `u` whose size
* is `bytes` number of bytes.
*/
private CanonicalField getAFieldWithSize(CanonicalUnion u, int bytes) {
result = u.getACanonicalField() and
private Field getAFieldWithSize(Union u, int bytes) {
result = u.getAField() and
bytes = getFieldSize(result)
}
cached
private newtype TContent =
TNonUnionContent(CanonicalField f, int indirectionIndex) {
TNonUnionContent(Field 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 .. max(SsaImpl::getMaxIndirectionsForType(f.getAnUnspecifiedType()))] and
indirectionIndex = [1 .. SsaImpl::getMaxIndirectionsForType(f.getUnspecifiedType())] and
// Reads and writes of union fields are tracked using `UnionContent`.
not f.getDeclaringType() instanceof Union
} or
TUnionContent(CanonicalUnion u, int bytes, int indirectionIndex) {
exists(CanonicalField f |
f = u.getACanonicalField() and
TUnionContent(Union u, int bytes, int indirectionIndex) {
exists(Field f |
f = u.getAField() 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)
.getAnUnspecifiedType())
.getUnspecifiedType())
)]
)
} or
@@ -2288,12 +2175,8 @@ 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.
*/
Field getField() { none() } // overridden in subclasses
final Field getField() { result = unique( | | this.getAField()) }
override int getIndirectionIndex() { none() } // overridden in subclasses
@@ -2304,33 +2187,32 @@ class FieldContent extends Content, TFieldContent {
/** A reference through a non-union instance field. */
class NonUnionFieldContent extends FieldContent, TNonUnionContent {
private CanonicalField f;
private Field f;
private int indirectionIndex;
NonUnionFieldContent() { this = TNonUnionContent(f, indirectionIndex) }
override string toString() { result = contentStars(this) + f.toString() }
final override Field getField() { result = f.getAField() }
override Field getAField() { result = this.getField() }
override Field getAField() { result = f }
/** Gets the indirection index of this `FieldContent`. */
override int getIndirectionIndex() { result = indirectionIndex }
override predicate impliesClearOf(Content c) {
exists(int i |
c = TNonUnionContent(f, i) and
exists(FieldContent fc |
fc = c and
fc.getField() = f and
// If `this` is `f` then `c` is cleared if it's of the
// form `*f`, `**f`, etc.
i >= indirectionIndex
fc.getIndirectionIndex() >= indirectionIndex
)
}
}
/** A reference through an instance field of a union. */
class UnionContent extends FieldContent, TUnionContent {
private CanonicalUnion u;
private Union u;
private int indirectionIndex;
private int bytes;
@@ -2338,31 +2220,24 @@ 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() {
exists(CanonicalField cf |
cf = u.getACanonicalField() and
result = cf.getAField() and
getFieldSize(cf) = bytes
)
}
override Field getAField() { result = u.getAField() and getFieldSize(result) = bytes }
/** Gets the underlying union of this `UnionContent`. */
Union getUnion() { result = u.getAUnion() }
Union getUnion() { result = u }
/** Gets the indirection index of this `UnionContent`. */
override int getIndirectionIndex() { result = indirectionIndex }
override predicate impliesClearOf(Content c) {
exists(int i |
c = TUnionContent(u, _, i) and
exists(UnionContent uc |
uc = c and
uc.getUnion() = u 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).
i >= indirectionIndex
uc.getIndirectionIndex() >= indirectionIndex
)
}
}

View File

@@ -1051,12 +1051,12 @@ module BarrierGuardWithIntParam<guardChecksNodeSig/4 guardChecksNode> {
}
private predicate guardChecksInstr(
IRGuards::Guards_v1::Guard g, IRGuards::GuardsInput::Expr instr, IRGuards::GuardValue gv,
IRGuards::Guards_v1::Guard g, IRGuards::GuardsInput::Expr instr, boolean branch,
int indirectionIndex
) {
exists(Node node |
nodeHasInstruction(node, instr, indirectionIndex) and
guardChecksNode(g, node, gv.asBooleanValue(), indirectionIndex)
guardChecksNode(g, node, branch, indirectionIndex)
)
}
@@ -1064,8 +1064,8 @@ module BarrierGuardWithIntParam<guardChecksNodeSig/4 guardChecksNode> {
DataFlowIntegrationInput::Guard g, SsaImpl::Definition def, IRGuards::GuardValue val,
int indirectionIndex
) {
IRGuards::Guards_v1::ParameterizedValidationWrapper<int, guardChecksInstr/4>::guardChecksDef(g,
def, val, indirectionIndex)
IRGuards::Guards_v1::ValidationWrapperWithState<int, guardChecksInstr/4>::guardChecksDef(g, def,
val, indirectionIndex)
}
Node getABarrierNode(int indirectionIndex) {

View File

@@ -688,9 +688,15 @@ private module Cached {
conversionFlow(mid, instr, false, _)
)
or
exists(Operand address |
isDereference(operand.getDef(), address, _) and
isUseImpl(address, base, ind - 1)
exists(int ind0 |
exists(Operand address |
isDereference(operand.getDef(), address, _) and
isUseImpl(address, base, ind0)
)
or
isUseImpl(operand.getDef().(InitializeParameterInstruction).getAnOperand(), base, ind0)
|
ind0 = ind - 1
)
}

View File

@@ -2679,7 +2679,7 @@ class TranslatedDestructorFieldDestruction extends TranslatedNonConstantExpr, St
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
tag = OnlyInstructionTag() and
operandTag instanceof UnaryOperandTag and
result = getTranslatedFunction(getEnclosingFunction(expr)).getLoadThisInstruction()
result = getTranslatedFunction(getEnclosingFunction(expr)).getInitializeThisInstruction()
}
final override Field getInstructionField(InstructionTag tag) {

View File

@@ -306,11 +306,11 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
final predicate hasReturnValue() { hasReturnValue(func) }
/**
* Gets the first load of `this` for this function. Holds only if the function
* is an instance member function, constructor, or destructor.
* Gets the single `InitializeThis` instruction for this function. Holds only
* if the function is an instance member function, constructor, or destructor.
*/
final Instruction getLoadThisInstruction() {
result = getTranslatedThisParameter(func).getInstruction(InitializerIndirectAddressTag())
final Instruction getInitializeThisInstruction() {
result = getTranslatedThisParameter(func).getInstruction(InitializerStoreTag())
}
/**
@@ -639,7 +639,7 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
}
override Instruction getTargetAddress() {
result = getTranslatedFunction(func).getLoadThisInstruction()
result = getTranslatedFunction(func).getInitializeThisInstruction()
}
override Type getTargetType() { result = getTranslatedFunction(func).getThisType() }

View File

@@ -950,7 +950,7 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
tag = OnlyInstructionTag() and
operandTag instanceof UnaryOperandTag and
result = getTranslatedFunction(this.getFunction()).getLoadThisInstruction()
result = getTranslatedFunction(this.getFunction()).getInitializeThisInstruction()
}
final override predicate getInstructionInheritance(
@@ -1000,7 +1000,7 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC
}
final override Instruction getReceiver() {
result = getTranslatedFunction(this.getFunction()).getLoadThisInstruction()
result = getTranslatedFunction(this.getFunction()).getInitializeThisInstruction()
}
}

View File

@@ -158,6 +158,22 @@ private class UnsignedBitwiseAndExpr extends BitwiseAndExpr {
}
}
/**
* Gets the floor of `v`, with additional logic to work around issues with
* large numbers.
*/
bindingset[v]
float safeFloor(float v) {
// return the floor of v
v.abs() < 2.pow(31) and
result = v.floor()
or
// `floor()` doesn't work correctly on large numbers (since it returns an integer),
// so fall back to unrounded numbers at this scale.
not v.abs() < 2.pow(31) and
result = v
}
/** A `MulExpr` where exactly one operand is constant. */
private class MulByConstantExpr extends MulExpr {
float constant;
@@ -1250,7 +1266,7 @@ private float getLowerBoundsImpl(Expr expr) {
rsExpr = expr and
left = getFullyConvertedLowerBounds(rsExpr.getLeftOperand()) and
right = getValue(rsExpr.getRightOperand().getFullyConverted()).toInt() and
result = (left / 2.pow(right)).floorFloat()
result = safeFloor(left / 2.pow(right))
)
// Not explicitly modeled by a SimpleRangeAnalysisExpr
) and
@@ -1459,7 +1475,7 @@ private float getUpperBoundsImpl(Expr expr) {
rsExpr = expr and
left = getFullyConvertedUpperBounds(rsExpr.getLeftOperand()) and
right = getValue(rsExpr.getRightOperand().getFullyConverted()).toInt() and
result = (left / 2.pow(right)).floorFloat()
result = safeFloor(left / 2.pow(right))
)
// Not explicitly modeled by a SimpleRangeAnalysisExpr
) and
@@ -1709,22 +1725,6 @@ predicate nonNanGuardedVariable(Expr guard, VariableAccess v, boolean branch) {
nanExcludingComparison(guard, branch)
}
/**
* Adjusts a lower bound to its meaning for integral types.
*
* Examples:
* `>= 3.0` becomes `3.0`
* ` > 3.0` becomes `4.0`
* `>= 3.5` becomes `4.0`
* ` > 3.5` becomes `4.0`
*/
bindingset[strictness, lb]
private float adjustLowerBoundIntegral(RelationStrictness strictness, float lb) {
if strictness = Nonstrict() and lb.floorFloat() = lb
then result = lb
else result = lb.floorFloat() + 1
}
/**
* If the guard is a comparison of the form `p*v + q <CMP> r`, then this
* predicate uses the bounds information for `r` to compute a lower bound
@@ -1736,29 +1736,15 @@ private predicate lowerBoundFromGuard(Expr guard, VariableAccess v, float lb, bo
|
if nonNanGuardedVariable(guard, v, branch)
then
if getVariableRangeType(v.getTarget()) instanceof IntegralType
then lb = adjustLowerBoundIntegral(strictness, childLB)
else lb = childLB
if
strictness = Nonstrict() or
not getVariableRangeType(v.getTarget()) instanceof IntegralType
then lb = childLB
else lb = childLB + 1
else lb = varMinVal(v.getTarget())
)
}
/**
* Adjusts an upper bound to its meaning for integral types.
*
* Examples:
* `<= 3.0` becomes `3.0`
* ` < 3.0` becomes `2.0`
* `<= 3.5` becomes `3.0`
* ` < 3.5` becomes `3.0`
*/
bindingset[strictness, ub]
private float adjustUpperBoundIntegral(RelationStrictness strictness, float ub) {
if strictness = Nonstrict() and ub.ceilFloat() = ub
then result = ub
else result = ub.ceilFloat() - 1
}
/**
* If the guard is a comparison of the form `p*v + q <CMP> r`, then this
* predicate uses the bounds information for `r` to compute a upper bound
@@ -1770,9 +1756,11 @@ private predicate upperBoundFromGuard(Expr guard, VariableAccess v, float ub, bo
|
if nonNanGuardedVariable(guard, v, branch)
then
if getVariableRangeType(v.getTarget()) instanceof IntegralType
then ub = adjustUpperBoundIntegral(strictness, childUB)
else ub = childUB
if
strictness = Nonstrict() or
not getVariableRangeType(v.getTarget()) instanceof IntegralType
then ub = childUB
else ub = childUB - 1
else ub = varMaxVal(v.getTarget())
)
}

View File

@@ -1,19 +1,3 @@
## 1.5.8
No user-facing changes.
## 1.5.7
No user-facing changes.
## 1.5.6
No user-facing changes.
## 1.5.5
No user-facing changes.
## 1.5.4
No user-facing changes.

View File

@@ -25,16 +25,11 @@ import UnsignedGEZero
//
// So to reduce the number of false positives, we do not report a result if
// the comparison is in a macro expansion. Similarly for template
// instantiations, static asserts, non-type template arguments, enum constants,
// and constexprs.
// instantiations.
from ComparisonOperation cmp, SmallSide ss, float left, float right, boolean value, string reason
where
not cmp.isInMacroExpansion() and
not cmp.isFromTemplateInstantiation(_) and
not exists(StaticAssert s | s.getCondition() = cmp.getParent*()) and
not exists(Declaration d | d.getATemplateArgument() = cmp.getParent*()) and
not exists(Variable v | v.isConstexpr() | v.getInitializer().getExpr() = cmp.getParent*()) and
not exists(EnumConstant e | e.getInitializer().getExpr() = cmp.getParent*()) and
not functionContainsDisabledCode(cmp.getEnclosingFunction()) and
reachablePointlessComparison(cmp, left, right, value, ss) and
// a comparison between an enum and zero is always valid because whether

View File

@@ -10,7 +10,7 @@ import ExternalAPIsSpecific
/** A node representing untrusted data being passed to an external API. */
class UntrustedExternalApiDataNode extends ExternalApiDataNode {
UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::flowTo(this) }
UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::flow(_, this) }
/** Gets a source of untrusted data which is passed to this external API data node. */
DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::flow(result, this) }

View File

@@ -10,7 +10,7 @@ import ExternalAPIsSpecific
/** A node representing untrusted data being passed to an external API. */
class UntrustedExternalApiDataNode extends ExternalApiDataNode {
UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::flowTo(this) }
UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::flow(_, this) }
/** Gets a source of untrusted data which is passed to this external API data node. */
DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::flow(result, this) }

View File

@@ -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::flowFrom(source) }
predicate isSource(DataFlow::Node source) { FromSensitiveFlow::flow(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::flowFrom(source.getNode()) and
not ToEncryptionFlow::flow(source.getNode(), _) and
not FromEncryptionFlow::flowTo(sink.getNode()) and
// construct result
if networkSendRecv instanceof NetworkSend

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* The `cpp/constant-comparison` query has been updated to not produce false positives for constants that are now represented by their unfolded expression trees.

View File

@@ -1,3 +0,0 @@
## 1.5.5
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 1.5.6
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 1.5.7
No user-facing changes.

View File

@@ -1,3 +0,0 @@
## 1.5.8
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.5.8
lastReleaseVersion: 1.5.4

View File

@@ -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

View File

@@ -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

View File

@@ -129,7 +129,7 @@ module PointerArithmeticToDerefFlow = DataFlow::Global<PointerArithmeticToDerefC
predicate pointerArithOverflow(PointerArithmeticInstruction pai, int delta) {
pointerArithOverflow0(pai, delta) and
PointerArithmeticToDerefFlow::flowFrom(DataFlow::instructionNode(pai))
PointerArithmeticToDerefFlow::flow(DataFlow::instructionNode(pai), _)
}
bindingset[v]

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 1.5.9-dev
version: 1.5.5-dev
groups:
- cpp
- queries

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,2 +1,4 @@
| 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 |

View File

@@ -0,0 +1,2 @@
static int gcc421 = __has_feature(attribute_deprecated_with_message);
// semmle-extractor-options: --gnu_version 40201

View File

@@ -0,0 +1,2 @@
static int gcc450 = __has_feature(attribute_deprecated_with_message);
// semmle-extractor-options: --gnu_version 40500

View File

@@ -26,7 +26,9 @@ void constantAddresses(int param) {
constexpr int *array2d = &int_arr_arr[1][1] + 1;
constexpr int *const_ints = &int_arr_arr[int_const][extern_int_const];
constexpr int *stmtexpr_int = &int_arr[ ({ 1; }) ];
// Commented out because clang and EDG disagree on whether this is
// constant.
//constexpr int *stmtexpr_int = &int_arr[ ({ 1; }) ];
constexpr int *comma_int = &int_arr[ ((void)0, 1) ];
constexpr int *comma_addr = ((void)0, &int_var);

View File

@@ -1,5 +0,0 @@
| addresses.cpp:29:35:29:54 | & ... | stmtexpr_int | misclassified as NOT constant |
| addresses.cpp:31:32:31:55 | & ... | comma_int | misclassified as NOT constant |
| addresses.cpp:36:39:36:70 | ... ? ... : ... | ternary_ptr_cond | misclassified as NOT constant |
| addresses.cpp:37:35:37:69 | & ... | ptr_subtract | misclassified as NOT constant |
| addresses.cpp:39:35:39:50 | ... + ... | constexpr_va | misclassified as NOT constant |

View File

@@ -30,14 +30,13 @@ 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; 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 |
| 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 |
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:37 |
| 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: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 |
@@ -46,10 +45,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: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 |
| 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 |
| 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 |
@@ -61,15 +60,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:35 |
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:34 |
| 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:34 |
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:33 |
| 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:36 |
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:35 |
| 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 | |
@@ -77,7 +76,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:33 |
| 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] 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 | |
@@ -104,13 +103,6 @@ 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 | |
@@ -322,14 +314,6 @@ 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 |
@@ -488,7 +472,6 @@ 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 |

View File

@@ -17,5 +17,4 @@ 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, "callWithNonTypeTemplate<T>", "(const T &)", "", "Argument[*0]", "ReturnValue", "value", "manual"]
- ["", "", False, "callWithArgument", "", "", "Argument[1]", "Argument[0].Parameter[0]", "value", "manual"]

View File

@@ -13,5 +13,3 @@
| 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 |

View File

@@ -2,7 +2,6 @@
| 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 |

View File

@@ -102,19 +102,4 @@ 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
}
}

View File

@@ -142,7 +142,6 @@ 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

View File

@@ -193,10 +193,10 @@ edges
| C.cpp:18:12:18:18 | call to C [s3] | C.cpp:18:12:18:18 | *new [s3] | provenance | |
| C.cpp:19:5:19:5 | *c [s1] | C.cpp:27:8:27:11 | *this [s1] | provenance | |
| C.cpp:19:5:19:5 | *c [s3] | C.cpp:27:8:27:11 | *this [s3] | provenance | |
| C.cpp:22:3:22:3 | *C [post update] [s1] | C.cpp:22:3:22:3 | *this [Return] [s1] | provenance | |
| C.cpp:22:3:22:3 | *this [Return] [s1] | C.cpp:18:12:18:18 | call to C [s1] | provenance | |
| C.cpp:22:3:22:3 | *this [Return] [s3] | C.cpp:18:12:18:18 | call to C [s3] | provenance | |
| C.cpp:22:12:22:21 | new | C.cpp:22:3:22:3 | *C [post update] [s1] | provenance | |
| C.cpp:22:3:22:3 | *this [post update] [s1] | C.cpp:22:3:22:3 | *this [Return] [s1] | provenance | |
| C.cpp:22:12:22:21 | new | C.cpp:22:3:22:3 | *this [post update] [s1] | provenance | |
| C.cpp:22:12:22:21 | new | C.cpp:22:12:22:21 | new | provenance | |
| C.cpp:24:5:24:8 | *this [post update] [s3] | C.cpp:22:3:22:3 | *this [Return] [s3] | provenance | |
| C.cpp:24:5:24:25 | ... = ... | C.cpp:24:5:24:8 | *this [post update] [s3] | provenance | |
@@ -736,12 +736,12 @@ edges
| constructors.cpp:19:22:19:23 | *this [b_] | constructors.cpp:19:22:19:23 | b_ | provenance | |
| constructors.cpp:19:22:19:23 | b_ | constructors.cpp:19:9:19:9 | *b | provenance | |
| constructors.cpp:19:22:19:23 | b_ | constructors.cpp:19:22:19:23 | b_ | provenance | |
| constructors.cpp:23:5:23:7 | *Foo [post update] [a_] | constructors.cpp:23:5:23:7 | *this [Return] [a_] | provenance | |
| constructors.cpp:23:5:23:7 | *Foo [post update] [b_] | constructors.cpp:23:5:23:7 | *this [Return] [b_] | provenance | |
| constructors.cpp:23:5:23:7 | *this [post update] [a_] | constructors.cpp:23:5:23:7 | *this [Return] [a_] | provenance | |
| constructors.cpp:23:5:23:7 | *this [post update] [b_] | constructors.cpp:23:5:23:7 | *this [Return] [b_] | provenance | |
| constructors.cpp:23:13:23:13 | a | constructors.cpp:23:28:23:28 | a | provenance | |
| constructors.cpp:23:20:23:20 | b | constructors.cpp:23:35:23:35 | b | provenance | |
| constructors.cpp:23:28:23:28 | a | constructors.cpp:23:5:23:7 | *Foo [post update] [a_] | provenance | |
| constructors.cpp:23:35:23:35 | b | constructors.cpp:23:5:23:7 | *Foo [post update] [b_] | provenance | |
| constructors.cpp:23:28:23:28 | a | constructors.cpp:23:5:23:7 | *this [post update] [a_] | provenance | |
| constructors.cpp:23:35:23:35 | b | constructors.cpp:23:5:23:7 | *this [post update] [b_] | provenance | |
| constructors.cpp:26:15:26:15 | *f [a_] | constructors.cpp:28:10:28:10 | *f [a_] | provenance | |
| constructors.cpp:26:15:26:15 | *f [b_] | constructors.cpp:29:10:29:10 | *f [b_] | provenance | |
| constructors.cpp:28:10:28:10 | *f [a_] | constructors.cpp:18:9:18:9 | *this [a_] | provenance | |
@@ -1122,9 +1122,9 @@ nodes
| C.cpp:18:12:18:18 | call to C [s3] | semmle.label | call to C [s3] |
| C.cpp:19:5:19:5 | *c [s1] | semmle.label | *c [s1] |
| C.cpp:19:5:19:5 | *c [s3] | semmle.label | *c [s3] |
| C.cpp:22:3:22:3 | *C [post update] [s1] | semmle.label | *C [post update] [s1] |
| C.cpp:22:3:22:3 | *this [Return] [s1] | semmle.label | *this [Return] [s1] |
| C.cpp:22:3:22:3 | *this [Return] [s3] | semmle.label | *this [Return] [s3] |
| C.cpp:22:3:22:3 | *this [post update] [s1] | semmle.label | *this [post update] [s1] |
| C.cpp:22:12:22:21 | new | semmle.label | new |
| C.cpp:22:12:22:21 | new | semmle.label | new |
| C.cpp:24:5:24:8 | *this [post update] [s3] | semmle.label | *this [post update] [s3] |
@@ -1678,10 +1678,10 @@ nodes
| constructors.cpp:19:22:19:23 | *this [b_] | semmle.label | *this [b_] |
| constructors.cpp:19:22:19:23 | b_ | semmle.label | b_ |
| constructors.cpp:19:22:19:23 | b_ | semmle.label | b_ |
| constructors.cpp:23:5:23:7 | *Foo [post update] [a_] | semmle.label | *Foo [post update] [a_] |
| constructors.cpp:23:5:23:7 | *Foo [post update] [b_] | semmle.label | *Foo [post update] [b_] |
| constructors.cpp:23:5:23:7 | *this [Return] [a_] | semmle.label | *this [Return] [a_] |
| constructors.cpp:23:5:23:7 | *this [Return] [b_] | semmle.label | *this [Return] [b_] |
| constructors.cpp:23:5:23:7 | *this [post update] [a_] | semmle.label | *this [post update] [a_] |
| constructors.cpp:23:5:23:7 | *this [post update] [b_] | semmle.label | *this [post update] [b_] |
| constructors.cpp:23:13:23:13 | a | semmle.label | a |
| constructors.cpp:23:20:23:20 | b | semmle.label | b |
| constructors.cpp:23:28:23:28 | a | semmle.label | a |

View File

@@ -308,5 +308,3 @@ 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 |

View File

@@ -670,8 +670,6 @@
| 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 |

View File

@@ -597,8 +597,6 @@ 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 |

View File

@@ -136,36 +136,4 @@ 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

View File

@@ -26843,24 +26843,6 @@ 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 & |
@@ -27101,10 +27083,6 @@ 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 & |
@@ -27308,8 +27286,6 @@ 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 |
@@ -27321,8 +27297,6 @@ 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 & |

Some files were not shown because too many files have changed in this diff Show More