From 6c28be98274e081a1bfa524bc1380420d0193fda Mon Sep 17 00:00:00 2001
From: Jon Janego
Date: Thu, 13 Mar 2025 11:49:48 -0500
Subject: [PATCH 001/409] Update query-metadata-style-guide.md
initial commit of changes starting to add quality tagging standards
---
docs/query-metadata-style-guide.md | 56 +++++++++++++++++++++---------
1 file changed, 39 insertions(+), 17 deletions(-)
diff --git a/docs/query-metadata-style-guide.md b/docs/query-metadata-style-guide.md
index 3350111db22e..d4704c6c11ed 100644
--- a/docs/query-metadata-style-guide.md
+++ b/docs/query-metadata-style-guide.md
@@ -121,12 +121,47 @@ Alert queries (`@kind problem` or `path-problem`) support two further properties
## Query tags `@tags`
-The `@tags` property is used to define categories that the query relates to. Each alert query should belong to one (or more, if necessary) of the following four top-level categories:
+The `@tags` property is used to define categories that the query relates to. As we prepare for the release of a dedicated code quality product, we will use tagging to prepare a stronger delineation between queries that are part of our existing "code security" product offering and those that are better suited as part of a "quality" product offering. Each alert query should belong to one of the following two top-level categories, with additional sub-categories:
-* `@tags correctness`–for queries that detect incorrect program behavior.
-* `@tags maintainability`–for queries that detect patterns that make it harder for developers to make changes to the code.
-* `@tags readability`–for queries that detect confusing patterns that make it harder for developers to read the code.
+#### High level category `@tags`
* `@tags security`–for queries that detect security weaknesses. See below for further information.
+* `@tags quality`–for queries that detect code quality issues. See below for further information.
+
+#### Security query `@tags`
+
+If your query is a security query, use one or more `@tags` to associate it with the relevant CWEs. Add `@tags` for the most specific Base Weakness or Class Weakness in [View 1000](https://cwe.mitre.org/data/definitions/1000.html), using the parent/child relationship. For example:
+
+| `@tags security` | `external/cwe/cwe-022`|
+|-|-|
+||`external/cwe/cwe-023` |
+||`external/cwe/cwe-036` |
+||`external/cwe/cwe-073` |
+
+When you tag a query like this, the associated CWE pages from [MITRE.org](https://cwe.mitre.org/index.html) will automatically appear in the references section of its associated qhelp file.
+
+> [!NOTE]
+> The automatic addition of CWE reference links works only if the qhelp file already contains a `` section.
+
+#### Quality query sub-category `@tags`
+
+* `@tags maintainability`–for queries that detect patterns that make it harder for developers to make changes to the code.
+* `@tags reliability`–for queries that detect issues that affect whether the code will perform as expected during execution.
+
+Software quality doesn't have as universally-agreed categorization method as security issues like CWE, so we will do our own categorization instead of using tags like CWE.
+
+We'll have two "top-level" categories of quality queries, with sub-categories beneath:
+
+* `@tags maintainability`–for queries that detect patterns that make it harder for developers to make changes to the code.
+ * `@tags readability`–for queries that detect confusing patterns that make it harder for developers to read the code.
+ *
+
+
+* `@tags reliability`–for queries that detect issues that affect whether the code will perform as expected during execution.
+ * `@tags correctness`–for queries that detect incorrect program behavior.
+
+
+
+
There are also more specific `@tags` that can be added. See, the following pages for examples of the low-level tags:
@@ -145,20 +180,7 @@ If necessary, you can also define your own low-level tags to categorize the quer
* Use a forward slash / to indicate a hierarchical relationship between tags if necessary. For example, a query with tag `foo/bar` is also interpreted as also having tag `foo`, but not `bar`.
* Use a single-word `@tags` name. Multiple words, separated with hyphens, can be used for clarity if necessary.
-#### Security query `@tags`
-
-If your query is a security query, use one or more `@tags` to associate it with the relevant CWEs. Add `@tags` for the most specific Base Weakness or Class Weakness in [View 1000](https://cwe.mitre.org/data/definitions/1000.html), using the parent/child relationship. For example:
-| `@tags security` | `external/cwe/cwe-022`|
-|-|-|
-||`external/cwe/cwe-023` |
-||`external/cwe/cwe-036` |
-||`external/cwe/cwe-073` |
-
-When you tag a query like this, the associated CWE pages from [MITRE.org](https://cwe.mitre.org/index.html) will automatically appear in the references section of its associated qhelp file.
-
-> [!NOTE]
-> The automatic addition of CWE reference links works only if the qhelp file already contains a `` section.
#### Metric/summary `@tags`
From de5d3b6263b25657f6524306ce66b20beaa9a963 Mon Sep 17 00:00:00 2001
From: Jon Janego
Date: Thu, 13 Mar 2025 12:42:51 -0500
Subject: [PATCH 002/409] Update query-metadata-style-guide.md
---
docs/query-metadata-style-guide.md | 40 +++++++++++++++++-------------
1 file changed, 23 insertions(+), 17 deletions(-)
diff --git a/docs/query-metadata-style-guide.md b/docs/query-metadata-style-guide.md
index d4704c6c11ed..a13ad200a9a3 100644
--- a/docs/query-metadata-style-guide.md
+++ b/docs/query-metadata-style-guide.md
@@ -121,9 +121,9 @@ Alert queries (`@kind problem` or `path-problem`) support two further properties
## Query tags `@tags`
-The `@tags` property is used to define categories that the query relates to. As we prepare for the release of a dedicated code quality product, we will use tagging to prepare a stronger delineation between queries that are part of our existing "code security" product offering and those that are better suited as part of a "quality" product offering. Each alert query should belong to one of the following two top-level categories, with additional sub-categories:
+The `@tags` property is used to define the high level category of problem that the query relates to. Each alert query should belong to one of the following two top-level categories, with additional sub-categories:
-#### High level category `@tags`
+### High level category `@tags`
* `@tags security`–for queries that detect security weaknesses. See below for further information.
* `@tags quality`–for queries that detect code quality issues. See below for further information.
@@ -149,18 +149,19 @@ When you tag a query like this, the associated CWE pages from [MITRE.org](https:
Software quality doesn't have as universally-agreed categorization method as security issues like CWE, so we will do our own categorization instead of using tags like CWE.
-We'll have two "top-level" categories of quality queries, with sub-categories beneath:
+We'll use two "top-level" categories of quality queries, with sub-categories beneath:
* `@tags maintainability`–for queries that detect patterns that make it harder for developers to make changes to the code.
* `@tags readability`–for queries that detect confusing patterns that make it harder for developers to read the code.
- *
-
+ * `@tags unused-code`-for queries that detect functions that are never used and other instances of unused code
+ * `@tags complexity`-for queries that detect patterns in the code that lead to unnecesary complexity such as unclear control flow, or high cyclomatic complexity
+
* `@tags reliability`–for queries that detect issues that affect whether the code will perform as expected during execution.
- * `@tags correctness`–for queries that detect incorrect program behavior.
-
-
-
+ * `@tags correctness`–for queries that detect incorrect program behavior or couse result in unintended outcomes.
+ * `@tags performance`-for queries that detect code that could impact performance through inefficient algorithms, unnecessary computation, etc
+ * `@tags concurrency`-for queries that detect concurrency related issues such as race conditions, deadlocks, thread safety, etc
+ * `@tags error-handling`-for queries that detect issues related to unsafe error handling such as uncaught exceptions, etc
There are also more specific `@tags` that can be added. See, the following pages for examples of the low-level tags:
@@ -172,22 +173,27 @@ There are also more specific `@tags` that can be added. See, the following pages
* [JavaScript queries](https://codeql.github.com/codeql-query-help/javascript/)
* [Python queries](https://codeql.github.com/codeql-query-help/python/)
-Metric queries (`@kind metric`) may have the `summary` tag. If SARIF output is used, the results of these queries can be found at `run[].properties.metricResults`.
-If necessary, you can also define your own low-level tags to categorize the queries specific to your project or organization. When creating your own tags, you should:
-
-* Use all lower-case letters, including for acronyms and proper nouns, with no spaces. All characters apart from * and @ are accepted.
-* Use a forward slash / to indicate a hierarchical relationship between tags if necessary. For example, a query with tag `foo/bar` is also interpreted as also having tag `foo`, but not `bar`.
-* Use a single-word `@tags` name. Multiple words, separated with hyphens, can be used for clarity if necessary.
+### Severities
+Maintainers are expected to add a `@security-severity` tag to security relevant queries that will be run on Code Scanning. There is a documented internal process for generating these `@security-severity` values.
+TODO: should we have a severity value for quality queries?
-#### Metric/summary `@tags`
+### Metric/summary `@tags`
Code Scanning may use tags to identify queries with specific meanings across languages. Currently, there is only one such tag: `lines-of-code`. The sum of the results for queries with this tag that return a single number column ([example for JavaScript](https://github.com/github/codeql/blob/c47d680d65f09a851e41d4edad58ffa7486b5431/java/ql/src/Metrics/Summaries/LinesOfCode.ql)) is interpreted by Code Scanning as the lines of code under the source root present in the database. Each language should have exactly one query of this form.
+Metric queries (`@kind metric`) may have the `summary` tag. If SARIF output is used, the results of these queries can be found at `run[].properties.metricResults`.
-Maintainers are expected to add a `@security-severity` tag to security relevant queries that will be run on Code Scanning. There is a documented internal process for generating these `@security-severity` values.
+
+### Customizing tags
+
+If necessary, you can also define your own low-level tags to categorize the queries specific to your project or organization, but if possible, please try to follow the above standards (or propose changes to this style guide). When creating your own tags, you should:
+
+* Use all lower-case letters, including for acronyms and proper nouns, with no spaces. All characters apart from * and @ are accepted.
+* Use a forward slash / to indicate a hierarchical relationship between tags if necessary. For example, a query with tag `foo/bar` is also interpreted as also having tag `foo`, but not `bar`.
+* Use a single-word `@tags` name. Multiple words, separated with hyphens, can be used for clarity if necessary.
## QL area
From 14d178f81773c21c62d428af41607f45b5dd5882 Mon Sep 17 00:00:00 2001
From: Jon Janego
Date: Wed, 19 Mar 2025 16:56:37 -0500
Subject: [PATCH 003/409] Update query-metadata-style-guide.md
minor tag changes to align with existing tags
---
docs/query-metadata-style-guide.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/query-metadata-style-guide.md b/docs/query-metadata-style-guide.md
index a13ad200a9a3..b51f6fea5a0a 100644
--- a/docs/query-metadata-style-guide.md
+++ b/docs/query-metadata-style-guide.md
@@ -153,7 +153,7 @@ We'll use two "top-level" categories of quality queries, with sub-categories ben
* `@tags maintainability`–for queries that detect patterns that make it harder for developers to make changes to the code.
* `@tags readability`–for queries that detect confusing patterns that make it harder for developers to read the code.
- * `@tags unused-code`-for queries that detect functions that are never used and other instances of unused code
+ * `@tags useless-code`-for queries that detect functions that are never used and other instances of unused code
* `@tags complexity`-for queries that detect patterns in the code that lead to unnecesary complexity such as unclear control flow, or high cyclomatic complexity
From f698d0a060b01adec18a57c2e9bfe1d952bf76e0 Mon Sep 17 00:00:00 2001
From: Jon Janego
Date: Wed, 19 Mar 2025 16:58:30 -0500
Subject: [PATCH 004/409] Update query-metadata-style-guide.md
---
docs/query-metadata-style-guide.md | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/docs/query-metadata-style-guide.md b/docs/query-metadata-style-guide.md
index b51f6fea5a0a..4c3f5b8814fe 100644
--- a/docs/query-metadata-style-guide.md
+++ b/docs/query-metadata-style-guide.md
@@ -121,7 +121,7 @@ Alert queries (`@kind problem` or `path-problem`) support two further properties
## Query tags `@tags`
-The `@tags` property is used to define the high level category of problem that the query relates to. Each alert query should belong to one of the following two top-level categories, with additional sub-categories:
+The `@tags` property is used to define the high level category of problem that the query relates to. Each alert query should belong to one of the following two top-level categories, with additional sub-categories:
### High level category `@tags`
* `@tags security`–for queries that detect security weaknesses. See below for further information.
@@ -173,6 +173,8 @@ There are also more specific `@tags` that can be added. See, the following pages
* [JavaScript queries](https://codeql.github.com/codeql-query-help/javascript/)
* [Python queries](https://codeql.github.com/codeql-query-help/python/)
+> [!NOTE]
+> There is a limit of 10 tags per query!
### Severities
From 81e85010f900a49f7fced559196166a2f982c335 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Thu, 20 Mar 2025 12:30:57 +0000
Subject: [PATCH 005/409] List subpackages in vendor/modules.txt
These were all generated by running depstubber.
---
go/ql/test/experimental/CWE-285/vendor/modules.txt | 2 +-
go/ql/test/experimental/CWE-321-V2/vendor/modules.txt | 2 +-
.../CWE-522-DecompressionBombs/vendor/modules.txt | 11 +++++++++--
.../semmle/go/concepts/LoggerCall/vendor/modules.txt | 5 -----
.../semmle/go/frameworks/Beego/vendor/modules.txt | 6 +++++-
.../go/frameworks/ElazarlGoproxy/vendor/modules.txt | 1 +
.../semmle/go/frameworks/Email/vendor/modules.txt | 2 +-
.../semmle/go/frameworks/Gin/vendor/modules.txt | 1 +
.../semmle/go/frameworks/GoMicro/vendor/modules.txt | 7 ++++++-
.../semmle/go/frameworks/Iris/vendor/modules.txt | 2 +-
.../go/frameworks/K8sIoApiCoreV1/vendor/modules.txt | 5 +++--
.../K8sIoApimachineryPkgRuntime/vendor/modules.txt | 4 +++-
.../go/frameworks/K8sIoClientGo/vendor/modules.txt | 2 +-
.../semmle/go/frameworks/NoSQL/vendor/modules.txt | 7 ++++---
.../semmle/go/frameworks/Revel/vendor/modules.txt | 4 +++-
.../semmle/go/frameworks/SQL/gogf/vendor/modules.txt | 3 ++-
.../semmle/go/frameworks/Spew/vendor/modules.txt | 2 +-
.../SystemCommandExecutors/vendor/modules.txt | 2 +-
.../semmle/go/frameworks/WebSocket/vendor/modules.txt | 2 +-
.../semmle/go/frameworks/Zap/vendor/modules.txt | 1 +
.../IncompleteHostnameRegexp/vendor/modules.txt | 2 --
.../query-tests/Security/CWE-079/vendor/modules.txt | 2 +-
.../query-tests/Security/CWE-089/vendor/modules.txt | 4 +++-
.../query-tests/Security/CWE-312/vendor/modules.txt | 5 +++--
.../query-tests/Security/CWE-347/vendor/modules.txt | 2 +-
.../query-tests/Security/CWE-640/vendor/modules.txt | 2 +-
.../query-tests/Security/CWE-643/vendor/modules.txt | 6 ++++--
.../query-tests/Security/CWE-798/vendor/modules.txt | 6 +++---
.../query-tests/Security/CWE-918/vendor/modules.txt | 2 +-
29 files changed, 63 insertions(+), 39 deletions(-)
diff --git a/go/ql/test/experimental/CWE-285/vendor/modules.txt b/go/ql/test/experimental/CWE-285/vendor/modules.txt
index 5ad327e8bb5b..8de84fbd85d0 100644
--- a/go/ql/test/experimental/CWE-285/vendor/modules.txt
+++ b/go/ql/test/experimental/CWE-285/vendor/modules.txt
@@ -1,3 +1,3 @@
# github.com/msteinert/pam v1.0.0
## explicit
-github.com/msteinert/pam
\ No newline at end of file
+github.com/msteinert/pam
diff --git a/go/ql/test/experimental/CWE-321-V2/vendor/modules.txt b/go/ql/test/experimental/CWE-321-V2/vendor/modules.txt
index eedc2bbfc925..015b30ce9a21 100644
--- a/go/ql/test/experimental/CWE-321-V2/vendor/modules.txt
+++ b/go/ql/test/experimental/CWE-321-V2/vendor/modules.txt
@@ -1,6 +1,6 @@
# github.com/go-jose/go-jose/v3 v3.0.0
## explicit
-github.com/go-jose/go-jose/v3
+github.com/go-jose/go-jose/v3/jwt
# github.com/golang-jwt/jwt/v5 v5.0.0
## explicit
github.com/golang-jwt/jwt/v5
diff --git a/go/ql/test/experimental/CWE-522-DecompressionBombs/vendor/modules.txt b/go/ql/test/experimental/CWE-522-DecompressionBombs/vendor/modules.txt
index 92976a6e7e99..228cc0e318d5 100644
--- a/go/ql/test/experimental/CWE-522-DecompressionBombs/vendor/modules.txt
+++ b/go/ql/test/experimental/CWE-522-DecompressionBombs/vendor/modules.txt
@@ -3,13 +3,20 @@
github.com/DataDog/zstd
# github.com/dsnet/compress v0.0.1
## explicit
-github.com/dsnet/compress
+github.com/dsnet/compress/bzip2
+github.com/dsnet/compress/flate
# github.com/golang/snappy v0.0.4
## explicit
github.com/golang/snappy
# github.com/klauspost/compress v1.16.6
## explicit
-github.com/klauspost/compress
+github.com/klauspost/compress/zstd
+github.com/klauspost/compress/snappy
+github.com/klauspost/compress/s2
+github.com/klauspost/compress/zlib
+github.com/klauspost/compress/zip
+github.com/klauspost/compress/flate
+github.com/klauspost/compress/gzip
# github.com/klauspost/pgzip v1.2.6
## explicit
github.com/klauspost/pgzip
diff --git a/go/ql/test/library-tests/semmle/go/concepts/LoggerCall/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/concepts/LoggerCall/vendor/modules.txt
index c20671b41943..da35ae80c085 100644
--- a/go/ql/test/library-tests/semmle/go/concepts/LoggerCall/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/concepts/LoggerCall/vendor/modules.txt
@@ -1,14 +1,9 @@
-# github.com/github/depstubber v0.0.0-20200916130315-f3217697abd4
-## explicit
# github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
## explicit
github.com/golang/glog
# github.com/sirupsen/logrus v1.7.0
## explicit
github.com/sirupsen/logrus
-# golang.org/x/sys v0.0.0-20191026070338-33540a1f6037
-golang.org/x/sys/unix
-golang.org/x/sys/windows
# k8s.io/klog v1.0.0
## explicit
k8s.io/klog
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Beego/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/Beego/vendor/modules.txt
index bb2db0e47da3..2ec051971307 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Beego/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Beego/vendor/modules.txt
@@ -1,6 +1,10 @@
# github.com/astaxie/beego v1.12.3
## explicit
+github.com/astaxie/beego/utils
github.com/astaxie/beego
+github.com/astaxie/beego/context
+github.com/astaxie/beego/logs
# github.com/beego/beego/v2 v2.1.2
## explicit
-github.com/beego/beego/v2
+github.com/beego/beego/v2/server/web
+github.com/beego/beego/v2/server/web/context
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/ElazarlGoproxy/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/ElazarlGoproxy/vendor/modules.txt
index bf027718a74a..d560618b74da 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/ElazarlGoproxy/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/ElazarlGoproxy/vendor/modules.txt
@@ -3,3 +3,4 @@
github.com/elazarl/goproxy
# github.com/github/depstubber v0.0.0-20201214172518-12c3da4b7c9d
## explicit
+github.com/github/depstubber
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Email/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/Email/vendor/modules.txt
index 4b7525957dfc..c964e33b1f68 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Email/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Email/vendor/modules.txt
@@ -1,3 +1,3 @@
# github.com/sendgrid/sendgrid-go v3.5.0+incompatible
## explicit
-github.com/sendgrid/sendgrid-go
+github.com/sendgrid/sendgrid-go/helpers/mail
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Gin/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/Gin/vendor/modules.txt
index 5f2816316f48..4d249b53d1ae 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Gin/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Gin/vendor/modules.txt
@@ -1,3 +1,4 @@
# github.com/gin-gonic/gin v1.6.2
## explicit
github.com/gin-gonic/gin
+github.com/gin-gonic/gin/binding
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/vendor/modules.txt
index 1884e9622afa..4235d3525987 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/vendor/modules.txt
@@ -1,6 +1,11 @@
# go-micro.dev/v4 v4.10.2
## explicit
+go-micro.dev/v4/api
+go-micro.dev/v4/client
+go-micro.dev/v4/server
go-micro.dev/v4
# google.golang.org/protobuf v1.28.1
## explicit
-google.golang.org/protobuf
+google.golang.org/protobuf/proto
+google.golang.org/protobuf/reflect/protoreflect
+google.golang.org/protobuf/runtime/protoimpl
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Iris/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/Iris/vendor/modules.txt
index e3c62be74a71..8fdf3c4082d5 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Iris/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Iris/vendor/modules.txt
@@ -1,6 +1,6 @@
# github.com/kataras/iris/v12 v12.2.5
## explicit
-github.com/kataras/iris/v12
+github.com/kataras/iris/v12/context
# github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06
## explicit
github.com/Shopify/goreferrer
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApiCoreV1/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApiCoreV1/vendor/modules.txt
index bd3ad03a88b4..859956613d50 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApiCoreV1/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApiCoreV1/vendor/modules.txt
@@ -1,6 +1,7 @@
# k8s.io/api v0.20.0
## explicit
-k8s.io/api
+k8s.io/api/core/v1
+k8s.io/apimachinery/pkg/runtime
# k8s.io/apimachinery v0.20.0
## explicit
-k8s.io/apimachinery
+k8s.io/apimachinery/pkg/runtime
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApimachineryPkgRuntime/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApimachineryPkgRuntime/vendor/modules.txt
index 007fe13b0dec..59d5b5f7464c 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApimachineryPkgRuntime/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApimachineryPkgRuntime/vendor/modules.txt
@@ -1,3 +1,5 @@
# k8s.io/apimachinery v0.19.4
## explicit
-k8s.io/apimachinery
+k8s.io/apimachinery/pkg/conversion
+k8s.io/apimachinery/pkg/runtime
+k8s.io/apimachinery/pkg/runtime/schema
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/K8sIoClientGo/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/K8sIoClientGo/vendor/modules.txt
index 7c2af6245595..3b8636e54ea4 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/K8sIoClientGo/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/K8sIoClientGo/vendor/modules.txt
@@ -18,7 +18,7 @@ golang.org/x/oauth2
golang.org/x/time
# k8s.io/client-go v0.19.0
## explicit
-k8s.io/client-go
+k8s.io/client-go/kubernetes/typed/core/v1
# k8s.io/utils v0.0.0-20201110183641-67b214c5f920
## explicit
k8s.io/utils
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/NoSQL/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/NoSQL/vendor/modules.txt
index efe6455326a2..94d59ce4d62a 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/NoSQL/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/NoSQL/vendor/modules.txt
@@ -1,6 +1,3 @@
-# go.mongodb.org/mongo-driver v1.3.2
-## explicit
-go.mongodb.org/mongo-driver
# github.com/couchbase/gocb/v2 v2.2.0
## explicit
github.com/couchbase/gocb/v2
@@ -10,6 +7,10 @@ github.com/google/uuid
# github.com/opentracing/opentracing-go v1.2.0
## explicit
github.com/opentracing/opentracing-go
+# go.mongodb.org/mongo-driver v1.3.2
+## explicit
+go.mongodb.org/mongo-driver/bson
+go.mongodb.org/mongo-driver/mongo
# gopkg.in/couchbase/gocb.v1 v1.6.7
## explicit
gopkg.in/couchbase/gocb.v1
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/Revel/vendor/modules.txt
index fe1af187494a..b674df40109f 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/vendor/modules.txt
@@ -3,7 +3,9 @@
github.com/go-stack/stack
# github.com/revel/modules v1.0.0
## explicit
-github.com/revel/modules
+github.com/revel/modules/orm/gorp/app/controllers
+github.com/revel/modules/static/app/controllers
# github.com/revel/revel v1.0.0
## explicit
github.com/revel/revel
+github.com/revel/revel/logger
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/vendor/modules.txt
index 72560d0da5e0..d3645e863f4b 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/vendor/modules.txt
@@ -1,6 +1,7 @@
# github.com/gogf/gf v1.16.9
## explicit
-github.com/gogf/gf
+github.com/gogf/gf/database/gdb
+github.com/gogf/gf/frame/g
# github.com/BurntSushi/toml v0.3.1
## explicit
github.com/BurntSushi/toml
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Spew/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/Spew/vendor/modules.txt
index 9e9ed5edf647..5d0fa4c56ac0 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Spew/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Spew/vendor/modules.txt
@@ -1,6 +1,6 @@
# github.com/davecgh/go-spew v1.1.1
## explicit
-github.com/davecgh/go-spew
+github.com/davecgh/go-spew/spew
# github.com/github/depstubber v0.0.0-20200916130315-f3217697abd4
## explicit
github.com/github/depstubber
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SystemCommandExecutors/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/SystemCommandExecutors/vendor/modules.txt
index 2fdb2ae4eae1..d6e69c7b2986 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/SystemCommandExecutors/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/SystemCommandExecutors/vendor/modules.txt
@@ -3,4 +3,4 @@
github.com/codeskyblue/go-sh
# golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59
## explicit
-golang.org/x/crypto
+golang.org/x/crypto/ssh
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/WebSocket/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/WebSocket/vendor/modules.txt
index 43950046ca3a..ea1d1721a315 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/WebSocket/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/WebSocket/vendor/modules.txt
@@ -9,7 +9,7 @@ github.com/gorilla/websocket
github.com/sacOO7/gowebsocket
# golang.org/x/net v0.0.0-20200505041828-1ed23360d12c
## explicit
-golang.org/x/net
+golang.org/x/net/websocket
# nhooyr.io/websocket v1.8.5
## explicit
nhooyr.io/websocket
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Zap/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/Zap/vendor/modules.txt
index 81aa5380f124..d6c25845fd46 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Zap/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Zap/vendor/modules.txt
@@ -1,3 +1,4 @@
# go.uber.org/zap v1.16.0
## explicit
go.uber.org/zap
+go.uber.org/zap/zapcore
diff --git a/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/vendor/modules.txt b/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/vendor/modules.txt
index bf027718a74a..a81e0c273fa7 100644
--- a/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/vendor/modules.txt
+++ b/go/ql/test/query-tests/Security/CWE-020/IncompleteHostnameRegexp/vendor/modules.txt
@@ -1,5 +1,3 @@
# github.com/elazarl/goproxy v0.0.0-20201021153353-00ad82a08272
## explicit
github.com/elazarl/goproxy
-# github.com/github/depstubber v0.0.0-20201214172518-12c3da4b7c9d
-## explicit
diff --git a/go/ql/test/query-tests/Security/CWE-079/vendor/modules.txt b/go/ql/test/query-tests/Security/CWE-079/vendor/modules.txt
index 5e59711dd7b0..f61f191db597 100644
--- a/go/ql/test/query-tests/Security/CWE-079/vendor/modules.txt
+++ b/go/ql/test/query-tests/Security/CWE-079/vendor/modules.txt
@@ -6,7 +6,7 @@ github.com/gobwas/ws
github.com/gorilla/websocket
# golang.org/x/net v0.0.0-20200505041828-1ed23360d12c
## explicit
-golang.org/x/net
+golang.org/x/net/websocket
# nhooyr.io/websocket v1.8.5
## explicit
nhooyr.io/websocket
diff --git a/go/ql/test/query-tests/Security/CWE-089/vendor/modules.txt b/go/ql/test/query-tests/Security/CWE-089/vendor/modules.txt
index ddbc30953a2e..b0de76d4f889 100644
--- a/go/ql/test/query-tests/Security/CWE-089/vendor/modules.txt
+++ b/go/ql/test/query-tests/Security/CWE-089/vendor/modules.txt
@@ -3,4 +3,6 @@
github.com/Masterminds/squirrel
# go.mongodb.org/mongo-driver v1.3.3
## explicit
-go.mongodb.org/mongo-driver
+go.mongodb.org/mongo-driver/mongo
+go.mongodb.org/mongo-driver/mongo/options
+go.mongodb.org/mongo-driver/bson
diff --git a/go/ql/test/query-tests/Security/CWE-312/vendor/modules.txt b/go/ql/test/query-tests/Security/CWE-312/vendor/modules.txt
index 239424327022..aa0c56a1a6f3 100644
--- a/go/ql/test/query-tests/Security/CWE-312/vendor/modules.txt
+++ b/go/ql/test/query-tests/Security/CWE-312/vendor/modules.txt
@@ -9,7 +9,8 @@ github.com/sirupsen/logrus
k8s.io/klog
# github.com/golang/protobuf v1.4.2
## explicit
-github.com/golang/protobuf
+github.com/golang/protobuf/proto
# google.golang.org/protobuf v1.23.0
## explicit
-google.golang.org/protobuf
+google.golang.org/protobuf/reflect/protoreflect
+google.golang.org/protobuf/runtime/protoimpl
diff --git a/go/ql/test/query-tests/Security/CWE-347/vendor/modules.txt b/go/ql/test/query-tests/Security/CWE-347/vendor/modules.txt
index 01144bc92497..811980fafee0 100644
--- a/go/ql/test/query-tests/Security/CWE-347/vendor/modules.txt
+++ b/go/ql/test/query-tests/Security/CWE-347/vendor/modules.txt
@@ -3,7 +3,7 @@
github.com/gin-gonic/gin
# github.com/go-jose/go-jose/v3 v3.0.0
## explicit
-github.com/go-jose/go-jose/v3
+github.com/go-jose/go-jose/v3/jwt
# github.com/golang-jwt/jwt/v5 v5.0.0
## explicit
github.com/golang-jwt/jwt/v5
diff --git a/go/ql/test/query-tests/Security/CWE-640/vendor/modules.txt b/go/ql/test/query-tests/Security/CWE-640/vendor/modules.txt
index 4b7525957dfc..c964e33b1f68 100644
--- a/go/ql/test/query-tests/Security/CWE-640/vendor/modules.txt
+++ b/go/ql/test/query-tests/Security/CWE-640/vendor/modules.txt
@@ -1,3 +1,3 @@
# github.com/sendgrid/sendgrid-go v3.5.0+incompatible
## explicit
-github.com/sendgrid/sendgrid-go
+github.com/sendgrid/sendgrid-go/helpers/mail
diff --git a/go/ql/test/query-tests/Security/CWE-643/vendor/modules.txt b/go/ql/test/query-tests/Security/CWE-643/vendor/modules.txt
index 3f70fcb344d3..a852f50be92f 100644
--- a/go/ql/test/query-tests/Security/CWE-643/vendor/modules.txt
+++ b/go/ql/test/query-tests/Security/CWE-643/vendor/modules.txt
@@ -1,5 +1,6 @@
# github.com/ChrisTrenkamp/goxpath v0.0.0-20190607011252-c5096ec8773d
## explicit
+github.com/ChrisTrenkamp/goxpath/tree
github.com/ChrisTrenkamp/goxpath
# github.com/antchfx/htmlquery v1.2.2
## explicit
@@ -18,10 +19,11 @@ github.com/antchfx/xpath
github.com/go-xmlpath/xmlpath
# github.com/jbowtie/gokogiri v0.0.0-20190301021639-37f655d3078f
## explicit
-github.com/jbowtie/gokogiri
+github.com/jbowtie/gokogiri/xpath
+github.com/jbowtie/gokogiri/xml
# github.com/lestrrat-go/libxml2 v0.0.0-20231124114421-99c71026c2f5
## explicit
-github.com/lestrrat-go/libxml2
+github.com/lestrrat-go/libxml2/parser
# github.com/santhosh-tekuri/xpathparser v1.0.0
## explicit
github.com/santhosh-tekuri/xpathparser
diff --git a/go/ql/test/query-tests/Security/CWE-798/vendor/modules.txt b/go/ql/test/query-tests/Security/CWE-798/vendor/modules.txt
index 61fe07b45404..caa73317d564 100644
--- a/go/ql/test/query-tests/Security/CWE-798/vendor/modules.txt
+++ b/go/ql/test/query-tests/Security/CWE-798/vendor/modules.txt
@@ -6,7 +6,7 @@ github.com/appleboy/gin-jwt/v2
github.com/cristalhq/jwt/v3
# github.com/go-kit/kit v0.12.0
## explicit
-github.com/go-kit/kit
+github.com/go-kit/kit/auth/jwt
# github.com/gogf/gf-jwt/v2 v2.0.1
## explicit
github.com/gogf/gf-jwt/v2
@@ -18,13 +18,13 @@ github.com/golang-jwt/jwt/v4
github.com/iris-contrib/middleware/jwt
# github.com/kataras/iris/v12 v12.2.0
## explicit
-github.com/kataras/iris/v12
+github.com/kataras/iris/v12/middleware/jwt
# github.com/kataras/jwt v0.1.8
## explicit
github.com/kataras/jwt
# github.com/lestrrat/go-jwx v0.9.1
## explicit
-github.com/lestrrat/go-jwx
+github.com/lestrrat/go-jwx/jwk
# github.com/square/go-jose/v3 v3.0.0-20200630053402-0a67ce9b0693
## explicit
github.com/square/go-jose/v3
diff --git a/go/ql/test/query-tests/Security/CWE-918/vendor/modules.txt b/go/ql/test/query-tests/Security/CWE-918/vendor/modules.txt
index 319b30b771be..a440f984681f 100644
--- a/go/ql/test/query-tests/Security/CWE-918/vendor/modules.txt
+++ b/go/ql/test/query-tests/Security/CWE-918/vendor/modules.txt
@@ -9,7 +9,7 @@ github.com/gorilla/websocket
github.com/sacOO7/gowebsocket
# golang.org/x/net v0.0.0-20200421231249-e086a090c8fd
## explicit
-golang.org/x/net
+golang.org/x/net/websocket
# nhooyr.io/websocket v1.8.5
## explicit
nhooyr.io/websocket
From 40768332d897d31ca57fddc4ffd53cb63350c7ec Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Thu, 20 Mar 2025 12:32:12 +0000
Subject: [PATCH 006/409] Remove empty imports from stubs
---
.../concepts/LoggerCall/vendor/github.com/golang/glog/stub.go | 2 --
.../semmle/go/concepts/LoggerCall/vendor/k8s.io/klog/stub.go | 2 --
.../vendor/github.com/sendgrid/sendgrid-go/helpers/mail/stub.go | 2 --
.../frameworks/K8sIoApiCoreV1/vendor/k8s.io/api/core/v1/stub.go | 2 --
.../vendor/k8s.io/apimachinery/pkg/runtime/stub.go | 2 --
.../vendor/k8s.io/apimachinery/pkg/runtime/schema/stub.go | 2 --
.../vendor/go.mongodb.org/mongo-driver/bson/primitive/stub.go | 2 --
.../Security/CWE-312/vendor/github.com/golang/glog/stub.go | 2 --
.../query-tests/Security/CWE-312/vendor/k8s.io/klog/stub.go | 2 --
.../vendor/github.com/sendgrid/sendgrid-go/helpers/mail/stub.go | 2 --
.../CWE-643/vendor/github.com/antchfx/htmlquery/stub.go | 2 --
.../CWE-643/vendor/github.com/antchfx/jsonquery/stub.go | 2 --
.../filters/ClassifyFiles/vendor/github.com/onsi/ginkgo/stub.go | 2 --
.../filters/ClassifyFiles/vendor/github.com/onsi/gomega/stub.go | 2 --
14 files changed, 28 deletions(-)
diff --git a/go/ql/test/library-tests/semmle/go/concepts/LoggerCall/vendor/github.com/golang/glog/stub.go b/go/ql/test/library-tests/semmle/go/concepts/LoggerCall/vendor/github.com/golang/glog/stub.go
index 7c4ffefc1e87..49f90bc21afb 100644
--- a/go/ql/test/library-tests/semmle/go/concepts/LoggerCall/vendor/github.com/golang/glog/stub.go
+++ b/go/ql/test/library-tests/semmle/go/concepts/LoggerCall/vendor/github.com/golang/glog/stub.go
@@ -7,8 +7,6 @@
// Package glog is a stub of github.com/golang/glog, generated by depstubber.
package glog
-import ()
-
func Error(_ ...interface{}) {}
func ErrorDepth(_ int, _ ...interface{}) {}
diff --git a/go/ql/test/library-tests/semmle/go/concepts/LoggerCall/vendor/k8s.io/klog/stub.go b/go/ql/test/library-tests/semmle/go/concepts/LoggerCall/vendor/k8s.io/klog/stub.go
index d03572488124..0c29992abcf8 100644
--- a/go/ql/test/library-tests/semmle/go/concepts/LoggerCall/vendor/k8s.io/klog/stub.go
+++ b/go/ql/test/library-tests/semmle/go/concepts/LoggerCall/vendor/k8s.io/klog/stub.go
@@ -7,8 +7,6 @@
// Package klog is a stub of k8s.io/klog, generated by depstubber.
package klog
-import ()
-
func Error(_ ...interface{}) {}
func ErrorDepth(_ int, _ ...interface{}) {}
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Email/vendor/github.com/sendgrid/sendgrid-go/helpers/mail/stub.go b/go/ql/test/library-tests/semmle/go/frameworks/Email/vendor/github.com/sendgrid/sendgrid-go/helpers/mail/stub.go
index cd1956cecc05..f5d9d9bbbef2 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Email/vendor/github.com/sendgrid/sendgrid-go/helpers/mail/stub.go
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Email/vendor/github.com/sendgrid/sendgrid-go/helpers/mail/stub.go
@@ -7,8 +7,6 @@
// Package mail is a stub of github.com/sendgrid/sendgrid-go/helpers/mail, generated by depstubber.
package mail
-import ()
-
type Asm struct {
GroupID int
GroupsToDisplay []int
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApiCoreV1/vendor/k8s.io/api/core/v1/stub.go b/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApiCoreV1/vendor/k8s.io/api/core/v1/stub.go
index 1c9a8e0dfdd4..e5f5c4ffa01b 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApiCoreV1/vendor/k8s.io/api/core/v1/stub.go
+++ b/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApiCoreV1/vendor/k8s.io/api/core/v1/stub.go
@@ -7,8 +7,6 @@
// Package core is a stub of k8s.io/api/core/v1, generated by depstubber.
package core
-import ()
-
type Secret struct {
TypeMeta interface{}
ObjectMeta interface{}
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApiCoreV1/vendor/k8s.io/apimachinery/pkg/runtime/stub.go b/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApiCoreV1/vendor/k8s.io/apimachinery/pkg/runtime/stub.go
index bb7bf0431974..2655b31d450a 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApiCoreV1/vendor/k8s.io/apimachinery/pkg/runtime/stub.go
+++ b/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApiCoreV1/vendor/k8s.io/apimachinery/pkg/runtime/stub.go
@@ -7,8 +7,6 @@
// Package runtime is a stub of k8s.io/apimachinery/pkg/runtime, generated by depstubber.
package runtime
-import ()
-
type ProtobufMarshaller interface {
MarshalTo(_ []byte) (int, error)
}
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApimachineryPkgRuntime/vendor/k8s.io/apimachinery/pkg/runtime/schema/stub.go b/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApimachineryPkgRuntime/vendor/k8s.io/apimachinery/pkg/runtime/schema/stub.go
index 58c86777a1cd..2d58b01f8eaa 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApimachineryPkgRuntime/vendor/k8s.io/apimachinery/pkg/runtime/schema/stub.go
+++ b/go/ql/test/library-tests/semmle/go/frameworks/K8sIoApimachineryPkgRuntime/vendor/k8s.io/apimachinery/pkg/runtime/schema/stub.go
@@ -7,8 +7,6 @@
// Package schema is a stub of k8s.io/apimachinery/pkg/runtime/schema, generated by depstubber.
package schema
-import ()
-
type GroupKind struct {
Group string
Kind string
diff --git a/go/ql/test/query-tests/Security/CWE-089/vendor/go.mongodb.org/mongo-driver/bson/primitive/stub.go b/go/ql/test/query-tests/Security/CWE-089/vendor/go.mongodb.org/mongo-driver/bson/primitive/stub.go
index 6f07aaff4ee2..3349209245aa 100644
--- a/go/ql/test/query-tests/Security/CWE-089/vendor/go.mongodb.org/mongo-driver/bson/primitive/stub.go
+++ b/go/ql/test/query-tests/Security/CWE-089/vendor/go.mongodb.org/mongo-driver/bson/primitive/stub.go
@@ -7,8 +7,6 @@
// Package primitive is a stub of go.mongodb.org/mongo-driver/bson/primitive, generated by depstubber.
package primitive
-import ()
-
type D []E
func (_ D) Map() M {
diff --git a/go/ql/test/query-tests/Security/CWE-312/vendor/github.com/golang/glog/stub.go b/go/ql/test/query-tests/Security/CWE-312/vendor/github.com/golang/glog/stub.go
index cdd12b34901a..932a5e6fc257 100644
--- a/go/ql/test/query-tests/Security/CWE-312/vendor/github.com/golang/glog/stub.go
+++ b/go/ql/test/query-tests/Security/CWE-312/vendor/github.com/golang/glog/stub.go
@@ -7,6 +7,4 @@
// Package glog is a stub of github.com/golang/glog, generated by depstubber.
package glog
-import ()
-
func Info(_ ...interface{}) {}
diff --git a/go/ql/test/query-tests/Security/CWE-312/vendor/k8s.io/klog/stub.go b/go/ql/test/query-tests/Security/CWE-312/vendor/k8s.io/klog/stub.go
index 7dbaa5001fc3..db9ede2303e3 100644
--- a/go/ql/test/query-tests/Security/CWE-312/vendor/k8s.io/klog/stub.go
+++ b/go/ql/test/query-tests/Security/CWE-312/vendor/k8s.io/klog/stub.go
@@ -7,6 +7,4 @@
// Package klog is a stub of k8s.io/klog, generated by depstubber.
package klog
-import ()
-
func Info(_ ...interface{}) {}
diff --git a/go/ql/test/query-tests/Security/CWE-640/vendor/github.com/sendgrid/sendgrid-go/helpers/mail/stub.go b/go/ql/test/query-tests/Security/CWE-640/vendor/github.com/sendgrid/sendgrid-go/helpers/mail/stub.go
index cd1956cecc05..f5d9d9bbbef2 100644
--- a/go/ql/test/query-tests/Security/CWE-640/vendor/github.com/sendgrid/sendgrid-go/helpers/mail/stub.go
+++ b/go/ql/test/query-tests/Security/CWE-640/vendor/github.com/sendgrid/sendgrid-go/helpers/mail/stub.go
@@ -7,8 +7,6 @@
// Package mail is a stub of github.com/sendgrid/sendgrid-go/helpers/mail, generated by depstubber.
package mail
-import ()
-
type Asm struct {
GroupID int
GroupsToDisplay []int
diff --git a/go/ql/test/query-tests/Security/CWE-643/vendor/github.com/antchfx/htmlquery/stub.go b/go/ql/test/query-tests/Security/CWE-643/vendor/github.com/antchfx/htmlquery/stub.go
index 0bac0acfe55c..7a41d8f98837 100644
--- a/go/ql/test/query-tests/Security/CWE-643/vendor/github.com/antchfx/htmlquery/stub.go
+++ b/go/ql/test/query-tests/Security/CWE-643/vendor/github.com/antchfx/htmlquery/stub.go
@@ -7,8 +7,6 @@
// Package htmlquery is a stub of github.com/antchfx/htmlquery, generated by depstubber.
package htmlquery
-import ()
-
func Find(_ interface{}, _ string) []interface{} {
return nil
}
diff --git a/go/ql/test/query-tests/Security/CWE-643/vendor/github.com/antchfx/jsonquery/stub.go b/go/ql/test/query-tests/Security/CWE-643/vendor/github.com/antchfx/jsonquery/stub.go
index 2948daae031c..4abcf002faa9 100644
--- a/go/ql/test/query-tests/Security/CWE-643/vendor/github.com/antchfx/jsonquery/stub.go
+++ b/go/ql/test/query-tests/Security/CWE-643/vendor/github.com/antchfx/jsonquery/stub.go
@@ -7,8 +7,6 @@
// Package jsonquery is a stub of github.com/antchfx/jsonquery, generated by depstubber.
package jsonquery
-import ()
-
func Find(_ *Node, _ string) []*Node {
return nil
}
diff --git a/go/ql/test/query-tests/filters/ClassifyFiles/vendor/github.com/onsi/ginkgo/stub.go b/go/ql/test/query-tests/filters/ClassifyFiles/vendor/github.com/onsi/ginkgo/stub.go
index fcf8b8b5683d..20f179c90028 100644
--- a/go/ql/test/query-tests/filters/ClassifyFiles/vendor/github.com/onsi/ginkgo/stub.go
+++ b/go/ql/test/query-tests/filters/ClassifyFiles/vendor/github.com/onsi/ginkgo/stub.go
@@ -7,8 +7,6 @@
// Package ginkgo is a stub of github.com/onsi/ginkgo, generated by depstubber.
package ginkgo
-import ()
-
func Fail(_ string, _ ...int) {}
type GinkgoTestingT interface {
diff --git a/go/ql/test/query-tests/filters/ClassifyFiles/vendor/github.com/onsi/gomega/stub.go b/go/ql/test/query-tests/filters/ClassifyFiles/vendor/github.com/onsi/gomega/stub.go
index 27fa1387b46a..61c9db70ad61 100644
--- a/go/ql/test/query-tests/filters/ClassifyFiles/vendor/github.com/onsi/gomega/stub.go
+++ b/go/ql/test/query-tests/filters/ClassifyFiles/vendor/github.com/onsi/gomega/stub.go
@@ -7,6 +7,4 @@
// Package gomega is a stub of github.com/onsi/gomega, generated by depstubber.
package gomega
-import ()
-
func RegisterFailHandler(_ interface{}) {}
From 6147f0a8734c26ac0912f3404301e0da0c730564 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Thu, 20 Mar 2025 12:32:56 +0000
Subject: [PATCH 007/409] Fix outdated depstubber command
---
.../semmle/go/frameworks/SQL/pg.go | 2 +-
.../vendor/github.com/go-pg/pg/orm/stub.go | 45 ++++++++++++-------
2 files changed, 30 insertions(+), 17 deletions(-)
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/pg.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/pg.go
index 09ffa084fe0e..7cd76f715c99 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/pg.go
+++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/pg.go
@@ -1,7 +1,7 @@
package main
//go:generate depstubber -vendor github.com/go-pg/pg Conn,DB,Tx Q
-//go:generate depstubber -vendor github.com/go-pg/pg/orm Query Q
+//go:generate depstubber -vendor github.com/go-pg/pg/orm Query,Formatter Q
//go:generate depstubber -vendor github.com/go-pg/pg/v9 Conn,DB,Tx Q
import (
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/github.com/go-pg/pg/orm/stub.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/github.com/go-pg/pg/orm/stub.go
index 1d049c8a9a3c..1214ad0492da 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/github.com/go-pg/pg/orm/stub.go
+++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/github.com/go-pg/pg/orm/stub.go
@@ -2,7 +2,7 @@
// This is a simple stub for github.com/go-pg/pg/orm, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
-// Source: github.com/go-pg/pg/orm (exports: Query, Formatter; functions: Q)
+// Source: github.com/go-pg/pg/orm (exports: Query,Formatter; functions: Q)
// Package orm is a stub of github.com/go-pg/pg/orm, generated by depstubber.
package orm
@@ -94,6 +94,34 @@ func (_ *Field) Value(_ reflect.Value) reflect.Value {
return reflect.Value{}
}
+type Formatter struct{}
+
+func (_ Formatter) Append(_ []byte, _ string, _ ...interface{}) []byte {
+ return nil
+}
+
+func (_ Formatter) AppendBytes(_ []byte, _ []byte, _ ...interface{}) []byte {
+ return nil
+}
+
+func (_ Formatter) FormatQuery(_ []byte, _ string, _ ...interface{}) []byte {
+ return nil
+}
+
+func (_ Formatter) Param(_ string) interface{} {
+ return nil
+}
+
+func (_ Formatter) String() string {
+ return ""
+}
+
+func (_ Formatter) WithParam(_ string, _ interface{}) Formatter {
+ return Formatter{}
+}
+
+func (_ *Formatter) SetParam(_ string, _ interface{}) {}
+
type Method struct {
Index int
}
@@ -491,18 +519,3 @@ type TableModel interface {
Table() *Table
Value() reflect.Value
}
-
-type Formatter struct {
-}
-
-func (f Formatter) Append(dst []byte, src string, params ...interface{}) []byte {
- return nil
-}
-
-func (f Formatter) AppendBytes(dst, src []byte, params ...interface{}) []byte {
- return nil
-}
-
-func (f Formatter) FormatQuery(dst []byte, query string, params ...interface{}) []byte {
- return nil
-}
From 7e04a9f6c0e33e06e21d178a224201dd5b3085b8 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Thu, 20 Mar 2025 12:33:39 +0000
Subject: [PATCH 008/409] Improve stubs (made by old version of depstubber?)
---
.../github.com/codeskyblue/go-sh/stub.go | 45 ++++---------
.../vendor/golang.org/x/crypto/ssh/stub.go | 67 +++++--------------
2 files changed, 31 insertions(+), 81 deletions(-)
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SystemCommandExecutors/vendor/github.com/codeskyblue/go-sh/stub.go b/go/ql/test/library-tests/semmle/go/frameworks/SystemCommandExecutors/vendor/github.com/codeskyblue/go-sh/stub.go
index 229a21145693..ae0660e5633c 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/SystemCommandExecutors/vendor/github.com/codeskyblue/go-sh/stub.go
+++ b/go/ql/test/library-tests/semmle/go/frameworks/SystemCommandExecutors/vendor/github.com/codeskyblue/go-sh/stub.go
@@ -1,10 +1,11 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/codeskyblue/go-sh, strictly for use in testing.
+// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/codeskyblue/go-sh (exports: ; functions: Command,InteractiveSession)
-// Package go_sh is a stub of github.com/codeskyblue/go-sh, generated by depstubber.
-package go_sh
+// Package go_pkg is a stub of github.com/codeskyblue/go-sh, generated by depstubber.
+package go_pkg
import (
io "io"
@@ -32,15 +33,11 @@ type Session struct {
func (_ *Session) Alias(_ string, _ string, _ ...string) {}
-func (_ *Session) Call(_ string, _ ...interface{}) interface {
- Error() string
-} {
+func (_ *Session) Call(_ string, _ ...interface{}) error {
return nil
}
-func (_ *Session) CombinedOutput() ([]uint8, interface {
- Error() string
-}) {
+func (_ *Session) CombinedOutput() ([]byte, error) {
return nil, nil
}
@@ -50,15 +47,11 @@ func (_ *Session) Command(_ string, _ ...interface{}) *Session {
func (_ *Session) Kill(_ os.Signal) {}
-func (_ *Session) Output() ([]uint8, interface {
- Error() string
-}) {
+func (_ *Session) Output() ([]byte, error) {
return nil, nil
}
-func (_ *Session) Run() interface {
- Error() string
-} {
+func (_ *Session) Run() error {
return nil
}
@@ -82,9 +75,7 @@ func (_ *Session) SetTimeout(_ time.Duration) *Session {
return nil
}
-func (_ *Session) Start() interface {
- Error() string
-} {
+func (_ *Session) Start() error {
return nil
}
@@ -92,32 +83,22 @@ func (_ *Session) Test(_ string, _ string) bool {
return false
}
-func (_ *Session) UnmarshalJSON(_ interface{}) interface {
- Error() string
-} {
+func (_ *Session) UnmarshalJSON(_ interface{}) error {
return nil
}
-func (_ *Session) UnmarshalXML(_ interface{}) interface {
- Error() string
-} {
+func (_ *Session) UnmarshalXML(_ interface{}) error {
return nil
}
-func (_ *Session) Wait() interface {
- Error() string
-} {
+func (_ *Session) Wait() error {
return nil
}
-func (_ *Session) WaitTimeout(_ time.Duration) interface {
- Error() string
-} {
+func (_ *Session) WaitTimeout(_ time.Duration) error {
return nil
}
-func (_ *Session) WriteStdout(_ string) interface {
- Error() string
-} {
+func (_ *Session) WriteStdout(_ string) error {
return nil
}
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SystemCommandExecutors/vendor/golang.org/x/crypto/ssh/stub.go b/go/ql/test/library-tests/semmle/go/frameworks/SystemCommandExecutors/vendor/golang.org/x/crypto/ssh/stub.go
index 9d1aab65e3c9..0c0c3d879bb8 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/SystemCommandExecutors/vendor/golang.org/x/crypto/ssh/stub.go
+++ b/go/ql/test/library-tests/semmle/go/frameworks/SystemCommandExecutors/vendor/golang.org/x/crypto/ssh/stub.go
@@ -1,6 +1,7 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for golang.org/x/crypto/ssh, strictly for use in testing.
+// See the LICENSE file for information about the licensing of the original library.
// Source: golang.org/x/crypto/ssh (exports: Session; functions: )
// Package ssh is a stub of golang.org/x/crypto/ssh, generated by depstubber.
@@ -16,102 +17,70 @@ type Session struct {
Stderr io.Writer
}
-func (_ *Session) Close() interface {
- Error() string
-} {
+func (_ *Session) Close() error {
return nil
}
-func (_ *Session) CombinedOutput(_ string) ([]uint8, interface {
- Error() string
-}) {
+func (_ *Session) CombinedOutput(_ string) ([]byte, error) {
return nil, nil
}
-func (_ *Session) Output(_ string) ([]uint8, interface {
- Error() string
-}) {
+func (_ *Session) Output(_ string) ([]byte, error) {
return nil, nil
}
-func (_ *Session) RequestPty(_ string, _ int, _ int, _ TerminalModes) interface {
- Error() string
-} {
+func (_ *Session) RequestPty(_ string, _ int, _ int, _ TerminalModes) error {
return nil
}
-func (_ *Session) RequestSubsystem(_ string) interface {
- Error() string
-} {
+func (_ *Session) RequestSubsystem(_ string) error {
return nil
}
-func (_ *Session) Run(_ string) interface {
- Error() string
-} {
+func (_ *Session) Run(_ string) error {
return nil
}
-func (_ *Session) SendRequest(_ string, _ bool, _ []uint8) (bool, interface {
- Error() string
-}) {
+func (_ *Session) SendRequest(_ string, _ bool, _ []byte) (bool, error) {
return false, nil
}
-func (_ *Session) Setenv(_ string, _ string) interface {
- Error() string
-} {
+func (_ *Session) Setenv(_ string, _ string) error {
return nil
}
-func (_ *Session) Shell() interface {
- Error() string
-} {
+func (_ *Session) Shell() error {
return nil
}
-func (_ *Session) Signal(_ Signal) interface {
- Error() string
-} {
+func (_ *Session) Signal(_ Signal) error {
return nil
}
-func (_ *Session) Start(_ string) interface {
- Error() string
-} {
+func (_ *Session) Start(_ string) error {
return nil
}
-func (_ *Session) StderrPipe() (io.Reader, interface {
- Error() string
-}) {
+func (_ *Session) StderrPipe() (io.Reader, error) {
return nil, nil
}
-func (_ *Session) StdinPipe() (io.WriteCloser, interface {
- Error() string
-}) {
+func (_ *Session) StdinPipe() (io.WriteCloser, error) {
return nil, nil
}
-func (_ *Session) StdoutPipe() (io.Reader, interface {
- Error() string
-}) {
+func (_ *Session) StdoutPipe() (io.Reader, error) {
return nil, nil
}
-func (_ *Session) Wait() interface {
- Error() string
-} {
+func (_ *Session) Wait() error {
return nil
}
-func (_ *Session) WindowChange(_ int, _ int) interface {
- Error() string
-} {
+func (_ *Session) WindowChange(_ int, _ int) error {
return nil
}
type Signal string
-type TerminalModes map[uint8]uint32
+type TerminalModes map[byte]uint32
From 19f009ae0807d1d143d1ac648b65121cc971f1d1 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 10 Dec 2024 16:48:13 +0000
Subject: [PATCH 009/409] Rust: Add tests for various kinds of dangling
pointers.
---
.../security/CWE-825/deallocation.rs | 149 +++++++
.../query-tests/security/CWE-825/lifetime.rs | 410 ++++++++++++++++++
.../test/query-tests/security/CWE-825/main.rs | 157 +++++++
.../query-tests/security/CWE-825/options.yml | 3 +
.../security/CWE-825/rust-toolchain.toml | 2 +
5 files changed, 721 insertions(+)
create mode 100644 rust/ql/test/query-tests/security/CWE-825/deallocation.rs
create mode 100644 rust/ql/test/query-tests/security/CWE-825/lifetime.rs
create mode 100644 rust/ql/test/query-tests/security/CWE-825/main.rs
create mode 100644 rust/ql/test/query-tests/security/CWE-825/options.yml
create mode 100644 rust/ql/test/query-tests/security/CWE-825/rust-toolchain.toml
diff --git a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
new file mode 100644
index 000000000000..1ad8d72c0082
--- /dev/null
+++ b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
@@ -0,0 +1,149 @@
+
+// --- std::alloc ---
+
+pub fn test_alloc(do_dangerous_writes: bool) {
+ let layout = std::alloc::Layout::new::();
+ unsafe {
+ let m1 = std::alloc::alloc(layout); // *mut u8
+ let m2 = m1 as *mut i64; // *mut i64
+ *m2 = 1; // GOOD
+
+ let v1 = *m1; // GOOD
+ let v2 = *m2; // GOOD
+ let v3 = std::ptr::read::(m1); // GOOD
+ let v4 = std::ptr::read::(m2); // GOOD
+ println!(" v1 = {v1}");
+ println!(" v2 = {v2}");
+ println!(" v3 = {v3}");
+ println!(" v4 = {v4}");
+
+ std::alloc::dealloc(m1, layout); // m1, m2 are now dangling
+
+ let v5 = *m1; // $ MISSING: Alert
+ let v6 = *m2; // $ MISSING: Alert
+ let v7 = std::ptr::read::(m1); // $ MISSING: Alert
+ let v8 = std::ptr::read::(m2); // $ MISSING: Alert
+ println!(" v5 = {v5} (!)"); // corrupt in practice
+ println!(" v6 = {v6} (!)"); // corrupt in practice
+ println!(" v7 = {v7} (!)"); // corrupt in practice
+ println!(" v8 = {v8} (!)"); // corrupt in practice
+
+ if do_dangerous_writes {
+ *m1 = 2; // $ MISSING: Alert
+ *m2 = 3; // $ MISSING: Alert
+ std::ptr::write::(m1, 4); // $ MISSING: Alert
+ std::ptr::write::(m2, 5); // $ MISSING: Alert
+ }
+ }
+}
+
+pub fn test_alloc_array(do_dangerous_writes: bool) {
+ let layout = std::alloc::Layout::new::<[u8; 10]>();
+ unsafe {
+ let m1 = std::alloc::alloc(layout);
+ let m2 = m1 as *mut [u8; 10];
+ (*m2)[0] = 4; // GOOD
+ (*m2)[1] = 5; // GOOD
+
+ let v1 = (*m2)[0]; // GOOD
+ let v2 = (*m2)[1]; // GOOD
+ println!(" v1 = {v1}");
+ println!(" v2 = {v2}");
+
+ std::alloc::dealloc(m2 as *mut u8, layout); // m1, m2 are now dangling
+
+ let v3 = (*m2)[0]; // $ MISSING: Alert
+ let v4 = (*m2)[1]; // $ MISSING: Alert
+ println!(" v3 = {v3} (!)"); // corrupt in practice
+ println!(" v4 = {v4} (!)"); // corrupt in practice
+
+ if do_dangerous_writes {
+ (*m2)[0] = 3; // $ MISSING: Alert
+ (*m2)[1] = 4; // $ MISSING: Alert
+ std::ptr::write::(m1, 5); // $ MISSING: Alert
+ std::ptr::write::<[u8; 10]>(m2, [6; 10]); // $ MISSING: Alert
+ }
+ }
+}
+
+// --- libc::malloc ---
+
+pub fn test_libc() {
+ unsafe {
+ let my_ptr = libc::malloc(256) as *mut i64;
+ *my_ptr = 10;
+
+ let v1 = *my_ptr; // GOOD
+ println!(" v1 = {v1}");
+
+ libc::free(my_ptr as *mut libc::c_void); // my_ptr is now dangling
+
+ let v2 = *my_ptr; // $ MISSING: Alert
+ println!(" v2 = {v2} (!)"); // corrupt in practice
+ }
+}
+
+// --- std::ptr ---
+
+pub fn test_ptr_invalid(do_dangerous_accesses: bool) {
+ let p1: *const i64 = std::ptr::dangling();
+ let p2: *mut i64 = std::ptr::dangling_mut();
+ let p3: *const i64 = std::ptr::null();
+
+ if do_dangerous_accesses {
+ unsafe {
+ // (a segmentation fault occurs in the code below)
+ let v1 = *p1; // $ MISSING: Alert
+ let v2 = *p2; // $ MISSING: Alert
+ let v3 = *p3; // $ MISSING: Alert
+ println!(" v1 = {v1} (!)");
+ println!(" v2 = {v2} (!)");
+ println!(" v3 = {v3} (!)");
+ }
+ }
+}
+
+// --- drop ---
+
+struct MyBuffer {
+ data: Vec
+}
+
+pub fn test_drop() {
+ let my_buffer = MyBuffer { data: vec!(1, 2, 3) };
+ let p1 = std::ptr::addr_of!(my_buffer);
+
+ unsafe {
+ let v1 = (*p1).data[0]; // GOOD
+ println!(" v1 = {v1}");
+ }
+
+ drop(my_buffer); // explicitly destructs the `my_buffer` variable
+
+ unsafe {
+ let v2 = (*p1).data[0]; // $ MISSING: Alert
+ println!(" v2 = {v2} (!)"); // corrupt in practice
+ }
+}
+
+pub fn test_ptr_drop() {
+ let layout = std::alloc::Layout::new::>();
+ unsafe {
+ let p1 = std::alloc::alloc(layout) as *mut Vec; // *mut i64
+ let p2 = p1;
+
+ *p1 = vec!(1, 2, 3);
+
+ let v1 = (*p1)[0]; // GOOD
+ let v2 = (*p2)[0]; // GOOD
+ println!(" v1 = {v1}");
+ println!(" v2 = {v2}");
+
+ std::ptr::drop_in_place(p1); // explicitly destructs the pointed-to `m2`
+
+ let v3 = (*p1)[0]; // $ MISSING: Alert
+ let v4 = (*p2)[0]; // $ MISSING: Alert
+ println!(" v3 = {v3} (!)"); // corrupt in practice
+ println!(" v4 = {v4} (!)"); // corrupt in practice
+ }
+}
diff --git a/rust/ql/test/query-tests/security/CWE-825/lifetime.rs b/rust/ql/test/query-tests/security/CWE-825/lifetime.rs
new file mode 100644
index 000000000000..49b0678b0359
--- /dev/null
+++ b/rust/ql/test/query-tests/security/CWE-825/lifetime.rs
@@ -0,0 +1,410 @@
+
+fn use_the_stack() {
+ let _buffer: [u8; 256] = [0xFF; 256];
+}
+
+struct MyValue {
+ value: i64
+}
+
+impl Drop for MyValue {
+ fn drop(&mut self) {
+ println!(" drop MyValue '{}'", self.value)
+ }
+}
+
+// --- local dangling ---
+
+fn get_local_dangling() -> *const i64 {
+ let my_local1: i64 = 1;
+
+ return &my_local1;
+} // (return value immediately becomes dangling)
+
+fn get_local_dangling_mut() -> *mut i64 {
+ let mut my_local2: i64 = 2;
+
+ return &mut my_local2;
+} // (return value immediately becomes dangling)
+
+fn get_local_dangling_raw_const() -> *const i64 {
+ let my_local3: i64 = 3;
+
+ return &raw const my_local3;
+} // (return value immediately becomes dangling)
+
+fn get_local_dangling_raw_mut() -> *mut i64 {
+ let mut my_local4: i64 = 4;
+
+ return &raw mut my_local4;
+} // (return value immediately becomes dangling)
+
+fn get_param_dangling(param5: i64) -> *const i64 {
+ return ¶m5;
+} // (return value immediately becomes dangling)
+
+fn get_local_field_dangling() -> *const i64 {
+ let val: MyValue;
+
+ val = MyValue { value: 6 };
+ return &val.value;
+}
+
+pub fn test_local_dangling() {
+ let p1 = get_local_dangling();
+ let p2 = get_local_dangling_mut();
+ let p3 = get_local_dangling_raw_const();
+ let p4 = get_local_dangling_raw_mut();
+ let p5 = get_param_dangling(5);
+ let p6 = get_local_field_dangling();
+ let p7: *const i64;
+ {
+ let my_local7 = 7;
+ p7 = &raw const my_local7;
+ } // (my_local goes out of scope, thus p7 is dangling)
+
+ use_the_stack();
+
+ unsafe {
+ let v1 = *p1; // $ MISSING: Alert
+ let v2 = *p2; // $ MISSING: Alert
+ let v3 = *p3; // $ MISSING: Alert
+ let v4 = *p4; // $ MISSING: Alert
+ let v5 = *p5; // $ MISSING: Alert
+ let v6 = *p6; // $ MISSING: Alert
+ let v7 = *p7; // $ MISSING: Alert
+ *p2 = 8; // $ MISSING: Alert
+ *p4 = 9; // $ MISSING: Alert
+
+ println!(" v1 = {v1} (!)"); // corrupt in practice
+ println!(" v2 = {v2} (!)"); // corrupt in practice
+ println!(" v3 = {v3} (!)"); // corrupt in practice
+ println!(" v4 = {v4} (!)"); // corrupt in practice
+ println!(" v5 = {v5} (!)"); // corrupt in practice
+ println!(" v6 = {v6} (!)"); // corrupt in practice
+ println!(" v7 = {v7} (!)");
+ }
+}
+
+// --- local in scope ---
+
+fn use_pointers(p1: *const i64, p2: *mut i64) {
+ let p3: *const i64;
+ let my_local1 = 1;
+ p3 = &my_local1;
+
+ use_the_stack();
+
+ unsafe {
+ let v1 = *p1; // GOOD
+ let v2 = *p2; // GOOD
+ let v3 = *p3; // GOOD
+ *p2 = 2; // GOOD
+ println!(" v1 = {v1}");
+ println!(" v2 = {v2}");
+ println!(" v3 = {v3}");
+ }
+}
+
+pub fn test_local_in_scope() {
+ let my_local3: i64 = 3;
+ let mut my_local_mut4: i64 = 4;
+
+ use_pointers(&my_local3, &mut my_local_mut4);
+}
+
+// --- static lifetime ---
+
+const MY_GLOBAL_CONST: i64 = 1;
+
+fn get_const() -> *const i64 {
+ return &MY_GLOBAL_CONST;
+}
+
+static mut MY_GLOBAL_STATIC: i64 = 2;
+
+fn get_static_mut() -> *mut i64 {
+ unsafe {
+ return &mut MY_GLOBAL_STATIC;
+ }
+}
+
+pub fn test_static() {
+ let p1 = get_const();
+ let p2 = get_static_mut();
+
+ use_the_stack();
+
+ unsafe {
+ let v1 = *p1; // GOOD
+ let v2 = *p2; // GOOD
+ *p2 = 3; // GOOD
+ println!(" v1 = {v1}");
+ println!(" v2 = {v2}");
+ }
+}
+
+// --- call contexts ---
+
+fn access_ptr_1(ptr: *const i64) {
+ // only called with `ptr` safe
+ unsafe {
+ let v1 = *ptr; // GOOD
+ println!(" v1 = {v1}");
+ }
+}
+
+fn access_ptr_2(ptr: *const i64) {
+ // only called with `ptr` dangling
+ unsafe {
+ let v2 = *ptr; // $ MISSING: Alert
+ println!(" v2 = {v2} (!)"); // corrupt in practice
+ }
+}
+
+fn access_ptr_3(ptr: *const i64) {
+ // called from contexts with `ptr` safe and dangling
+ unsafe {
+ let v3 = *ptr; // $ MISSING: Alert
+ println!(" v3 = {v3} (!)"); // corrupt in practice (in one context)
+ }
+}
+
+fn access_and_get_dangling() -> *const i64 {
+ let my_local1 = 1;
+ let ptr = &my_local1;
+
+ access_ptr_1(ptr);
+ access_ptr_3(ptr);
+
+ return ptr;
+} // (returned pointer becomes dangling)
+
+pub fn test_call_contexts() {
+ let ptr = access_and_get_dangling();
+
+ use_the_stack();
+
+ access_ptr_2(ptr);
+ access_ptr_3(ptr);
+}
+
+// --- call contexts (recursive) ---
+
+fn access_ptr_rec(ptr_up: *const i64, count: i64) -> *const i64 {
+ let my_local_rec = count;
+ let ptr_ours = &my_local_rec;
+
+ if count < 5 {
+ let ptr_down = access_ptr_rec(ptr_ours, count + 1);
+
+ use_the_stack();
+
+ unsafe {
+ let v_up = *ptr_up; // GOOD
+ let v_ours = *ptr_ours; // GOOD
+ let v_down = *ptr_down; // $ MISSING: Alert
+ println!(" v_up = {v_up}");
+ println!(" v_ours = {v_ours}");
+ println!(" v_down = {v_down} (!)");
+ }
+ }
+
+ return ptr_ours;
+} // (returned pointer becomes dangling)
+
+pub fn test_call_contexts_rec() {
+ let my_local_rec2 = 1;
+ let ptr_start = &my_local_rec2;
+
+ _ = access_ptr_rec(ptr_start, 2);
+}
+
+// --- loops ---
+
+pub fn test_loop() {
+ let my_local1 = vec!(0);
+ let mut prev: *const Vec = &my_local1;
+
+ for i in 1..5 {
+ let my_local2 = vec!(i);
+
+ use_the_stack();
+
+ unsafe {
+ let v1 = (*prev)[0]; // $ MISSING: Alert
+ println!(" v1 = {v1} (!)"); // incorrect values in practice (except first iteration)
+ }
+
+ prev = &my_local2;
+ } // (my_local2 goes out of scope, thus prev is dangling)
+
+ unsafe {
+ let v2 = (*prev)[0]; // $ MISSING: Alert
+ println!(" v2 = {v2} (!)"); // corrupt in practice
+ }
+}
+
+// --- enum ---
+
+enum MyEnum {
+ Value(i64),
+}
+
+impl Drop for MyEnum {
+ fn drop(&mut self) {
+ println!(" drop MyEnum");
+ }
+}
+
+pub fn test_enum() {
+ let result: *const i64;
+
+ {
+ let e1 = MyEnum::Value(1);
+
+ result = match e1 {
+ MyEnum::Value(x) => { &x }
+ }; // (x goes out of scope, so result is dangling, I think; seen in real world code)
+
+ use_the_stack();
+
+ unsafe {
+ let v1 = *result; // $ MISSING: Alert
+ println!(" v1 = {v1}");
+ }
+ } // (e1 goes out of scope, so result is definitely dangling now)
+
+ use_the_stack();
+
+ unsafe {
+ let v2 = *result; // $ MISSING: Alert
+ println!(" v2 = {v2}"); // dropped in practice
+ }
+}
+
+// --- std::ptr ---
+
+#[derive(Debug)]
+struct MyPair {
+ a: i64,
+ b: i64
+}
+
+impl Drop for MyPair {
+ fn drop(&mut self) {
+ println!(" drop MyPair '{} {}'", self.a, self.b);
+ self.a = -1;
+ self.b = -1;
+ }
+}
+
+pub fn test_ptr_to_struct() {
+ let p1: *mut MyPair;
+ let p2: *const i64;
+ let p3: *mut i64;
+
+ {
+ let mut my_pair = MyPair { a: 1, b: 2};
+ p1 = std::ptr::addr_of_mut!(my_pair);
+ p2 = std::ptr::addr_of!(my_pair.a);
+ p3 = std::ptr::addr_of_mut!(my_pair.b);
+
+ unsafe {
+ let v1 = (*p1).a; // GOOD
+ let v2 = (*p1).b; // GOOD
+ let v3 = *p2; // GOOD
+ let v4 = *p3; // GOOD
+ (*p1).a = 3; // GOOD
+ (*p1).b = 4; // GOOD
+ *p3 = 5; // GOOD
+ println!(" v1 = {v1}");
+ println!(" v2 = {v2}");
+ println!(" v3 = {v3}");
+ println!(" v4 = {v4}");
+ }
+ }; // my_pair goes out of scope, thus p1, p2, p3 are dangling
+
+ use_the_stack();
+
+ unsafe {
+ let v5 = (*p1).a; // $ MISSING: Alert
+ let v6 = (*p1).b; // $ MISSING: Alert
+ let v7 = *p2; // $ MISSING: Alert
+ let v8 = *p3; // $ MISSING: Alert
+ (*p1).a = 6; // $ MISSING: Alert
+ (*p1).b = 7; // $ MISSING: Alert
+ *p3 = 8; // $ MISSING: Alert
+ println!(" v5 = {v5} (!)"); // dropped in practice
+ println!(" v6 = {v6} (!)"); // dropped in practice
+ println!(" v7 = {v7} (!)"); // dropped in practice
+ println!(" v8 = {v8} (!)"); // dropped in practice
+ }
+}
+
+fn get_ptr_from_ref(val: i32) -> *const i32 {
+ let my_val = val;
+ let r1: &i32 = &my_val;
+ let p1: *const i32 = std::ptr::from_ref(r1);
+
+ unsafe {
+ let v1 = *p1; // GOOD
+ println!(" v1 = {v1}");
+ }
+
+ return p1;
+} // (returned pointer becomes dangling)
+
+pub fn test_ptr_from_ref() {
+ let p1 = get_ptr_from_ref(1);
+
+ use_the_stack();
+
+ unsafe {
+ let v2 = *p1; // $ MISSING: Alert
+ let v3 = *get_ptr_from_ref(2); // $ MISSING: Alert
+ println!(" v2 = {v2} (!)"); // corrupt in practice
+ println!(" v3 = {v3} (!)");
+ }
+}
+
+// --- std::rc (reference counting pointer) ---
+
+pub fn test_rc() {
+ let p1: *const i64;
+ let p2: *const i64;
+
+ {
+ let rc1: std::rc::Rc = std::rc::Rc::new(1);
+ p1 = std::rc::Rc::::as_ptr(&rc1);
+
+ {
+ let rc2: std::rc::Rc = std::rc::Rc::clone(&rc1);
+ p2 = std::rc::Rc::::as_ptr(&rc2);
+
+ unsafe {
+ let v1 = *p1; // GOOD
+ let v2 = *p2; // GOOD
+ println!(" v1 = {v1}");
+ println!(" v2 = {v2}");
+ }
+ } // rc2 goes out of scope, but the reference count is still 1 so the pointer remains valid
+
+ unsafe {
+ let v3 = *p1; // GOOD
+ let v4 = *p2; // GOOD
+ println!(" v3 = {v3}");
+ println!(" v4 = {v4}");
+ }
+ } // rc1 go out of scope, the reference count is 0, so p1, p2 are dangling
+
+ unsafe {
+ let v5 = *p1; // $ MISSING: Alert
+ let v6 = *p2; // $ MISSING: Alert
+ println!(" v5 = {v5} (!)"); // corrupt in practice
+ println!(" v6 = {v6} (!)"); // corrupt in practice
+ }
+
+ // note: simialar things are likely possible with Ref, RefMut, RefCell,
+ // Vec and others.
+}
diff --git a/rust/ql/test/query-tests/security/CWE-825/main.rs b/rust/ql/test/query-tests/security/CWE-825/main.rs
new file mode 100644
index 000000000000..e7a2154c3262
--- /dev/null
+++ b/rust/ql/test/query-tests/security/CWE-825/main.rs
@@ -0,0 +1,157 @@
+#![feature(box_as_ptr)]
+#![feature(box_into_inner)]
+
+mod deallocation;
+use deallocation::*;
+mod lifetime;
+use lifetime::*;
+
+fn use_the_heap() {
+ let _a = Box::new(0x7FFFFFFF);
+ let _b = Box::new(0x7FFFFFFF);
+}
+
+// --- boxes ---
+
+pub fn test_boxes_into() {
+ let b1: Box = Box::new(7); // b1 owns the memory for '50'
+ let p1 = Box::as_ptr(&b1); // b1 still owns the memory
+
+ unsafe {
+ let v1 = *p1; // GOOD
+ println!(" v1 = {v1}");
+ }
+
+ let v2 = Box::into_inner(b1); // b1 is explicitly freed here, thus p1 is dangling
+ println!(" v2 = {v2}");
+
+ unsafe {
+ let v3 = *p1; // $ MISSING: Alert
+ println!(" v3 = {v3} (!)"); // corrupt in practice
+ }
+}
+
+pub fn test_boxes_1(do_dangerous_writes: bool) {
+ let p1: *const i64;
+ let p2: *const i64;
+ let p3: *mut i64;
+
+ {
+ let b1: Box = Box::new(1);
+ p1 = Box::into_raw(b1); // now owned by p1
+
+ let b2: Box = Box::new(2);
+ p2 = Box::as_ptr(&b2); // still owned by b2
+
+ let mut b3: Box = Box::new(3);
+ p3 = Box::as_mut_ptr(&mut b3); // still owned by b3
+
+ unsafe {
+ let v1 = *p1; // GOOD
+ let v2 = *p2; // GOOD
+ let v3 = *p3; // GOOD
+ *p3 = 4;
+
+ println!(" v1 = {v1}");
+ println!(" v2 = {v2}");
+ println!(" v3 = {v3}");
+ }
+ } // (b2, b3 go out of scope, thus p2, p3 are dangling)
+
+ unsafe {
+ let v4 = *p1; // GOOD
+ let v5 = *p2; // $ MISSING: Alert
+ let v6 = *p3; // $ MISSING: Alert
+
+ if do_dangerous_writes {
+ *p3 = 5; // $ MISSING: Alert
+ use_the_heap(); // "malloc: Heap corruption detected"
+ }
+
+ println!(" v4 = {v4}");
+ println!(" v5 = {v5} (!)"); // corrupt in practice
+ println!(" v6 = {v6} (!)"); // corrupt in practice
+ }
+}
+
+pub fn test_boxes_2() {
+ let b1: Box = Box::new(6); // b1 owns the memory
+ let p1 = Box::into_raw(b1); // now p1 owns the memory
+
+ unsafe {
+ let _b2 = Box::from_raw(p1); // now _b2 owns the memory
+
+ let v1 = *p1; // GOOD
+ println!(" v1 = {v1}");
+ } // (_b2 goes out of scope, thus the memory is freed and p1 is dangling)
+
+ unsafe {
+ let v2 = *p1; // $ MISSING: Alert
+ println!(" v2 = {v2} (!)"); // corrupt in practice
+ }
+}
+
+// --- main ---
+
+fn main() {
+ println!("test_boxes_into:");
+ test_boxes_into();
+
+ println!("test_boxes_1:");
+ test_boxes_1(false);
+
+ println!("test_boxes_2:");
+ test_boxes_2();
+
+ // ---
+
+ println!("test_alloc:");
+ test_alloc(false);
+
+ println!("test_alloc_array:");
+ test_alloc_array(false);
+
+ println!("test_libc:");
+ test_libc();
+
+ println!("test_ptr_invalid:");
+ test_ptr_invalid(false);
+
+ println!("test_drop:");
+ test_drop();
+
+ println!("test_ptr_drop:");
+ test_ptr_drop();
+
+ // ---
+
+ println!("test_local_dangling:");
+ test_local_dangling();
+
+ println!("test_local_in_scope:");
+ test_local_in_scope();
+
+ println!("test_static:");
+ test_static();
+
+ println!("test_call_contexts:");
+ test_call_contexts();
+
+ println!("test_call_contexts_rec:");
+ test_call_contexts_rec();
+
+ println!("test_loop:");
+ test_loop();
+
+ println!("test_enum:");
+ test_enum();
+
+ println!("test_ptr_to_struct:");
+ test_ptr_to_struct();
+
+ println!("test_ptr_from_ref:");
+ test_ptr_from_ref();
+
+ println!("test_rc:");
+ test_rc();
+}
diff --git a/rust/ql/test/query-tests/security/CWE-825/options.yml b/rust/ql/test/query-tests/security/CWE-825/options.yml
new file mode 100644
index 000000000000..95a17a53b431
--- /dev/null
+++ b/rust/ql/test/query-tests/security/CWE-825/options.yml
@@ -0,0 +1,3 @@
+qltest_cargo_check: true
+qltest_dependencies:
+ - libc = { version = "0.2.11" }
diff --git a/rust/ql/test/query-tests/security/CWE-825/rust-toolchain.toml b/rust/ql/test/query-tests/security/CWE-825/rust-toolchain.toml
new file mode 100644
index 000000000000..afeb59293258
--- /dev/null
+++ b/rust/ql/test/query-tests/security/CWE-825/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel = "nightly-2025-03-17"
From a139b3734cdb644e836f82e3258c467dd863fb37 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 13 Mar 2025 17:40:54 +0000
Subject: [PATCH 010/409] Rust: Split lang-core.model.yml into lang-core and
lang-alloc.
---
.../rust/frameworks/stdlib/lang-alloc.model.yml | 11 +++++++++++
.../codeql/rust/frameworks/stdlib/lang-core.model.yml | 6 ------
2 files changed, 11 insertions(+), 6 deletions(-)
create mode 100644 rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml
diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml
new file mode 100644
index 000000000000..4e8f86dae345
--- /dev/null
+++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml
@@ -0,0 +1,11 @@
+extensions:
+ - addsTo:
+ pack: codeql/rust-all
+ extensible: summaryModel
+ data:
+ # Fmt
+ - ["lang:alloc", "crate::fmt::format", "Argument[0]", "ReturnValue", "taint", "manual"]
+ # String
+ - ["lang:alloc", "::as_str", "Argument[self]", "ReturnValue", "taint", "manual"]
+ - ["lang:alloc", "::as_bytes", "Argument[self]", "ReturnValue", "taint", "manual"]
+ - ["lang:alloc", "<_ as crate::string::ToString>::to_string", "Argument[self]", "ReturnValue", "taint", "manual"]
diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
index a2f6b15ab2cc..fb11ff1e1220 100644
--- a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
+++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
@@ -3,8 +3,6 @@ extensions:
pack: codeql/rust-all
extensible: summaryModel
data:
- # Fmt
- - ["lang:alloc", "crate::fmt::format", "Argument[0]", "ReturnValue", "taint", "manual"]
# Iterator
- ["lang:core", "<[_]>::iter", "Argument[Self].Element", "ReturnValue.Element", "value", "manual"]
- ["lang:core", "<[_]>::iter_mut", "Argument[Self].Element", "ReturnValue.Element", "value", "manual"]
@@ -28,7 +26,3 @@ extensions:
- ["lang:core", "crate::ptr::write_volatile", "Argument[1]", "Argument[0].Reference", "value", "manual"]
# Str
- ["lang:core", "::parse", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
- # String
- - ["lang:alloc", "::as_str", "Argument[self]", "ReturnValue", "taint", "manual"]
- - ["lang:alloc", "::as_bytes", "Argument[self]", "ReturnValue", "taint", "manual"]
- - ["lang:alloc", "<_ as crate::string::ToString>::to_string", "Argument[self]", "ReturnValue", "taint", "manual"]
From dcd016f5be41301d9e55bdc8409ba57a9412cbff Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 13 Mar 2025 17:04:48 +0000
Subject: [PATCH 011/409] Rust: Initial version of the query.
---
.../frameworks/stdlib/lang-core.model.yml | 8 +++
.../AccessInvalidPointerExtensions.qll | 58 +++++++++++++++++++
.../security/CWE-825/AccessInvalidPointer.ql | 35 +++++++++++
rust/ql/src/queries/summary/Stats.qll | 1 +
.../CWE-825/AccessInvalidPointer.expected | 32 ++++++++++
.../CWE-825/AccessInvalidPointer.qlref | 4 ++
.../security/CWE-825/deallocation.rs | 12 ++--
7 files changed, 144 insertions(+), 6 deletions(-)
create mode 100644 rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
create mode 100644 rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
create mode 100644 rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
create mode 100644 rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.qlref
diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
index fb11ff1e1220..db1901bf8522 100644
--- a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
+++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
@@ -26,3 +26,11 @@ extensions:
- ["lang:core", "crate::ptr::write_volatile", "Argument[1]", "Argument[0].Reference", "value", "manual"]
# Str
- ["lang:core", "::parse", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
+ - addsTo:
+ pack: codeql/rust-all
+ extensible: sourceModel
+ data:
+ # Alloc
+ - ["lang:core", "crate::ptr::dangling", "ReturnValue", "pointer-invalidate", "manual"]
+ - ["lang:core", "crate::ptr::dangling_mut", "ReturnValue", "pointer-invalidate", "manual"]
+ - ["lang:core", "crate::ptr::null", "ReturnValue", "pointer-invalidate", "manual"]
diff --git a/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll b/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
new file mode 100644
index 000000000000..faf9de48deff
--- /dev/null
+++ b/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
@@ -0,0 +1,58 @@
+/**
+ * Provides classes and predicates for reasoning about accesses to invalid
+ * pointers.
+ */
+
+import rust
+private import codeql.rust.dataflow.DataFlow
+private import codeql.rust.dataflow.FlowSource
+private import codeql.rust.dataflow.FlowSink
+private import codeql.rust.Concepts
+
+/**
+ * Provides default sources, sinks and barriers for detecting accesses to
+ * invalid pointers, as well as extension points for adding your own.
+ */
+module AccessInvalidPointer {
+ /**
+ * A data flow source for invalid pointer accesses, that is, an operation
+ * where a pointer becomes invalid.
+ */
+ abstract class Source extends DataFlow::Node { }
+
+ /**
+ * A data flow sink for invalid pointer accesses, that is, a pointer
+ * dereference.
+ */
+ abstract class Sink extends QuerySink::Range {
+ override string getSinkType() { result = "AccessInvalidPointer" }
+ }
+
+ /**
+ * A barrier for invalid pointer accesses.
+ */
+ abstract class Barrier extends DataFlow::Node { }
+
+ /**
+ * A pointer invalidation from model data.
+ */
+ private class ModelsAsDataSource extends Source {
+ ModelsAsDataSource() { sourceNode(this, "pointer-invalidate") }
+ }
+
+ /**
+ * A pointer access using the unary `*` operator.
+ */
+ private class DereferenceSink extends Sink {
+ DereferenceSink() {
+ exists(PrefixExpr p | p.getOperatorName() = "*" and p.getExpr() = this.asExpr().getExpr())
+ }
+ }
+
+ /**
+ * A pointer access from model data.
+ */
+ private class ModelsAsDataSink extends Sink {
+ ModelsAsDataSink() { sinkNode(this, "pointer-access") }
+ }
+}
diff --git a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
new file mode 100644
index 000000000000..ba124c99d40f
--- /dev/null
+++ b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
@@ -0,0 +1,35 @@
+/**
+ * @name Access of invalid pointer
+ * @description Dereferencing an invalid or dangling pointer is undefined behavior and may cause memory corruption.
+ * @kind path-problem
+ * @problem.severity error
+ * @security-severity TODO
+ * @precision TODO
+ * @id rust/access-invalid-pointer
+ * @tags reliability
+ * security
+ * external/cwe/cwe-476
+ * external/cwe/cwe-825
+ */
+
+import rust
+import codeql.rust.dataflow.DataFlow
+import codeql.rust.security.AccessInvalidPointerExtensions
+import AccessInvalidPointerFlow::PathGraph
+
+/**
+ * A data flow configuration for accesses to invalid pointers.
+ */
+module AccessInvalidPointerConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node node) { node instanceof AccessInvalidPointer::Source }
+
+ predicate isSink(DataFlow::Node node) { node instanceof AccessInvalidPointer::Sink }
+
+ predicate isBarrier(DataFlow::Node barrier) { barrier instanceof AccessInvalidPointer::Barrier }
+}
+
+module AccessInvalidPointerFlow = DataFlow::Global;
+
+from AccessInvalidPointerFlow::PathNode sourceNode, AccessInvalidPointerFlow::PathNode sinkNode
+where AccessInvalidPointerFlow::flowPath(sourceNode, sinkNode)
+select sinkNode.getNode(), sourceNode, sinkNode, "This operation dereferences a pointer that may be $@.", sourceNode.getNode(), "invalid"
diff --git a/rust/ql/src/queries/summary/Stats.qll b/rust/ql/src/queries/summary/Stats.qll
index a2220398b415..f011dda2852e 100644
--- a/rust/ql/src/queries/summary/Stats.qll
+++ b/rust/ql/src/queries/summary/Stats.qll
@@ -12,6 +12,7 @@ private import codeql.rust.controlflow.internal.CfgConsistency as CfgConsistency
private import codeql.rust.dataflow.internal.DataFlowConsistency as DataFlowConsistency
private import codeql.rust.Concepts
// import all query extensions files, so that all extensions of `QuerySink` are found
+private import codeql.rust.security.AccessInvalidPointerExtensions
private import codeql.rust.security.CleartextLoggingExtensions
private import codeql.rust.security.SqlInjectionExtensions
private import codeql.rust.security.WeakSensitiveDataHashingExtensions
diff --git a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
new file mode 100644
index 000000000000..88c1e0d685c0
--- /dev/null
+++ b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
@@ -0,0 +1,32 @@
+#select
+| deallocation.rs:96:14:96:15 | p1 | deallocation.rs:89:23:89:40 | ...::dangling | deallocation.rs:96:14:96:15 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:89:23:89:40 | ...::dangling | invalid |
+| deallocation.rs:97:14:97:15 | p2 | deallocation.rs:90:21:90:42 | ...::dangling_mut | deallocation.rs:97:14:97:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:90:21:90:42 | ...::dangling_mut | invalid |
+| deallocation.rs:98:14:98:15 | p3 | deallocation.rs:91:23:91:36 | ...::null | deallocation.rs:98:14:98:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:91:23:91:36 | ...::null | invalid |
+edges
+| deallocation.rs:89:6:89:7 | p1 | deallocation.rs:96:14:96:15 | p1 | provenance | |
+| deallocation.rs:89:23:89:40 | ...::dangling | deallocation.rs:89:23:89:42 | ...::dangling(...) | provenance | Src:MaD:1 MaD:1 |
+| deallocation.rs:89:23:89:42 | ...::dangling(...) | deallocation.rs:89:6:89:7 | p1 | provenance | |
+| deallocation.rs:90:6:90:7 | p2 | deallocation.rs:97:14:97:15 | p2 | provenance | |
+| deallocation.rs:90:21:90:42 | ...::dangling_mut | deallocation.rs:90:21:90:44 | ...::dangling_mut(...) | provenance | Src:MaD:2 MaD:2 |
+| deallocation.rs:90:21:90:44 | ...::dangling_mut(...) | deallocation.rs:90:6:90:7 | p2 | provenance | |
+| deallocation.rs:91:6:91:7 | p3 | deallocation.rs:98:14:98:15 | p3 | provenance | |
+| deallocation.rs:91:23:91:36 | ...::null | deallocation.rs:91:23:91:38 | ...::null(...) | provenance | Src:MaD:3 MaD:3 |
+| deallocation.rs:91:23:91:38 | ...::null(...) | deallocation.rs:91:6:91:7 | p3 | provenance | |
+models
+| 1 | Source: lang:core; crate::ptr::dangling; pointer-invalidate; ReturnValue |
+| 2 | Source: lang:core; crate::ptr::dangling_mut; pointer-invalidate; ReturnValue |
+| 3 | Source: lang:core; crate::ptr::null; pointer-invalidate; ReturnValue |
+nodes
+| deallocation.rs:89:6:89:7 | p1 | semmle.label | p1 |
+| deallocation.rs:89:23:89:40 | ...::dangling | semmle.label | ...::dangling |
+| deallocation.rs:89:23:89:42 | ...::dangling(...) | semmle.label | ...::dangling(...) |
+| deallocation.rs:90:6:90:7 | p2 | semmle.label | p2 |
+| deallocation.rs:90:21:90:42 | ...::dangling_mut | semmle.label | ...::dangling_mut |
+| deallocation.rs:90:21:90:44 | ...::dangling_mut(...) | semmle.label | ...::dangling_mut(...) |
+| deallocation.rs:91:6:91:7 | p3 | semmle.label | p3 |
+| deallocation.rs:91:23:91:36 | ...::null | semmle.label | ...::null |
+| deallocation.rs:91:23:91:38 | ...::null(...) | semmle.label | ...::null(...) |
+| deallocation.rs:96:14:96:15 | p1 | semmle.label | p1 |
+| deallocation.rs:97:14:97:15 | p2 | semmle.label | p2 |
+| deallocation.rs:98:14:98:15 | p3 | semmle.label | p3 |
+subpaths
diff --git a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.qlref b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.qlref
new file mode 100644
index 000000000000..c8e593a6a31f
--- /dev/null
+++ b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.qlref
@@ -0,0 +1,4 @@
+query: queries/security/CWE-825/AccessInvalidPointer.ql
+postprocess:
+ - utils/test/PrettyPrintModels.ql
+ - utils/test/InlineExpectationsTestQuery.ql
diff --git a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
index 1ad8d72c0082..c880ed9fd082 100644
--- a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
@@ -86,16 +86,16 @@ pub fn test_libc() {
// --- std::ptr ---
pub fn test_ptr_invalid(do_dangerous_accesses: bool) {
- let p1: *const i64 = std::ptr::dangling();
- let p2: *mut i64 = std::ptr::dangling_mut();
- let p3: *const i64 = std::ptr::null();
+ let p1: *const i64 = std::ptr::dangling(); // $ Source=dangling
+ let p2: *mut i64 = std::ptr::dangling_mut(); // $ Source=dangling_mut
+ let p3: *const i64 = std::ptr::null(); // $ Source=null
if do_dangerous_accesses {
unsafe {
// (a segmentation fault occurs in the code below)
- let v1 = *p1; // $ MISSING: Alert
- let v2 = *p2; // $ MISSING: Alert
- let v3 = *p3; // $ MISSING: Alert
+ let v1 = *p1; // $ Alert[rust/access-invalid-pointer]=dangling
+ let v2 = *p2; // $ Alert[rust/access-invalid-pointer]=dangling_mut
+ let v3 = *p3; // $ Alert[rust/access-invalid-pointer]=null
println!(" v1 = {v1} (!)");
println!(" v2 = {v2} (!)");
println!(" v3 = {v3} (!)");
From c2ee4211e5622f119361970475090d27bc64bb71 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 18 Mar 2025 17:53:58 +0000
Subject: [PATCH 012/409] Rust: Add more models.
---
.../lib/codeql/rust/frameworks/libc.model.yml | 7 +++++++
.../frameworks/stdlib/lang-alloc.model.yml | 6 ++++++
.../frameworks/stdlib/lang-core.model.yml | 19 +++++++++++++++++--
3 files changed, 30 insertions(+), 2 deletions(-)
create mode 100644 rust/ql/lib/codeql/rust/frameworks/libc.model.yml
diff --git a/rust/ql/lib/codeql/rust/frameworks/libc.model.yml b/rust/ql/lib/codeql/rust/frameworks/libc.model.yml
new file mode 100644
index 000000000000..77f0212b6c15
--- /dev/null
+++ b/rust/ql/lib/codeql/rust/frameworks/libc.model.yml
@@ -0,0 +1,7 @@
+extensions:
+ - addsTo:
+ pack: codeql/rust-all
+ extensible: sourceModel
+ data:
+ # Alloc
+ - ["repo:https://github.com/rust-lang/libc:libc", "::free", "Argument[0]", "pointer-invalidate", "manual"]
diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml
index 4e8f86dae345..fba9ae5fea33 100644
--- a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml
+++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml
@@ -9,3 +9,9 @@ extensions:
- ["lang:alloc", "::as_str", "Argument[self]", "ReturnValue", "taint", "manual"]
- ["lang:alloc", "::as_bytes", "Argument[self]", "ReturnValue", "taint", "manual"]
- ["lang:alloc", "<_ as crate::string::ToString>::to_string", "Argument[self]", "ReturnValue", "taint", "manual"]
+ - addsTo:
+ pack: codeql/rust-all
+ extensible: sourceModel
+ data:
+ # Alloc
+ - ["lang:alloc", "crate::alloc::dealloc", "Argument[0]", "pointer-invalidate", "manual"]
diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
index db1901bf8522..0960dd9c541a 100644
--- a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
+++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
@@ -17,7 +17,7 @@ extensions:
- ["lang:core", "::collect", "Argument[self].Element", "ReturnValue.Element", "value", "manual"]
- ["lang:core", "::map", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"]
- ["lang:core", "::for_each", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"]
- # ptr
+ # Ptr
- ["lang:core", "crate::ptr::read", "Argument[0].Reference", "ReturnValue", "value", "manual"]
- ["lang:core", "crate::ptr::read_unaligned", "Argument[0].Reference", "ReturnValue", "value", "manual"]
- ["lang:core", "crate::ptr::read_volatile", "Argument[0].Reference", "ReturnValue", "value", "manual"]
@@ -30,7 +30,22 @@ extensions:
pack: codeql/rust-all
extensible: sourceModel
data:
- # Alloc
+ # Mem
+ - ["lang:core", "crate::mem::drop", "Argument[0]", "pointer-invalidate", "manual"]
+ # Ptr
+ - ["lang:core", "crate::ptr::drop_in_place", "Argument[0]", "pointer-invalidate", "manual"]
- ["lang:core", "crate::ptr::dangling", "ReturnValue", "pointer-invalidate", "manual"]
- ["lang:core", "crate::ptr::dangling_mut", "ReturnValue", "pointer-invalidate", "manual"]
- ["lang:core", "crate::ptr::null", "ReturnValue", "pointer-invalidate", "manual"]
+ - addsTo:
+ pack: codeql/rust-all
+ extensible: sinkModel
+ data:
+ # Ptr
+ - ["lang:core", "crate::ptr::read", "Argument[0]", "pointer-access", "manual"]
+ - ["lang:core", "crate::ptr::read_unaligned", "Argument[0]", "pointer-access", "manual"]
+ - ["lang:core", "crate::ptr::read_volatile", "Argument[0]", "pointer-access", "manual"]
+ - ["lang:core", "crate::ptr::write", "Argument[0]", "pointer-access", "manual"]
+ - ["lang:core", "crate::ptr::write_bytes", "Argument[0]", "pointer-access", "manual"]
+ - ["lang:core", "crate::ptr::write_unaligned", "Argument[0]", "pointer-access", "manual"]
+ - ["lang:core", "crate::ptr::write_volatile", "Argument[0]", "pointer-access", "manual"]
From be6d0d1f863067901792b1a1d818590a483c6d83 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 19 Mar 2025 16:50:48 +0000
Subject: [PATCH 013/409] Rust: Work around data flow source issue.
---
.../AccessInvalidPointerExtensions.qll | 15 ++++
.../CWE-825/AccessInvalidPointer.expected | 79 ++++++++++++-------
.../security/CWE-825/deallocation.rs | 16 ++--
3 files changed, 76 insertions(+), 34 deletions(-)
diff --git a/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll b/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
index faf9de48deff..64b97a62de62 100644
--- a/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
+++ b/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
@@ -8,6 +8,7 @@ private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.FlowSource
private import codeql.rust.dataflow.FlowSink
private import codeql.rust.Concepts
+private import codeql.rust.dataflow.internal.Node
/**
* Provides default sources, sinks and barriers for detecting accesses to
@@ -40,6 +41,20 @@ module AccessInvalidPointer {
ModelsAsDataSource() { sourceNode(this, "pointer-invalidate") }
}
+ /**
+ * A pointer invalidation from an argument of a modelled call (this is a workaround).
+ */
+ private class ModelsAsDataArgumentSource extends Source {
+ ModelsAsDataArgumentSource() {
+ exists(DataFlow::Node n, CallExpr ce, Expr arg |
+ sourceNode(n, "pointer-invalidate") and
+ n.(FlowSummaryNode).getSourceElement() = ce.getFunction() and
+ arg = ce.getArgList().getAnArg() and
+ this.asExpr().getExpr() = arg
+ )
+ }
+ }
+
/**
* A pointer access using the unary `*` operator.
*/
diff --git a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
index 88c1e0d685c0..ee35913d6511 100644
--- a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
+++ b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
@@ -1,32 +1,57 @@
#select
-| deallocation.rs:96:14:96:15 | p1 | deallocation.rs:89:23:89:40 | ...::dangling | deallocation.rs:96:14:96:15 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:89:23:89:40 | ...::dangling | invalid |
-| deallocation.rs:97:14:97:15 | p2 | deallocation.rs:90:21:90:42 | ...::dangling_mut | deallocation.rs:97:14:97:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:90:21:90:42 | ...::dangling_mut | invalid |
-| deallocation.rs:98:14:98:15 | p3 | deallocation.rs:91:23:91:36 | ...::null | deallocation.rs:98:14:98:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:91:23:91:36 | ...::null | invalid |
+| deallocation.rs:23:13:23:14 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:23:13:23:14 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
+| deallocation.rs:25:12:25:31 | ...::read::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:25:12:25:31 | ...::read::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
+| deallocation.rs:33:5:33:6 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:33:5:33:6 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
+| deallocation.rs:35:4:35:24 | ...::write::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:35:4:35:24 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
+| deallocation.rs:97:14:97:15 | p1 | deallocation.rs:90:23:90:40 | ...::dangling | deallocation.rs:97:14:97:15 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:90:23:90:40 | ...::dangling | invalid |
+| deallocation.rs:98:14:98:15 | p2 | deallocation.rs:91:21:91:42 | ...::dangling_mut | deallocation.rs:98:14:98:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:91:21:91:42 | ...::dangling_mut | invalid |
+| deallocation.rs:99:14:99:15 | p3 | deallocation.rs:92:23:92:36 | ...::null | deallocation.rs:99:14:99:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:92:23:92:36 | ...::null | invalid |
+| deallocation.rs:146:14:146:15 | p1 | deallocation.rs:143:27:143:28 | p1 | deallocation.rs:146:14:146:15 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:143:27:143:28 | p1 | invalid |
edges
-| deallocation.rs:89:6:89:7 | p1 | deallocation.rs:96:14:96:15 | p1 | provenance | |
-| deallocation.rs:89:23:89:40 | ...::dangling | deallocation.rs:89:23:89:42 | ...::dangling(...) | provenance | Src:MaD:1 MaD:1 |
-| deallocation.rs:89:23:89:42 | ...::dangling(...) | deallocation.rs:89:6:89:7 | p1 | provenance | |
-| deallocation.rs:90:6:90:7 | p2 | deallocation.rs:97:14:97:15 | p2 | provenance | |
-| deallocation.rs:90:21:90:42 | ...::dangling_mut | deallocation.rs:90:21:90:44 | ...::dangling_mut(...) | provenance | Src:MaD:2 MaD:2 |
-| deallocation.rs:90:21:90:44 | ...::dangling_mut(...) | deallocation.rs:90:6:90:7 | p2 | provenance | |
-| deallocation.rs:91:6:91:7 | p3 | deallocation.rs:98:14:98:15 | p3 | provenance | |
-| deallocation.rs:91:23:91:36 | ...::null | deallocation.rs:91:23:91:38 | ...::null(...) | provenance | Src:MaD:3 MaD:3 |
-| deallocation.rs:91:23:91:38 | ...::null(...) | deallocation.rs:91:6:91:7 | p3 | provenance | |
+| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:23:13:23:14 | m1 | provenance | |
+| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:25:33:25:34 | m1 | provenance | |
+| deallocation.rs:25:33:25:34 | m1 | deallocation.rs:25:12:25:31 | ...::read::<...> | provenance | MaD:1 Sink:MaD:1 |
+| deallocation.rs:25:33:25:34 | m1 | deallocation.rs:33:5:33:6 | m1 | provenance | |
+| deallocation.rs:25:33:25:34 | m1 | deallocation.rs:33:5:33:6 | m1 | provenance | |
+| deallocation.rs:33:5:33:6 | m1 | deallocation.rs:35:26:35:27 | m1 | provenance | |
+| deallocation.rs:35:26:35:27 | m1 | deallocation.rs:35:4:35:24 | ...::write::<...> | provenance | MaD:2 Sink:MaD:2 |
+| deallocation.rs:90:6:90:7 | p1 | deallocation.rs:97:14:97:15 | p1 | provenance | |
+| deallocation.rs:90:23:90:40 | ...::dangling | deallocation.rs:90:23:90:42 | ...::dangling(...) | provenance | Src:MaD:3 MaD:3 |
+| deallocation.rs:90:23:90:42 | ...::dangling(...) | deallocation.rs:90:6:90:7 | p1 | provenance | |
+| deallocation.rs:91:6:91:7 | p2 | deallocation.rs:98:14:98:15 | p2 | provenance | |
+| deallocation.rs:91:21:91:42 | ...::dangling_mut | deallocation.rs:91:21:91:44 | ...::dangling_mut(...) | provenance | Src:MaD:4 MaD:4 |
+| deallocation.rs:91:21:91:44 | ...::dangling_mut(...) | deallocation.rs:91:6:91:7 | p2 | provenance | |
+| deallocation.rs:92:6:92:7 | p3 | deallocation.rs:99:14:99:15 | p3 | provenance | |
+| deallocation.rs:92:23:92:36 | ...::null | deallocation.rs:92:23:92:38 | ...::null(...) | provenance | Src:MaD:5 MaD:5 |
+| deallocation.rs:92:23:92:38 | ...::null(...) | deallocation.rs:92:6:92:7 | p3 | provenance | |
+| deallocation.rs:143:27:143:28 | p1 | deallocation.rs:146:14:146:15 | p1 | provenance | |
models
-| 1 | Source: lang:core; crate::ptr::dangling; pointer-invalidate; ReturnValue |
-| 2 | Source: lang:core; crate::ptr::dangling_mut; pointer-invalidate; ReturnValue |
-| 3 | Source: lang:core; crate::ptr::null; pointer-invalidate; ReturnValue |
+| 1 | Sink: lang:core; crate::ptr::read; pointer-access; Argument[0] |
+| 2 | Sink: lang:core; crate::ptr::write; pointer-access; Argument[0] |
+| 3 | Source: lang:core; crate::ptr::dangling; pointer-invalidate; ReturnValue |
+| 4 | Source: lang:core; crate::ptr::dangling_mut; pointer-invalidate; ReturnValue |
+| 5 | Source: lang:core; crate::ptr::null; pointer-invalidate; ReturnValue |
nodes
-| deallocation.rs:89:6:89:7 | p1 | semmle.label | p1 |
-| deallocation.rs:89:23:89:40 | ...::dangling | semmle.label | ...::dangling |
-| deallocation.rs:89:23:89:42 | ...::dangling(...) | semmle.label | ...::dangling(...) |
-| deallocation.rs:90:6:90:7 | p2 | semmle.label | p2 |
-| deallocation.rs:90:21:90:42 | ...::dangling_mut | semmle.label | ...::dangling_mut |
-| deallocation.rs:90:21:90:44 | ...::dangling_mut(...) | semmle.label | ...::dangling_mut(...) |
-| deallocation.rs:91:6:91:7 | p3 | semmle.label | p3 |
-| deallocation.rs:91:23:91:36 | ...::null | semmle.label | ...::null |
-| deallocation.rs:91:23:91:38 | ...::null(...) | semmle.label | ...::null(...) |
-| deallocation.rs:96:14:96:15 | p1 | semmle.label | p1 |
-| deallocation.rs:97:14:97:15 | p2 | semmle.label | p2 |
-| deallocation.rs:98:14:98:15 | p3 | semmle.label | p3 |
+| deallocation.rs:20:23:20:24 | m1 | semmle.label | m1 |
+| deallocation.rs:23:13:23:14 | m1 | semmle.label | m1 |
+| deallocation.rs:25:12:25:31 | ...::read::<...> | semmle.label | ...::read::<...> |
+| deallocation.rs:25:33:25:34 | m1 | semmle.label | m1 |
+| deallocation.rs:33:5:33:6 | m1 | semmle.label | m1 |
+| deallocation.rs:33:5:33:6 | m1 | semmle.label | m1 |
+| deallocation.rs:35:4:35:24 | ...::write::<...> | semmle.label | ...::write::<...> |
+| deallocation.rs:35:26:35:27 | m1 | semmle.label | m1 |
+| deallocation.rs:90:6:90:7 | p1 | semmle.label | p1 |
+| deallocation.rs:90:23:90:40 | ...::dangling | semmle.label | ...::dangling |
+| deallocation.rs:90:23:90:42 | ...::dangling(...) | semmle.label | ...::dangling(...) |
+| deallocation.rs:91:6:91:7 | p2 | semmle.label | p2 |
+| deallocation.rs:91:21:91:42 | ...::dangling_mut | semmle.label | ...::dangling_mut |
+| deallocation.rs:91:21:91:44 | ...::dangling_mut(...) | semmle.label | ...::dangling_mut(...) |
+| deallocation.rs:92:6:92:7 | p3 | semmle.label | p3 |
+| deallocation.rs:92:23:92:36 | ...::null | semmle.label | ...::null |
+| deallocation.rs:92:23:92:38 | ...::null(...) | semmle.label | ...::null(...) |
+| deallocation.rs:97:14:97:15 | p1 | semmle.label | p1 |
+| deallocation.rs:98:14:98:15 | p2 | semmle.label | p2 |
+| deallocation.rs:99:14:99:15 | p3 | semmle.label | p3 |
+| deallocation.rs:143:27:143:28 | p1 | semmle.label | p1 |
+| deallocation.rs:146:14:146:15 | p1 | semmle.label | p1 |
subpaths
diff --git a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
index c880ed9fd082..e8acb404253d 100644
--- a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
@@ -17,11 +17,12 @@ pub fn test_alloc(do_dangerous_writes: bool) {
println!(" v3 = {v3}");
println!(" v4 = {v4}");
- std::alloc::dealloc(m1, layout); // m1, m2 are now dangling
+ std::alloc::dealloc(m1, layout); // $ Source=dealloc
+ // (m1, m2 are now dangling)
- let v5 = *m1; // $ MISSING: Alert
+ let v5 = *m1; // $ Alert[rust/access-invalid-pointer]=dealloc
let v6 = *m2; // $ MISSING: Alert
- let v7 = std::ptr::read::(m1); // $ MISSING: Alert
+ let v7 = std::ptr::read::(m1); // $ Alert[rust/access-invalid-pointer]=dealloc
let v8 = std::ptr::read::(m2); // $ MISSING: Alert
println!(" v5 = {v5} (!)"); // corrupt in practice
println!(" v6 = {v6} (!)"); // corrupt in practice
@@ -29,9 +30,9 @@ pub fn test_alloc(do_dangerous_writes: bool) {
println!(" v8 = {v8} (!)"); // corrupt in practice
if do_dangerous_writes {
- *m1 = 2; // $ MISSING: Alert
+ *m1 = 2; // $ Alert[rust/access-invalid-pointer]=dealloc
*m2 = 3; // $ MISSING: Alert
- std::ptr::write::(m1, 4); // $ MISSING: Alert
+ std::ptr::write::(m1, 4); // $ Alert[rust/access-invalid-pointer]=dealloc
std::ptr::write::(m2, 5); // $ MISSING: Alert
}
}
@@ -139,9 +140,10 @@ pub fn test_ptr_drop() {
println!(" v1 = {v1}");
println!(" v2 = {v2}");
- std::ptr::drop_in_place(p1); // explicitly destructs the pointed-to `m2`
+ std::ptr::drop_in_place(p1); // $ Source=drop_in_place
+ // explicitly destructs the pointed-to `m2`
- let v3 = (*p1)[0]; // $ MISSING: Alert
+ let v3 = (*p1)[0]; // $ Alert[rust/access-invalid-pointer]=drop_in_place
let v4 = (*p2)[0]; // $ MISSING: Alert
println!(" v3 = {v3} (!)"); // corrupt in practice
println!(" v4 = {v4} (!)"); // corrupt in practice
From 7ceb76441a4e7256684fd1b5b3cfebeee8a66852 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 19 Mar 2025 18:01:45 +0000
Subject: [PATCH 014/409] Rust: Improve the source to account for conversions.
---
.../AccessInvalidPointerExtensions.qll | 2 +-
.../CWE-825/AccessInvalidPointer.expected | 78 ++++++++++++-------
.../security/CWE-825/deallocation.rs | 18 +++--
3 files changed, 61 insertions(+), 37 deletions(-)
diff --git a/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll b/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
index 64b97a62de62..ca485273c068 100644
--- a/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
+++ b/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
@@ -50,7 +50,7 @@ module AccessInvalidPointer {
sourceNode(n, "pointer-invalidate") and
n.(FlowSummaryNode).getSourceElement() = ce.getFunction() and
arg = ce.getArgList().getAnArg() and
- this.asExpr().getExpr() = arg
+ this.asExpr().getExpr().getParentNode*() = arg
)
}
}
diff --git a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
index ee35913d6511..ae7fb1dfb501 100644
--- a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
+++ b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
@@ -3,10 +3,16 @@
| deallocation.rs:25:12:25:31 | ...::read::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:25:12:25:31 | ...::read::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
| deallocation.rs:33:5:33:6 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:33:5:33:6 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
| deallocation.rs:35:4:35:24 | ...::write::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:35:4:35:24 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
-| deallocation.rs:97:14:97:15 | p1 | deallocation.rs:90:23:90:40 | ...::dangling | deallocation.rs:97:14:97:15 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:90:23:90:40 | ...::dangling | invalid |
-| deallocation.rs:98:14:98:15 | p2 | deallocation.rs:91:21:91:42 | ...::dangling_mut | deallocation.rs:98:14:98:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:91:21:91:42 | ...::dangling_mut | invalid |
-| deallocation.rs:99:14:99:15 | p3 | deallocation.rs:92:23:92:36 | ...::null | deallocation.rs:99:14:99:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:92:23:92:36 | ...::null | invalid |
-| deallocation.rs:146:14:146:15 | p1 | deallocation.rs:143:27:143:28 | p1 | deallocation.rs:146:14:146:15 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:143:27:143:28 | p1 | invalid |
+| deallocation.rs:57:14:57:15 | m2 | deallocation.rs:54:23:54:24 | m2 | deallocation.rs:57:14:57:15 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:54:23:54:24 | m2 | invalid |
+| deallocation.rs:58:14:58:15 | m2 | deallocation.rs:54:23:54:24 | m2 | deallocation.rs:58:14:58:15 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:54:23:54:24 | m2 | invalid |
+| deallocation.rs:63:6:63:7 | m2 | deallocation.rs:54:23:54:24 | m2 | deallocation.rs:63:6:63:7 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:54:23:54:24 | m2 | invalid |
+| deallocation.rs:64:6:64:7 | m2 | deallocation.rs:54:23:54:24 | m2 | deallocation.rs:64:6:64:7 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:54:23:54:24 | m2 | invalid |
+| deallocation.rs:66:4:66:30 | ...::write::<...> | deallocation.rs:54:23:54:24 | m2 | deallocation.rs:66:4:66:30 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:54:23:54:24 | m2 | invalid |
+| deallocation.rs:84:13:84:18 | my_ptr | deallocation.rs:81:14:81:19 | my_ptr | deallocation.rs:84:13:84:18 | my_ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:81:14:81:19 | my_ptr | invalid |
+| deallocation.rs:99:14:99:15 | p1 | deallocation.rs:92:23:92:40 | ...::dangling | deallocation.rs:99:14:99:15 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:92:23:92:40 | ...::dangling | invalid |
+| deallocation.rs:100:14:100:15 | p2 | deallocation.rs:93:21:93:42 | ...::dangling_mut | deallocation.rs:100:14:100:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:93:21:93:42 | ...::dangling_mut | invalid |
+| deallocation.rs:101:14:101:15 | p3 | deallocation.rs:94:23:94:36 | ...::null | deallocation.rs:101:14:101:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:94:23:94:36 | ...::null | invalid |
+| deallocation.rs:148:14:148:15 | p1 | deallocation.rs:145:27:145:28 | p1 | deallocation.rs:148:14:148:15 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:145:27:145:28 | p1 | invalid |
edges
| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:23:13:23:14 | m1 | provenance | |
| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:25:33:25:34 | m1 | provenance | |
@@ -15,16 +21,23 @@ edges
| deallocation.rs:25:33:25:34 | m1 | deallocation.rs:33:5:33:6 | m1 | provenance | |
| deallocation.rs:33:5:33:6 | m1 | deallocation.rs:35:26:35:27 | m1 | provenance | |
| deallocation.rs:35:26:35:27 | m1 | deallocation.rs:35:4:35:24 | ...::write::<...> | provenance | MaD:2 Sink:MaD:2 |
-| deallocation.rs:90:6:90:7 | p1 | deallocation.rs:97:14:97:15 | p1 | provenance | |
-| deallocation.rs:90:23:90:40 | ...::dangling | deallocation.rs:90:23:90:42 | ...::dangling(...) | provenance | Src:MaD:3 MaD:3 |
-| deallocation.rs:90:23:90:42 | ...::dangling(...) | deallocation.rs:90:6:90:7 | p1 | provenance | |
-| deallocation.rs:91:6:91:7 | p2 | deallocation.rs:98:14:98:15 | p2 | provenance | |
-| deallocation.rs:91:21:91:42 | ...::dangling_mut | deallocation.rs:91:21:91:44 | ...::dangling_mut(...) | provenance | Src:MaD:4 MaD:4 |
-| deallocation.rs:91:21:91:44 | ...::dangling_mut(...) | deallocation.rs:91:6:91:7 | p2 | provenance | |
-| deallocation.rs:92:6:92:7 | p3 | deallocation.rs:99:14:99:15 | p3 | provenance | |
-| deallocation.rs:92:23:92:36 | ...::null | deallocation.rs:92:23:92:38 | ...::null(...) | provenance | Src:MaD:5 MaD:5 |
-| deallocation.rs:92:23:92:38 | ...::null(...) | deallocation.rs:92:6:92:7 | p3 | provenance | |
-| deallocation.rs:143:27:143:28 | p1 | deallocation.rs:146:14:146:15 | p1 | provenance | |
+| deallocation.rs:54:23:54:24 | m2 | deallocation.rs:57:14:57:15 | m2 | provenance | |
+| deallocation.rs:54:23:54:24 | m2 | deallocation.rs:58:14:58:15 | m2 | provenance | |
+| deallocation.rs:54:23:54:24 | m2 | deallocation.rs:63:6:63:7 | m2 | provenance | |
+| deallocation.rs:54:23:54:24 | m2 | deallocation.rs:64:6:64:7 | m2 | provenance | |
+| deallocation.rs:54:23:54:24 | m2 | deallocation.rs:66:32:66:33 | m2 | provenance | |
+| deallocation.rs:66:32:66:33 | m2 | deallocation.rs:66:4:66:30 | ...::write::<...> | provenance | MaD:2 Sink:MaD:2 |
+| deallocation.rs:81:14:81:19 | my_ptr | deallocation.rs:84:13:84:18 | my_ptr | provenance | |
+| deallocation.rs:92:6:92:7 | p1 | deallocation.rs:99:14:99:15 | p1 | provenance | |
+| deallocation.rs:92:23:92:40 | ...::dangling | deallocation.rs:92:23:92:42 | ...::dangling(...) | provenance | Src:MaD:3 MaD:3 |
+| deallocation.rs:92:23:92:42 | ...::dangling(...) | deallocation.rs:92:6:92:7 | p1 | provenance | |
+| deallocation.rs:93:6:93:7 | p2 | deallocation.rs:100:14:100:15 | p2 | provenance | |
+| deallocation.rs:93:21:93:42 | ...::dangling_mut | deallocation.rs:93:21:93:44 | ...::dangling_mut(...) | provenance | Src:MaD:4 MaD:4 |
+| deallocation.rs:93:21:93:44 | ...::dangling_mut(...) | deallocation.rs:93:6:93:7 | p2 | provenance | |
+| deallocation.rs:94:6:94:7 | p3 | deallocation.rs:101:14:101:15 | p3 | provenance | |
+| deallocation.rs:94:23:94:36 | ...::null | deallocation.rs:94:23:94:38 | ...::null(...) | provenance | Src:MaD:5 MaD:5 |
+| deallocation.rs:94:23:94:38 | ...::null(...) | deallocation.rs:94:6:94:7 | p3 | provenance | |
+| deallocation.rs:145:27:145:28 | p1 | deallocation.rs:148:14:148:15 | p1 | provenance | |
models
| 1 | Sink: lang:core; crate::ptr::read; pointer-access; Argument[0] |
| 2 | Sink: lang:core; crate::ptr::write; pointer-access; Argument[0] |
@@ -40,18 +53,27 @@ nodes
| deallocation.rs:33:5:33:6 | m1 | semmle.label | m1 |
| deallocation.rs:35:4:35:24 | ...::write::<...> | semmle.label | ...::write::<...> |
| deallocation.rs:35:26:35:27 | m1 | semmle.label | m1 |
-| deallocation.rs:90:6:90:7 | p1 | semmle.label | p1 |
-| deallocation.rs:90:23:90:40 | ...::dangling | semmle.label | ...::dangling |
-| deallocation.rs:90:23:90:42 | ...::dangling(...) | semmle.label | ...::dangling(...) |
-| deallocation.rs:91:6:91:7 | p2 | semmle.label | p2 |
-| deallocation.rs:91:21:91:42 | ...::dangling_mut | semmle.label | ...::dangling_mut |
-| deallocation.rs:91:21:91:44 | ...::dangling_mut(...) | semmle.label | ...::dangling_mut(...) |
-| deallocation.rs:92:6:92:7 | p3 | semmle.label | p3 |
-| deallocation.rs:92:23:92:36 | ...::null | semmle.label | ...::null |
-| deallocation.rs:92:23:92:38 | ...::null(...) | semmle.label | ...::null(...) |
-| deallocation.rs:97:14:97:15 | p1 | semmle.label | p1 |
-| deallocation.rs:98:14:98:15 | p2 | semmle.label | p2 |
-| deallocation.rs:99:14:99:15 | p3 | semmle.label | p3 |
-| deallocation.rs:143:27:143:28 | p1 | semmle.label | p1 |
-| deallocation.rs:146:14:146:15 | p1 | semmle.label | p1 |
+| deallocation.rs:54:23:54:24 | m2 | semmle.label | m2 |
+| deallocation.rs:57:14:57:15 | m2 | semmle.label | m2 |
+| deallocation.rs:58:14:58:15 | m2 | semmle.label | m2 |
+| deallocation.rs:63:6:63:7 | m2 | semmle.label | m2 |
+| deallocation.rs:64:6:64:7 | m2 | semmle.label | m2 |
+| deallocation.rs:66:4:66:30 | ...::write::<...> | semmle.label | ...::write::<...> |
+| deallocation.rs:66:32:66:33 | m2 | semmle.label | m2 |
+| deallocation.rs:81:14:81:19 | my_ptr | semmle.label | my_ptr |
+| deallocation.rs:84:13:84:18 | my_ptr | semmle.label | my_ptr |
+| deallocation.rs:92:6:92:7 | p1 | semmle.label | p1 |
+| deallocation.rs:92:23:92:40 | ...::dangling | semmle.label | ...::dangling |
+| deallocation.rs:92:23:92:42 | ...::dangling(...) | semmle.label | ...::dangling(...) |
+| deallocation.rs:93:6:93:7 | p2 | semmle.label | p2 |
+| deallocation.rs:93:21:93:42 | ...::dangling_mut | semmle.label | ...::dangling_mut |
+| deallocation.rs:93:21:93:44 | ...::dangling_mut(...) | semmle.label | ...::dangling_mut(...) |
+| deallocation.rs:94:6:94:7 | p3 | semmle.label | p3 |
+| deallocation.rs:94:23:94:36 | ...::null | semmle.label | ...::null |
+| deallocation.rs:94:23:94:38 | ...::null(...) | semmle.label | ...::null(...) |
+| deallocation.rs:99:14:99:15 | p1 | semmle.label | p1 |
+| deallocation.rs:100:14:100:15 | p2 | semmle.label | p2 |
+| deallocation.rs:101:14:101:15 | p3 | semmle.label | p3 |
+| deallocation.rs:145:27:145:28 | p1 | semmle.label | p1 |
+| deallocation.rs:148:14:148:15 | p1 | semmle.label | p1 |
subpaths
diff --git a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
index e8acb404253d..cd3ac57c487d 100644
--- a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
@@ -51,18 +51,19 @@ pub fn test_alloc_array(do_dangerous_writes: bool) {
println!(" v1 = {v1}");
println!(" v2 = {v2}");
- std::alloc::dealloc(m2 as *mut u8, layout); // m1, m2 are now dangling
+ std::alloc::dealloc(m2 as *mut u8, layout); // $ Source=dealloc_array
+ // m1, m2 are now dangling
- let v3 = (*m2)[0]; // $ MISSING: Alert
- let v4 = (*m2)[1]; // $ MISSING: Alert
+ let v3 = (*m2)[0]; // $ Alert[rust/access-invalid-pointer]=dealloc_array
+ let v4 = (*m2)[1]; // $ Alert[rust/access-invalid-pointer]=dealloc_array
println!(" v3 = {v3} (!)"); // corrupt in practice
println!(" v4 = {v4} (!)"); // corrupt in practice
if do_dangerous_writes {
- (*m2)[0] = 3; // $ MISSING: Alert
- (*m2)[1] = 4; // $ MISSING: Alert
+ (*m2)[0] = 3; // $ Alert[rust/access-invalid-pointer]=dealloc_array
+ (*m2)[1] = 4; // $ Alert[rust/access-invalid-pointer]=dealloc_array
std::ptr::write::(m1, 5); // $ MISSING: Alert
- std::ptr::write::<[u8; 10]>(m2, [6; 10]); // $ MISSING: Alert
+ std::ptr::write::<[u8; 10]>(m2, [6; 10]); // $ Alert[rust/access-invalid-pointer]=dealloc_array
}
}
}
@@ -77,9 +78,10 @@ pub fn test_libc() {
let v1 = *my_ptr; // GOOD
println!(" v1 = {v1}");
- libc::free(my_ptr as *mut libc::c_void); // my_ptr is now dangling
+ libc::free(my_ptr as *mut libc::c_void); // $ Source=free
+ // (my_ptr is now dangling)
- let v2 = *my_ptr; // $ MISSING: Alert
+ let v2 = *my_ptr; // $ Alert[rust/access-invalid-pointer]=free
println!(" v2 = {v2} (!)"); // corrupt in practice
}
}
From 671f7dff943094abcc9e9301f206ad5ad8e521ce Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 19 Mar 2025 18:59:48 +0000
Subject: [PATCH 015/409] Rust: Query metadata.
---
rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
index ba124c99d40f..a1ff02bb429a 100644
--- a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
+++ b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
@@ -3,8 +3,8 @@
* @description Dereferencing an invalid or dangling pointer is undefined behavior and may cause memory corruption.
* @kind path-problem
* @problem.severity error
- * @security-severity TODO
- * @precision TODO
+ * @security-severity 7.5
+ * @precision high
* @id rust/access-invalid-pointer
* @tags reliability
* security
From 019fcbfbf9b0867ffd464772c93affa732e7b0be Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 20 Mar 2025 10:04:34 +0000
Subject: [PATCH 016/409] Rust: Add qhelp examples, and add them as tests.
---
.../CWE-825/AccessInvalidPointerBad.rs | 10 ++++
.../CWE-825/AccessInvalidPointerGood.rs | 10 ++++
.../CWE-825/AccessInvalidPointer.expected | 4 ++
.../security/CWE-825/deallocation.rs | 47 +++++++++++++++++++
.../test/query-tests/security/CWE-825/main.rs | 3 ++
5 files changed, 74 insertions(+)
create mode 100644 rust/ql/src/queries/security/CWE-825/AccessInvalidPointerBad.rs
create mode 100644 rust/ql/src/queries/security/CWE-825/AccessInvalidPointerGood.rs
diff --git a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointerBad.rs b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointerBad.rs
new file mode 100644
index 000000000000..ef635450bddb
--- /dev/null
+++ b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointerBad.rs
@@ -0,0 +1,10 @@
+
+unsafe {
+ std::ptr::drop_in_place(ptr); // executes the destructor of `*ptr`
+}
+
+// ...
+
+unsafe {
+ do_something(&*ptr); // BAD: dereferences `ptr`
+}
diff --git a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointerGood.rs b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointerGood.rs
new file mode 100644
index 000000000000..77dbdfb9d394
--- /dev/null
+++ b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointerGood.rs
@@ -0,0 +1,10 @@
+
+unsafe {
+ do_something(&*ptr); // GOOD: dereferences `ptr` while it is still valid
+}
+
+// ...
+
+{
+ std::ptr::drop_in_place(ptr); // executes the destructor of `*ptr`
+}
diff --git a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
index ae7fb1dfb501..0067fcc17daa 100644
--- a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
+++ b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
@@ -13,6 +13,7 @@
| deallocation.rs:100:14:100:15 | p2 | deallocation.rs:93:21:93:42 | ...::dangling_mut | deallocation.rs:100:14:100:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:93:21:93:42 | ...::dangling_mut | invalid |
| deallocation.rs:101:14:101:15 | p3 | deallocation.rs:94:23:94:36 | ...::null | deallocation.rs:101:14:101:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:94:23:94:36 | ...::null | invalid |
| deallocation.rs:148:14:148:15 | p1 | deallocation.rs:145:27:145:28 | p1 | deallocation.rs:148:14:148:15 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:145:27:145:28 | p1 | invalid |
+| deallocation.rs:179:18:179:20 | ptr | deallocation.rs:173:27:173:29 | ptr | deallocation.rs:179:18:179:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:173:27:173:29 | ptr | invalid |
edges
| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:23:13:23:14 | m1 | provenance | |
| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:25:33:25:34 | m1 | provenance | |
@@ -38,6 +39,7 @@ edges
| deallocation.rs:94:23:94:36 | ...::null | deallocation.rs:94:23:94:38 | ...::null(...) | provenance | Src:MaD:5 MaD:5 |
| deallocation.rs:94:23:94:38 | ...::null(...) | deallocation.rs:94:6:94:7 | p3 | provenance | |
| deallocation.rs:145:27:145:28 | p1 | deallocation.rs:148:14:148:15 | p1 | provenance | |
+| deallocation.rs:173:27:173:29 | ptr | deallocation.rs:179:18:179:20 | ptr | provenance | |
models
| 1 | Sink: lang:core; crate::ptr::read; pointer-access; Argument[0] |
| 2 | Sink: lang:core; crate::ptr::write; pointer-access; Argument[0] |
@@ -76,4 +78,6 @@ nodes
| deallocation.rs:101:14:101:15 | p3 | semmle.label | p3 |
| deallocation.rs:145:27:145:28 | p1 | semmle.label | p1 |
| deallocation.rs:148:14:148:15 | p1 | semmle.label | p1 |
+| deallocation.rs:173:27:173:29 | ptr | semmle.label | ptr |
+| deallocation.rs:179:18:179:20 | ptr | semmle.label | ptr |
subpaths
diff --git a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
index cd3ac57c487d..69e4919b480f 100644
--- a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
@@ -151,3 +151,50 @@ pub fn test_ptr_drop() {
println!(" v4 = {v4} (!)"); // corrupt in practice
}
}
+
+fn do_something(s: &String) {
+ println!(" s = {}", s);
+}
+
+fn test_qhelp_test_good(ptr: *mut String) {
+ unsafe {
+ do_something(&*ptr);
+ }
+
+ // ...
+
+ unsafe {
+ std::ptr::drop_in_place(ptr);
+ }
+}
+
+fn test_qhelp_test_bad(ptr: *mut String) {
+ unsafe {
+ std::ptr::drop_in_place(ptr); // $ Source=drop_in_place
+ }
+
+ // ...
+
+ unsafe {
+ do_something(&*ptr); // $ Alert[rust/access-invalid-pointer]=drop_in_place
+ }
+}
+
+pub fn test_qhelp_tests() {
+ let layout = std::alloc::Layout::new::<[String; 2]>();
+ unsafe {
+ let ptr = std::alloc::alloc(layout);
+ let ptr_s = ptr as *mut [String; 2];
+ let ptr1 = &raw mut (*ptr_s)[0];
+ let ptr2 = &raw mut (*ptr_s)[1];
+
+ *ptr1 = String::from("123");
+ *ptr2 = String::from("456");
+
+ test_qhelp_test_good(ptr1);
+
+ test_qhelp_test_bad(ptr2);
+
+ std::alloc::dealloc(ptr, layout);
+ }
+}
diff --git a/rust/ql/test/query-tests/security/CWE-825/main.rs b/rust/ql/test/query-tests/security/CWE-825/main.rs
index e7a2154c3262..1859ac8c7219 100644
--- a/rust/ql/test/query-tests/security/CWE-825/main.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/main.rs
@@ -123,6 +123,9 @@ fn main() {
println!("test_ptr_drop:");
test_ptr_drop();
+ println!("test_qhelp_tests:");
+ test_qhelp_tests();
+
// ---
println!("test_local_dangling:");
From 7ecba71166dab89a9aad23bf3b6eee2537dfaad3 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 20 Mar 2025 11:13:28 +0000
Subject: [PATCH 017/409] Rust: Add .qhelp.
---
.../CWE-825/AccessInvalidPointer.qhelp | 48 +++++++++++++++++++
1 file changed, 48 insertions(+)
create mode 100644 rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp
diff --git a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp
new file mode 100644
index 000000000000..78c7267a0e6f
--- /dev/null
+++ b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp
@@ -0,0 +1,48 @@
+
+
+
+
+
+Dereferencing an invalid or dangling pointer is undefined behavior. Memory may be corrupted
+causing the program to crash or behave incorrectly, in some cases exposing the program to
+potential attacks.
+
+
+
+
+
+
+When dereferencing a pointer in unsafe code, take care that the pointer is valid and
+points to the intended data. Code may need to be rearranged or additional checks added to ensure
+safety in all circumstances. If possible, rewrite the code using safe Rust types to avoid this
+class of problems altogether.
+
+
+
+
+
+
+In the following example, std::ptr::drop_in_place is used to execute the destructor
+of an object. However, a pointer to that object is dereferenced later in the program, causing
+undefined behavior:
+
+
+
+
+
+In this case undefined behavior can be avoided by rearranging the code so that the dereference
+comes before the call to std::ptr::drop_in_place:
+
+
+
+
+
+
+
+Rust Documentation: Behavior considered undefined >> Dangling pointers.
+Rust Documentation: Module ptr - Safety.
+
+
+
From 5831c446d331273e5da839c863bd79711c9e990c Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 20 Mar 2025 13:46:20 +0000
Subject: [PATCH 018/409] Rust: Add test cases for another situation I came
across.
---
.../security/CWE-825/deallocation.rs | 40 +++++++++++++++++++
.../test/query-tests/security/CWE-825/main.rs | 3 ++
2 files changed, 43 insertions(+)
diff --git a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
index 69e4919b480f..30677ddc07cc 100644
--- a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
@@ -198,3 +198,43 @@ pub fn test_qhelp_tests() {
std::alloc::dealloc(ptr, layout);
}
}
+
+pub fn test_vec_reserve() {
+ let mut vec1 = Vec::::new();
+ vec1.push(100);
+ let ptr1 = &raw mut vec1[0];
+
+ unsafe {
+ let v1 = *ptr1;
+ println!(" v1 = {}", v1);
+ }
+
+ vec1.reserve(1000); // $ MISSING: Source=reserve
+ // (may invalidate the pointer)
+
+ unsafe {
+ let v2 = *ptr1; // $ MISSING: Alert[rust/access-invalid-pointer]=reserve
+ println!(" v2 = {}", v2); // corrupt in practice
+ }
+
+ // -
+
+ let mut vec2 = Vec::::new();
+ vec2.push(200);
+ let ptr2 = &raw mut vec2[0];
+
+ unsafe {
+ let v3 = *ptr2;
+ println!(" v3 = {}", v3);
+ }
+
+ for _i in 0..1000 {
+ vec2.push(0); // $ MISSING: Source=push
+ // (may invalidate the pointer)
+ }
+
+ unsafe {
+ let v4 = *ptr2; // $ MISSING: Alert[rust/access-invalid-pointer]=push
+ println!(" v4 = {}", v4); // corrupt in practice
+ }
+}
diff --git a/rust/ql/test/query-tests/security/CWE-825/main.rs b/rust/ql/test/query-tests/security/CWE-825/main.rs
index 1859ac8c7219..9a3dfcd2889c 100644
--- a/rust/ql/test/query-tests/security/CWE-825/main.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/main.rs
@@ -126,6 +126,9 @@ fn main() {
println!("test_qhelp_tests:");
test_qhelp_tests();
+ println!("test_vec_reserve:");
+ test_vec_reserve();
+
// ---
println!("test_local_dangling:");
From 5e18e1be11f7dde5a7faef6852ca58e32373cded Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 20 Mar 2025 15:03:55 +0000
Subject: [PATCH 019/409] Rust: Autofix and US spelling.
---
.../codeql/rust/security/AccessInvalidPointerExtensions.qll | 2 +-
rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll b/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
index ca485273c068..9f895ef6f87e 100644
--- a/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
+++ b/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
@@ -42,7 +42,7 @@ module AccessInvalidPointer {
}
/**
- * A pointer invalidation from an argument of a modelled call (this is a workaround).
+ * A pointer invalidation from an argument of a modeled call (this is a workaround).
*/
private class ModelsAsDataArgumentSource extends Source {
ModelsAsDataArgumentSource() {
diff --git a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
index a1ff02bb429a..cb474d0bb0fb 100644
--- a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
+++ b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
@@ -32,4 +32,5 @@ module AccessInvalidPointerFlow = DataFlow::Global;
from AccessInvalidPointerFlow::PathNode sourceNode, AccessInvalidPointerFlow::PathNode sinkNode
where AccessInvalidPointerFlow::flowPath(sourceNode, sinkNode)
-select sinkNode.getNode(), sourceNode, sinkNode, "This operation dereferences a pointer that may be $@.", sourceNode.getNode(), "invalid"
+select sinkNode.getNode(), sourceNode, sinkNode,
+ "This operation dereferences a pointer that may be $@.", sourceNode.getNode(), "invalid"
From c6c4e3cf16f71793db8661f281fbd5aad436b824 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 20 Mar 2025 15:16:17 +0000
Subject: [PATCH 020/409] Rust: Add another reference.
---
rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp | 1 +
1 file changed, 1 insertion(+)
diff --git a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp
index 78c7267a0e6f..2981564b9eec 100644
--- a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp
+++ b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp
@@ -43,6 +43,7 @@ comes before the call to std::ptr::drop_in_place:
Rust Documentation: Behavior considered undefined >> Dangling pointers.
Rust Documentation: Module ptr - Safety.
+Massachusetts Institute of Technology: Unsafe Rust - Dereferencing a Raw Pointer.
From 98690f924a1dd829c42fbc70578c9dfb7bda473f Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 20 Mar 2025 15:38:54 +0000
Subject: [PATCH 021/409] Rust: Incidental changes to other .expected files.
---
.../query-tests/security/CWE-020/RegexInjection.expected | 8 ++++----
.../utils-tests/modelgenerator/CaptureSinkModels.expected | 4 ++++
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected b/rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected
index e204b5a39264..0e1ea0fb063a 100644
--- a/rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected
+++ b/rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected
@@ -2,15 +2,15 @@
| main.rs:6:25:6:30 | ®ex | main.rs:4:20:4:32 | ...::var | main.rs:6:25:6:30 | ®ex | This regular expression is constructed from a $@. | main.rs:4:20:4:32 | ...::var | user-provided value |
edges
| main.rs:4:9:4:16 | username | main.rs:5:25:5:44 | MacroExpr | provenance | |
-| main.rs:4:20:4:32 | ...::var | main.rs:4:20:4:40 | ...::var(...) [Ok] | provenance | Src:MaD:62 |
-| main.rs:4:20:4:40 | ...::var(...) [Ok] | main.rs:4:20:4:66 | ... .unwrap_or(...) | provenance | MaD:1593 |
+| main.rs:4:20:4:32 | ...::var | main.rs:4:20:4:40 | ...::var(...) [Ok] | provenance | Src:MaD:63 |
+| main.rs:4:20:4:40 | ...::var(...) [Ok] | main.rs:4:20:4:66 | ... .unwrap_or(...) | provenance | MaD:1607 |
| main.rs:4:20:4:66 | ... .unwrap_or(...) | main.rs:4:9:4:16 | username | provenance | |
| main.rs:5:9:5:13 | regex | main.rs:6:26:6:30 | regex | provenance | |
| main.rs:5:17:5:45 | res | main.rs:5:25:5:44 | { ... } | provenance | |
| main.rs:5:25:5:44 | ...::format(...) | main.rs:5:17:5:45 | res | provenance | |
| main.rs:5:25:5:44 | ...::must_use(...) | main.rs:5:9:5:13 | regex | provenance | |
-| main.rs:5:25:5:44 | MacroExpr | main.rs:5:25:5:44 | ...::format(...) | provenance | MaD:66 |
-| main.rs:5:25:5:44 | { ... } | main.rs:5:25:5:44 | ...::must_use(...) | provenance | MaD:3016 |
+| main.rs:5:25:5:44 | MacroExpr | main.rs:5:25:5:44 | ...::format(...) | provenance | MaD:67 |
+| main.rs:5:25:5:44 | { ... } | main.rs:5:25:5:44 | ...::must_use(...) | provenance | MaD:3030 |
| main.rs:6:26:6:30 | regex | main.rs:6:25:6:30 | ®ex | provenance | |
nodes
| main.rs:4:9:4:16 | username | semmle.label | username |
diff --git a/rust/ql/test/utils-tests/modelgenerator/CaptureSinkModels.expected b/rust/ql/test/utils-tests/modelgenerator/CaptureSinkModels.expected
index cb6fc390349c..12afcda158bb 100644
--- a/rust/ql/test/utils-tests/modelgenerator/CaptureSinkModels.expected
+++ b/rust/ql/test/utils-tests/modelgenerator/CaptureSinkModels.expected
@@ -1,2 +1,6 @@
unexpectedModel
+| Unexpected sink found: repo::test;::replace;Argument[self];pointer-access;df-generated |
+| Unexpected sink found: repo::test;::take;Argument[self];pointer-access;df-generated |
+| Unexpected sink found: repo::test;::take_if;Argument[self];pointer-access;df-generated |
+| Unexpected sink found: repo::test;crate::option::replace;Argument[0];pointer-access;df-generated |
expectedModel
From 91d273ad761f3ec64808b9727af847d5b901aca8 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 20 Mar 2025 15:49:55 +0000
Subject: [PATCH 022/409] Rust: I think these generated models are correct.
Accept them.
---
.../utils-tests/modelgenerator/CaptureSinkModels.expected | 4 ----
rust/ql/test/utils-tests/modelgenerator/option.rs | 4 ++++
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/rust/ql/test/utils-tests/modelgenerator/CaptureSinkModels.expected b/rust/ql/test/utils-tests/modelgenerator/CaptureSinkModels.expected
index 12afcda158bb..cb6fc390349c 100644
--- a/rust/ql/test/utils-tests/modelgenerator/CaptureSinkModels.expected
+++ b/rust/ql/test/utils-tests/modelgenerator/CaptureSinkModels.expected
@@ -1,6 +1,2 @@
unexpectedModel
-| Unexpected sink found: repo::test;::replace;Argument[self];pointer-access;df-generated |
-| Unexpected sink found: repo::test;::take;Argument[self];pointer-access;df-generated |
-| Unexpected sink found: repo::test;::take_if;Argument[self];pointer-access;df-generated |
-| Unexpected sink found: repo::test;crate::option::replace;Argument[0];pointer-access;df-generated |
expectedModel
diff --git a/rust/ql/test/utils-tests/modelgenerator/option.rs b/rust/ql/test/utils-tests/modelgenerator/option.rs
index 774cce8c38f7..5e2e2391ba76 100644
--- a/rust/ql/test/utils-tests/modelgenerator/option.rs
+++ b/rust/ql/test/utils-tests/modelgenerator/option.rs
@@ -10,6 +10,7 @@ use core::{hint, mem};
// summary=repo::test;crate::option::replace;Argument[0].Reference;ReturnValue;value;dfc-generated
// summary=repo::test;crate::option::replace;Argument[1];Argument[0].Reference;value;dfc-generated
+// sink=repo::test;crate::option::replace;Argument[0];pointer-access;df-generated
pub fn replace(dest: &mut T, src: T) -> T {
unsafe {
let result = ptr::read(dest);
@@ -338,6 +339,7 @@ impl MyOption {
}
// summary=repo::test;::take;Argument[self].Reference;ReturnValue;value;dfc-generated
+ // sink=repo::test;::take;Argument[self];pointer-access;df-generated
pub fn take(&mut self) -> MyOption {
// FIXME(const-hack) replace `mem::replace` by `mem::take` when the latter is const ready
replace(self, MyNone)
@@ -345,6 +347,7 @@ impl MyOption {
// summary=repo::test;::take_if;Argument[self].Reference.Field[crate::option::MyOption::MySome(0)];Argument[0].Parameter[0].Reference;value;dfc-generated
// summary=repo::test;::take_if;Argument[self].Reference;ReturnValue;value;dfc-generated
+ // sink=repo::test;::take_if;Argument[self];pointer-access;df-generated
pub fn take_if(&mut self, predicate: P) -> MyOption
where
P: FnOnce(&mut T) -> bool,
@@ -358,6 +361,7 @@ impl MyOption {
// summary=repo::test;::replace;Argument[0];Argument[self].Reference.Field[crate::option::MyOption::MySome(0)];value;dfc-generated
// summary=repo::test;::replace;Argument[self].Reference;ReturnValue;value;dfc-generated
+ // sink=repo::test;::replace;Argument[self];pointer-access;df-generated
pub fn replace(&mut self, value: T) -> MyOption {
replace(self, MySome(value))
}
From e44f7f946fa1f4514074de01a5023f3852e0191b Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Fri, 21 Mar 2025 09:45:50 +0000
Subject: [PATCH 023/409] Sort package paths in vendor/modules.txt
---
.../semmle/go/frameworks/Beego/vendor/modules.txt | 2 +-
.../semmle/go/frameworks/GoMicro/vendor/modules.txt | 2 +-
go/ql/test/query-tests/Security/CWE-089/vendor/modules.txt | 2 +-
go/ql/test/query-tests/Security/CWE-643/vendor/modules.txt | 4 ++--
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Beego/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/Beego/vendor/modules.txt
index 2ec051971307..d1bcf3037c5e 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/Beego/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/Beego/vendor/modules.txt
@@ -1,9 +1,9 @@
# github.com/astaxie/beego v1.12.3
## explicit
-github.com/astaxie/beego/utils
github.com/astaxie/beego
github.com/astaxie/beego/context
github.com/astaxie/beego/logs
+github.com/astaxie/beego/utils
# github.com/beego/beego/v2 v2.1.2
## explicit
github.com/beego/beego/v2/server/web
diff --git a/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/vendor/modules.txt
index 4235d3525987..a03262041901 100644
--- a/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/vendor/modules.txt
+++ b/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/vendor/modules.txt
@@ -1,9 +1,9 @@
# go-micro.dev/v4 v4.10.2
## explicit
+go-micro.dev/v4
go-micro.dev/v4/api
go-micro.dev/v4/client
go-micro.dev/v4/server
-go-micro.dev/v4
# google.golang.org/protobuf v1.28.1
## explicit
google.golang.org/protobuf/proto
diff --git a/go/ql/test/query-tests/Security/CWE-089/vendor/modules.txt b/go/ql/test/query-tests/Security/CWE-089/vendor/modules.txt
index b0de76d4f889..020db5bbe9ca 100644
--- a/go/ql/test/query-tests/Security/CWE-089/vendor/modules.txt
+++ b/go/ql/test/query-tests/Security/CWE-089/vendor/modules.txt
@@ -3,6 +3,6 @@
github.com/Masterminds/squirrel
# go.mongodb.org/mongo-driver v1.3.3
## explicit
+go.mongodb.org/mongo-driver/bson
go.mongodb.org/mongo-driver/mongo
go.mongodb.org/mongo-driver/mongo/options
-go.mongodb.org/mongo-driver/bson
diff --git a/go/ql/test/query-tests/Security/CWE-643/vendor/modules.txt b/go/ql/test/query-tests/Security/CWE-643/vendor/modules.txt
index a852f50be92f..36b5fdf2ae07 100644
--- a/go/ql/test/query-tests/Security/CWE-643/vendor/modules.txt
+++ b/go/ql/test/query-tests/Security/CWE-643/vendor/modules.txt
@@ -1,7 +1,7 @@
# github.com/ChrisTrenkamp/goxpath v0.0.0-20190607011252-c5096ec8773d
## explicit
-github.com/ChrisTrenkamp/goxpath/tree
github.com/ChrisTrenkamp/goxpath
+github.com/ChrisTrenkamp/goxpath/tree
# github.com/antchfx/htmlquery v1.2.2
## explicit
github.com/antchfx/htmlquery
@@ -19,8 +19,8 @@ github.com/antchfx/xpath
github.com/go-xmlpath/xmlpath
# github.com/jbowtie/gokogiri v0.0.0-20190301021639-37f655d3078f
## explicit
-github.com/jbowtie/gokogiri/xpath
github.com/jbowtie/gokogiri/xml
+github.com/jbowtie/gokogiri/xpath
# github.com/lestrrat-go/libxml2 v0.0.0-20231124114421-99c71026c2f5
## explicit
github.com/lestrrat-go/libxml2/parser
From af6e1bda4c5bc02e1833289d69e219f8c26349a3 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Thu, 20 Mar 2025 15:18:19 +0100
Subject: [PATCH 024/409] C#: Extract alignment and format clauses of string
interpolation expressions.
---
.../SymbolExtensions.cs | 9 ++++
.../Entities/Expressions/Binary.cs | 2 +-
.../Entities/Expressions/ImplicitToString.cs | 7 +--
.../Expressions/InterpolatedString.cs | 11 +---
.../Expressions/InterpolatedStringInsert.cs | 41 +++++++++++++++
.../Kinds/ExprKind.cs | 1 +
.../internal/TaintTrackingPrivate.qll | 3 ++
.../ql/lib/semmle/code/csharp/exprs/Expr.qll | 51 ++++++++++++++++---
csharp/ql/lib/semmlecode.csharp.dbscheme | 1 +
9 files changed, 104 insertions(+), 22 deletions(-)
create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedStringInsert.cs
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs
index cb1f36f8a2de..72f78f160598 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs
@@ -29,6 +29,15 @@ public AnnotatedTypeSymbol(ITypeSymbol? symbol, NullableAnnotation nullability)
symbol is null ? (AnnotatedTypeSymbol?)null : new AnnotatedTypeSymbol(symbol, NullableAnnotation.None);
}
+ internal static class AnnotatedTypeSymbolExtensions
+ {
+ ///
+ /// Returns true if the type is a string type.
+ ///
+ public static bool IsStringType(this AnnotatedTypeSymbol? type) =>
+ type.HasValue && type.Value.Symbol?.SpecialType == SpecialType.System_String;
+ }
+
internal static class SymbolExtensions
{
///
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Binary.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Binary.cs
index eeb1b9ba63b2..d4cc5cc81d58 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Binary.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Binary.cs
@@ -18,7 +18,7 @@ private Expression CreateChild(Context cx, ExpressionSyntax node, int child)
{
// If this is a "+" expression we might need to wrap the child expressions
// in ToString calls
- return Kind == ExprKind.ADD
+ return Kind == ExprKind.ADD && Type.IsStringType()
? ImplicitToString.Create(cx, node, this, child)
: Create(cx, node, this, child);
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitToString.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitToString.cs
index 32c00f8a729e..bebc0c2c5d81 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitToString.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitToString.cs
@@ -39,16 +39,13 @@ private ImplicitToString(ExpressionNodeInfo info, IMethodSymbol toString) : base
Context.TrapWriter.Writer.expr_call(this, target);
}
- private static bool IsStringType(AnnotatedTypeSymbol? type) =>
- type.HasValue && type.Value.Symbol?.SpecialType == SpecialType.System_String;
-
///
/// Creates a new expression, adding a compiler generated `ToString` call if required.
///
- public static Expression Create(Context cx, ExpressionSyntax node, Expression parent, int child)
+ public static Expression Create(Context cx, ExpressionSyntax node, IExpressionParentEntity parent, int child)
{
var info = new ExpressionNodeInfo(cx, node, parent, child);
- return CreateFromNode(info.SetImplicitToString(IsStringType(parent.Type) && !IsStringType(info.Type)));
+ return CreateFromNode(info.SetImplicitToString(!info.Type.IsStringType()));
}
///
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedString.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedString.cs
index 6d17d1e7f176..5cd13dffe20b 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedString.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedString.cs
@@ -1,5 +1,4 @@
using System.IO;
-using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
@@ -21,15 +20,7 @@ protected override void PopulateExpression(TextWriter trapFile)
{
case SyntaxKind.Interpolation:
var interpolation = (InterpolationSyntax)c;
- var exp = interpolation.Expression;
- if (Context.GetTypeInfo(exp).Type is ITypeSymbol type && !type.ImplementsIFormattable())
- {
- ImplicitToString.Create(Context, exp, this, child++);
- }
- else
- {
- Create(Context, exp, this, child++);
- }
+ new InterpolatedStringInsert(Context, interpolation, this, child++);
break;
case SyntaxKind.InterpolatedStringText:
// Create a string literal
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedStringInsert.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedStringInsert.cs
new file mode 100644
index 000000000000..beac4bc64a64
--- /dev/null
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedStringInsert.cs
@@ -0,0 +1,41 @@
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Semmle.Extraction.Kinds;
+
+namespace Semmle.Extraction.CSharp.Entities.Expressions
+{
+ internal class InterpolatedStringInsert : Expression
+ {
+ public InterpolatedStringInsert(Context cx, InterpolationSyntax syntax, Expression parent, int child) :
+ base(new ExpressionInfo(cx, null, cx.CreateLocation(syntax.GetLocation()), ExprKind.INTERPOLATED_STRING_INSERT, parent, child, isCompilerGenerated: false, null))
+ {
+ var exp = syntax.Expression;
+ if (parent.Type.IsStringType() &&
+ cx.GetTypeInfo(exp).Type is ITypeSymbol type &&
+ !type.ImplementsIFormattable())
+ {
+ ImplicitToString.Create(cx, exp, this, 0);
+ }
+ else
+ {
+ Create(cx, exp, this, 0);
+ }
+
+ // Hardcode the child number of the optional alignment clause to 1 and format clause to 2.
+ // This simplifies the logic in QL.
+ if (syntax.AlignmentClause?.Value is ExpressionSyntax alignment)
+ {
+ Create(cx, alignment, this, 1);
+ }
+
+ if (syntax.FormatClause is InterpolationFormatClauseSyntax format)
+ {
+ var f = format.FormatStringToken.ValueText;
+ var t = AnnotatedTypeSymbol.CreateNotAnnotated(cx.Compilation.GetSpecialType(SpecialType.System_String));
+ new Expression(new ExpressionInfo(cx, t, cx.CreateLocation(format.GetLocation()), ExprKind.UTF16_STRING_LITERAL, this, 2, isCompilerGenerated: false, f));
+ }
+
+ }
+ }
+
+}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs b/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs
index 297acda9524c..46a694192842 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs
@@ -132,6 +132,7 @@ public enum ExprKind
UTF8_STRING_LITERAL = 135,
COLLECTION = 136,
SPREAD_ELEMENT = 137,
+ INTERPOLATED_STRING_INSERT = 138,
DEFINE_SYMBOL = 999,
}
}
diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll
index 1a044a77777d..b7681994e2c3 100644
--- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll
+++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll
@@ -66,6 +66,9 @@ private class LocalTaintExprStepConfiguration extends ControlFlowReachabilityCon
e1 = e2.(InterpolatedStringExpr).getAChild() and
scope = e2
or
+ e1 = e2.(InterpolatedStringInsertExpr).getInsert() and
+ scope = e2
+ or
e2 =
any(OperatorCall oc |
oc.getTarget().(ConversionOperator).fromLibrary() and
diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll
index 85676bbd2701..ada010652588 100644
--- a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll
+++ b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll
@@ -34,8 +34,9 @@ private import semmle.code.csharp.TypeRef
* `as` expression (`AsExpr`), a cast (`CastExpr`), a `typeof` expression
* (`TypeofExpr`), a `default` expression (`DefaultValueExpr`), an `await`
* expression (`AwaitExpr`), a `nameof` expression (`NameOfExpr`), an
- * interpolated string (`InterpolatedStringExpr`), a qualifiable expression
- * (`QualifiableExpr`), or a literal (`Literal`).
+ * interpolated string (`InterpolatedStringExpr`), an interpolated string
+ * insert (`InterpolatedStringInsertExpr`), a qualifiable expression (`QualifiableExpr`),
+ * or a literal (`Literal`).
*/
class Expr extends ControlFlowElement, @expr {
override Location getALocation() { expr_location(this, result) }
@@ -917,6 +918,40 @@ class NameOfExpr extends Expr, @nameof_expr {
override string getAPrimaryQlClass() { result = "NameOfExpr" }
}
+/**
+ * An interpolated string insert, for example `{pi, align:F3}` on line 3 in
+ *
+ * ```csharp
+ * void Pi() {
+ * float pi = 3.14159f;
+ * Console.WriteLine($"Hello Pi, {pi,6:F3}");
+ * }
+ * ```
+ */
+class InterpolatedStringInsertExpr extends Expr, @interpolated_string_insert_expr {
+ override string toString() { result = "{...}" }
+
+ override string getAPrimaryQlClass() { result = "InterpolatedStringInsertExpr" }
+
+ /**
+ * Gets the insert expression in this interpolated string insert. For
+ * example, the insert expression in `{pi, align:F3}` is `pi`.
+ */
+ Expr getInsert() { result = this.getChild(0) }
+
+ /**
+ * Gets the alignment expression in this interpolated string insert, if any.
+ * For example, the alignment expression in `{pi, align:F3}` is `align`.
+ */
+ Expr getAlignment() { result = this.getChild(1) }
+
+ /**
+ * Gets the format expression in this interpolated string insert, if any.
+ * For example, the format expression in `{pi, align:F3}` is `F3`.
+ */
+ StringLiteral getFormat() { result = this.getChild(2) }
+}
+
/**
* An interpolated string, for example `$"Hello, {name}!"` on line 2 in
*
@@ -931,16 +966,20 @@ class InterpolatedStringExpr extends Expr, @interpolated_string_expr {
override string getAPrimaryQlClass() { result = "InterpolatedStringExpr" }
+ /**
+ * Gets the interpolated string insert at index `i` in this interpolated string, if any.
+ * For example, the interpolated string insert at index `i = 1` is `{pi, align:F3}`
+ * in `$"Hello, {pi, align:F3}!"`.
+ */
+ InterpolatedStringInsertExpr getInterpolatedInsert(int i) { result = this.getChild(i) }
+
/**
* Gets the insert at index `i` in this interpolated string, if any. For
* example, the insert at index `i = 1` is `name` in `$"Hello, {name}!"`.
* Note that there is no insert at index `i = 0`, but instead a text
* element (`getText(0)` gets the text).
*/
- Expr getInsert(int i) {
- result = this.getChild(i) and
- not result instanceof StringLiteral
- }
+ Expr getInsert(int i) { result = this.getInterpolatedInsert(i).getInsert() }
/**
* Gets the text element at index `i` in this interpolated string, if any.
diff --git a/csharp/ql/lib/semmlecode.csharp.dbscheme b/csharp/ql/lib/semmlecode.csharp.dbscheme
index a2bda57dbc6e..66044cfa5bbf 100644
--- a/csharp/ql/lib/semmlecode.csharp.dbscheme
+++ b/csharp/ql/lib/semmlecode.csharp.dbscheme
@@ -1168,6 +1168,7 @@ case @expr.kind of
/* C# 12.0 */
| 136 = @collection_expr
| 137 = @spread_element_expr
+| 138 = @interpolated_string_insert_expr
/* Preprocessor */
| 999 = @define_symbol_expr
;
From 2ca5ec00321f5cb2a17b1ffa1514c26dc917e65d Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Thu, 20 Mar 2025 15:43:03 +0100
Subject: [PATCH 025/409] C#: Add some string interpolation tests with
alignment and formatting.
---
.../StringInterpolation.cs | 17 +++++++++++++
.../library-tests/stringinterpolation/options | 2 ++
.../stringInterpolation.expected | 23 +++++++++++++++++
.../stringInterpolation.ql | 25 +++++++++++++++++++
4 files changed, 67 insertions(+)
create mode 100644 csharp/ql/test/library-tests/stringinterpolation/StringInterpolation.cs
create mode 100644 csharp/ql/test/library-tests/stringinterpolation/options
create mode 100644 csharp/ql/test/library-tests/stringinterpolation/stringInterpolation.expected
create mode 100644 csharp/ql/test/library-tests/stringinterpolation/stringInterpolation.ql
diff --git a/csharp/ql/test/library-tests/stringinterpolation/StringInterpolation.cs b/csharp/ql/test/library-tests/stringinterpolation/StringInterpolation.cs
new file mode 100644
index 000000000000..d14c3d75e465
--- /dev/null
+++ b/csharp/ql/test/library-tests/stringinterpolation/StringInterpolation.cs
@@ -0,0 +1,17 @@
+using System;
+
+public class MyStringInterpolationClass
+{
+
+ public void M()
+ {
+ float i = 3.14159f;
+ const int align = 5;
+ var x1 = $"Hello, Pi {i}";
+ var x2 = $"Hello, Pi {i:F1}";
+ var x3 = $"Hello, Pi {i,6}";
+ var x4 = $"Hello, Pi {i,6:F3}";
+ var x5 = $"Hello, Pi {i,align}";
+ var x6 = $"Hello, Pi {i,align:F2}";
+ }
+}
diff --git a/csharp/ql/test/library-tests/stringinterpolation/options b/csharp/ql/test/library-tests/stringinterpolation/options
new file mode 100644
index 000000000000..77b22963f5c8
--- /dev/null
+++ b/csharp/ql/test/library-tests/stringinterpolation/options
@@ -0,0 +1,2 @@
+semmle-extractor-options: /nostdlib /noconfig
+semmle-extractor-options: --load-sources-from-project:${testdir}/../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
diff --git a/csharp/ql/test/library-tests/stringinterpolation/stringInterpolation.expected b/csharp/ql/test/library-tests/stringinterpolation/stringInterpolation.expected
new file mode 100644
index 000000000000..9ce88ad83c31
--- /dev/null
+++ b/csharp/ql/test/library-tests/stringinterpolation/stringInterpolation.expected
@@ -0,0 +1,23 @@
+inserts
+| StringInterpolation.cs:10:18:10:33 | $"..." | StringInterpolation.cs:10:31:10:31 | access to local variable i |
+| StringInterpolation.cs:11:18:11:36 | $"..." | StringInterpolation.cs:11:31:11:31 | access to local variable i |
+| StringInterpolation.cs:12:18:12:35 | $"..." | StringInterpolation.cs:12:31:12:31 | access to local variable i |
+| StringInterpolation.cs:13:18:13:38 | $"..." | StringInterpolation.cs:13:31:13:31 | access to local variable i |
+| StringInterpolation.cs:14:18:14:39 | $"..." | StringInterpolation.cs:14:31:14:31 | access to local variable i |
+| StringInterpolation.cs:15:18:15:42 | $"..." | StringInterpolation.cs:15:31:15:31 | access to local variable i |
+texts
+| StringInterpolation.cs:10:18:10:33 | $"..." | StringInterpolation.cs:10:20:10:29 | "Hello, Pi " |
+| StringInterpolation.cs:11:18:11:36 | $"..." | StringInterpolation.cs:11:20:11:29 | "Hello, Pi " |
+| StringInterpolation.cs:12:18:12:35 | $"..." | StringInterpolation.cs:12:20:12:29 | "Hello, Pi " |
+| StringInterpolation.cs:13:18:13:38 | $"..." | StringInterpolation.cs:13:20:13:29 | "Hello, Pi " |
+| StringInterpolation.cs:14:18:14:39 | $"..." | StringInterpolation.cs:14:20:14:29 | "Hello, Pi " |
+| StringInterpolation.cs:15:18:15:42 | $"..." | StringInterpolation.cs:15:20:15:29 | "Hello, Pi " |
+interpolationInsertsWithAlign
+| StringInterpolation.cs:12:18:12:35 | $"..." | StringInterpolation.cs:12:31:12:31 | access to local variable i | StringInterpolation.cs:12:33:12:33 | 6 |
+| StringInterpolation.cs:13:18:13:38 | $"..." | StringInterpolation.cs:13:31:13:31 | access to local variable i | StringInterpolation.cs:13:33:13:33 | 6 |
+| StringInterpolation.cs:14:18:14:39 | $"..." | StringInterpolation.cs:14:31:14:31 | access to local variable i | StringInterpolation.cs:14:33:14:37 | access to local variable align |
+| StringInterpolation.cs:15:18:15:42 | $"..." | StringInterpolation.cs:15:31:15:31 | access to local variable i | StringInterpolation.cs:15:33:15:37 | access to local variable align |
+interpolationInsertsWithFormat
+| StringInterpolation.cs:11:18:11:36 | $"..." | StringInterpolation.cs:11:31:11:31 | access to local variable i | StringInterpolation.cs:11:32:11:34 | "F1" |
+| StringInterpolation.cs:13:18:13:38 | $"..." | StringInterpolation.cs:13:31:13:31 | access to local variable i | StringInterpolation.cs:13:34:13:36 | "F3" |
+| StringInterpolation.cs:15:18:15:42 | $"..." | StringInterpolation.cs:15:31:15:31 | access to local variable i | StringInterpolation.cs:15:38:15:40 | "F2" |
diff --git a/csharp/ql/test/library-tests/stringinterpolation/stringInterpolation.ql b/csharp/ql/test/library-tests/stringinterpolation/stringInterpolation.ql
new file mode 100644
index 000000000000..21b33b12b56d
--- /dev/null
+++ b/csharp/ql/test/library-tests/stringinterpolation/stringInterpolation.ql
@@ -0,0 +1,25 @@
+import csharp
+
+query predicate inserts(InterpolatedStringExpr expr, Expr e) {
+ expr.getAnInsert() = e // and inSpecificSource(expr)
+}
+
+query predicate texts(InterpolatedStringExpr expr, StringLiteral literal) {
+ expr.getAText() = literal // and inSpecificSource(expr)
+}
+
+query predicate interpolationInsertsWithAlign(InterpolatedStringExpr expr, Expr insert, Expr align) {
+ exists(InterpolatedStringInsertExpr e | expr.getInterpolatedInsert(_) = e |
+ insert = e.getInsert() and
+ align = e.getAlignment()
+ )
+}
+
+query predicate interpolationInsertsWithFormat(
+ InterpolatedStringExpr expr, Expr insert, StringLiteral format
+) {
+ exists(InterpolatedStringInsertExpr e | expr.getInterpolatedInsert(_) = e |
+ insert = e.getInsert() and
+ format = e.getFormat()
+ )
+}
From a73a61b8fa3916211950688690003867ba85f5c4 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Fri, 21 Mar 2025 12:35:49 +0100
Subject: [PATCH 026/409] C#: Add PrintAst test for string interpolation
expressions.
---
.../stringinterpolation/PrintAst.expected | 70 +++++++++++++++++++
.../stringinterpolation/PrintAst.qlref | 1 +
2 files changed, 71 insertions(+)
create mode 100644 csharp/ql/test/library-tests/stringinterpolation/PrintAst.expected
create mode 100644 csharp/ql/test/library-tests/stringinterpolation/PrintAst.qlref
diff --git a/csharp/ql/test/library-tests/stringinterpolation/PrintAst.expected b/csharp/ql/test/library-tests/stringinterpolation/PrintAst.expected
new file mode 100644
index 000000000000..6529f9feed5c
--- /dev/null
+++ b/csharp/ql/test/library-tests/stringinterpolation/PrintAst.expected
@@ -0,0 +1,70 @@
+StringInterpolation.cs:
+# 3| [Class] MyStringInterpolationClass
+# 6| 5: [Method] M
+# 6| -1: [TypeMention] Void
+# 7| 4: [BlockStmt] {...}
+# 8| 0: [LocalVariableDeclStmt] ... ...;
+# 8| 0: [LocalVariableDeclAndInitExpr] Single i = ...
+# 8| -1: [TypeMention] float
+# 8| 0: [LocalVariableAccess] access to local variable i
+# 8| 1: [FloatLiteral] 3.14159
+# 9| 1: [LocalConstantDeclStmt] const ... ...;
+# 9| 0: [LocalVariableDeclAndInitExpr] Int32 align = ...
+# 9| -1: [TypeMention] int
+# 9| 0: [LocalVariableAccess] access to local variable align
+# 9| 1: [IntLiteral] 5
+# 10| 2: [LocalVariableDeclStmt] ... ...;
+# 10| 0: [LocalVariableDeclAndInitExpr] String x1 = ...
+# 10| -1: [TypeMention] string
+# 10| 0: [LocalVariableAccess] access to local variable x1
+# 10| 1: [InterpolatedStringExpr] $"..."
+# 10| 0: [StringLiteralUtf16] "Hello, Pi "
+# 10| 1: [InterpolatedStringInsertExpr] {...}
+# 10| 0: [LocalVariableAccess] access to local variable i
+# 11| 3: [LocalVariableDeclStmt] ... ...;
+# 11| 0: [LocalVariableDeclAndInitExpr] String x2 = ...
+# 11| -1: [TypeMention] string
+# 11| 0: [LocalVariableAccess] access to local variable x2
+# 11| 1: [InterpolatedStringExpr] $"..."
+# 11| 0: [StringLiteralUtf16] "Hello, Pi "
+# 11| 1: [InterpolatedStringInsertExpr] {...}
+# 11| 0: [LocalVariableAccess] access to local variable i
+# 11| 2: [StringLiteralUtf16] "F1"
+# 12| 4: [LocalVariableDeclStmt] ... ...;
+# 12| 0: [LocalVariableDeclAndInitExpr] String x3 = ...
+# 12| -1: [TypeMention] string
+# 12| 0: [LocalVariableAccess] access to local variable x3
+# 12| 1: [InterpolatedStringExpr] $"..."
+# 12| 0: [StringLiteralUtf16] "Hello, Pi "
+# 12| 1: [InterpolatedStringInsertExpr] {...}
+# 12| 0: [LocalVariableAccess] access to local variable i
+# 12| 1: [IntLiteral] 6
+# 13| 5: [LocalVariableDeclStmt] ... ...;
+# 13| 0: [LocalVariableDeclAndInitExpr] String x4 = ...
+# 13| -1: [TypeMention] string
+# 13| 0: [LocalVariableAccess] access to local variable x4
+# 13| 1: [InterpolatedStringExpr] $"..."
+# 13| 0: [StringLiteralUtf16] "Hello, Pi "
+# 13| 1: [InterpolatedStringInsertExpr] {...}
+# 13| 0: [LocalVariableAccess] access to local variable i
+# 13| 1: [IntLiteral] 6
+# 13| 2: [StringLiteralUtf16] "F3"
+# 14| 6: [LocalVariableDeclStmt] ... ...;
+# 14| 0: [LocalVariableDeclAndInitExpr] String x5 = ...
+# 14| -1: [TypeMention] string
+# 14| 0: [LocalVariableAccess] access to local variable x5
+# 14| 1: [InterpolatedStringExpr] $"..."
+# 14| 0: [StringLiteralUtf16] "Hello, Pi "
+# 14| 1: [InterpolatedStringInsertExpr] {...}
+# 14| 0: [LocalVariableAccess] access to local variable i
+# 14| 1: [LocalVariableAccess] access to local variable align
+# 15| 7: [LocalVariableDeclStmt] ... ...;
+# 15| 0: [LocalVariableDeclAndInitExpr] String x6 = ...
+# 15| -1: [TypeMention] string
+# 15| 0: [LocalVariableAccess] access to local variable x6
+# 15| 1: [InterpolatedStringExpr] $"..."
+# 15| 0: [StringLiteralUtf16] "Hello, Pi "
+# 15| 1: [InterpolatedStringInsertExpr] {...}
+# 15| 0: [LocalVariableAccess] access to local variable i
+# 15| 1: [LocalVariableAccess] access to local variable align
+# 15| 2: [StringLiteralUtf16] "F2"
diff --git a/csharp/ql/test/library-tests/stringinterpolation/PrintAst.qlref b/csharp/ql/test/library-tests/stringinterpolation/PrintAst.qlref
new file mode 100644
index 000000000000..f867dd01f9f8
--- /dev/null
+++ b/csharp/ql/test/library-tests/stringinterpolation/PrintAst.qlref
@@ -0,0 +1 @@
+shared/PrintAst.ql
\ No newline at end of file
From 5ae7e5ddb3890de6369a6be488d45fcee416d819 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Fri, 21 Mar 2025 12:44:46 +0100
Subject: [PATCH 027/409] C#: Update other test expected output files.
---
.../controlflow/graph/BasicBlock.expected | 18 +++----
.../controlflow/graph/Dominance.expected | 54 ++++++++++++-------
.../graph/EnclosingCallable.expected | 9 ++++
.../controlflow/graph/EntryElement.expected | 9 ++++
.../controlflow/graph/ExitElement.expected | 9 ++++
.../controlflow/graph/NodeGraph.expected | 27 ++++++----
.../library-tests/csharp11/PrintAst.expected | 26 +++++----
.../csharp6/InterpolatedStringExpr.expected | 16 +++---
.../library-tests/csharp6/PrintAst.expected | 44 ++++++++-------
.../library-tests/csharp7.3/PrintAst.expected | 3 +-
.../library-tests/csharp7/IsFlow.expected | 12 +++--
.../csharp7/LocalTaintFlow.expected | 18 ++++---
.../library-tests/csharp7/PrintAst.expected | 18 ++++---
.../library-tests/csharp8/PrintAst.expected | 6 ++-
.../library-tests/csharp9/PrintAst.expected | 5 +-
.../implicittostring/PrintAst.expected | 10 ++--
.../dataflow/local/TaintTrackingStep.expected | 12 +++--
17 files changed, 194 insertions(+), 102 deletions(-)
diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected
index b3ea35fe7e4b..623b5404f781 100644
--- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected
+++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected
@@ -377,8 +377,8 @@
| Conditions.cs:143:10:143:12 | exit M11 (normal) | Conditions.cs:143:10:143:12 | exit M11 | 2 |
| Conditions.cs:145:21:145:23 | [b (line 143): true] "a" | Conditions.cs:146:13:146:13 | [b (line 143): true] access to parameter b | 5 |
| Conditions.cs:145:27:145:29 | [b (line 143): false] "b" | Conditions.cs:146:13:146:13 | [b (line 143): false] access to parameter b | 5 |
-| Conditions.cs:147:13:147:49 | ...; | Conditions.cs:147:13:147:48 | call to method WriteLine | 5 |
-| Conditions.cs:149:13:149:49 | ...; | Conditions.cs:149:13:149:48 | call to method WriteLine | 5 |
+| Conditions.cs:147:13:147:49 | ...; | Conditions.cs:147:13:147:48 | call to method WriteLine | 6 |
+| Conditions.cs:149:13:149:49 | ...; | Conditions.cs:149:13:149:48 | call to method WriteLine | 6 |
| ExitMethods.cs:6:7:6:17 | enter ExitMethods | ExitMethods.cs:6:7:6:17 | exit ExitMethods | 5 |
| ExitMethods.cs:8:10:8:11 | enter M1 | ExitMethods.cs:8:10:8:11 | exit M1 | 8 |
| ExitMethods.cs:14:10:14:11 | enter M2 | ExitMethods.cs:14:10:14:11 | exit M2 | 8 |
@@ -859,11 +859,11 @@
| Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:8:18:8:23 | Int32 i1 | 8 |
| Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:8:13:8:23 | [false] ... is ... | 1 |
| Patterns.cs:8:13:8:23 | [true] ... is ... | Patterns.cs:8:13:8:23 | [true] ... is ... | 1 |
-| Patterns.cs:9:9:11:9 | {...} | Patterns.cs:10:13:10:42 | call to method WriteLine | 6 |
+| Patterns.cs:9:9:11:9 | {...} | Patterns.cs:10:13:10:42 | call to method WriteLine | 7 |
| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:23:12:31 | String s1 | 3 |
| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:12:18:12:31 | [false] ... is ... | 1 |
| Patterns.cs:12:18:12:31 | [true] ... is ... | Patterns.cs:12:18:12:31 | [true] ... is ... | 1 |
-| Patterns.cs:13:9:15:9 | {...} | Patterns.cs:14:13:14:45 | call to method WriteLine | 6 |
+| Patterns.cs:13:9:15:9 | {...} | Patterns.cs:14:13:14:45 | call to method WriteLine | 7 |
| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:16:23:16:28 | Object v1 | 3 |
| Patterns.cs:16:18:16:28 | [false] ... is ... | Patterns.cs:16:18:16:28 | [false] ... is ... | 1 |
| Patterns.cs:16:18:16:28 | [true] ... is ... | Patterns.cs:16:18:16:28 | [true] ... is ... | 1 |
@@ -872,11 +872,11 @@
| Patterns.cs:23:17:23:22 | break; | Patterns.cs:23:17:23:22 | break; | 1 |
| Patterns.cs:24:13:24:36 | case ...: | Patterns.cs:24:18:24:23 | Int32 i2 | 2 |
| Patterns.cs:24:30:24:31 | access to local variable i2 | Patterns.cs:24:30:24:35 | ... > ... | 3 |
-| Patterns.cs:25:17:25:52 | ...; | Patterns.cs:26:17:26:22 | break; | 6 |
+| Patterns.cs:25:17:25:52 | ...; | Patterns.cs:26:17:26:22 | break; | 7 |
| Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:27:18:27:23 | Int32 i3 | 2 |
-| Patterns.cs:28:17:28:47 | ...; | Patterns.cs:29:17:29:22 | break; | 6 |
+| Patterns.cs:28:17:28:47 | ...; | Patterns.cs:29:17:29:22 | break; | 7 |
| Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:30:18:30:26 | String s2 | 2 |
-| Patterns.cs:31:17:31:50 | ...; | Patterns.cs:32:17:32:22 | break; | 6 |
+| Patterns.cs:31:17:31:50 | ...; | Patterns.cs:32:17:32:22 | break; | 7 |
| Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:33:18:33:23 | Object v2 | 2 |
| Patterns.cs:34:17:34:22 | break; | Patterns.cs:34:17:34:22 | break; | 1 |
| Patterns.cs:35:13:35:20 | default: | Patterns.cs:37:17:37:22 | break; | 5 |
@@ -1076,8 +1076,8 @@
| Switch.cs:156:36:156:38 | "a" | Switch.cs:156:28:156:38 | ... => ... | 2 |
| Switch.cs:156:41:156:45 | false | Switch.cs:156:41:156:45 | false | 1 |
| Switch.cs:156:50:156:52 | "b" | Switch.cs:156:41:156:52 | ... => ... | 2 |
-| Switch.cs:158:13:158:49 | ...; | Switch.cs:158:13:158:48 | call to method WriteLine | 5 |
-| Switch.cs:160:13:160:49 | ...; | Switch.cs:160:13:160:48 | call to method WriteLine | 5 |
+| Switch.cs:158:13:158:49 | ...; | Switch.cs:158:13:158:48 | call to method WriteLine | 6 |
+| Switch.cs:160:13:160:49 | ...; | Switch.cs:160:13:160:48 | call to method WriteLine | 6 |
| TypeAccesses.cs:1:7:1:18 | enter TypeAccesses | TypeAccesses.cs:1:7:1:18 | exit TypeAccesses | 5 |
| TypeAccesses.cs:3:10:3:10 | enter M | TypeAccesses.cs:7:18:7:22 | Int32 j | 13 |
| TypeAccesses.cs:7:13:7:22 | [false] ... is ... | TypeAccesses.cs:7:13:7:22 | [false] ... is ... | 1 |
diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected
index 7706539ad306..b2d700660689 100644
--- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected
+++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected
@@ -1527,11 +1527,13 @@ dominance
| Conditions.cs:147:13:147:49 | ...; | Conditions.cs:147:40:147:43 | "a = " |
| Conditions.cs:147:38:147:47 | $"..." | Conditions.cs:147:13:147:48 | call to method WriteLine |
| Conditions.cs:147:40:147:43 | "a = " | Conditions.cs:147:45:147:45 | access to local variable s |
-| Conditions.cs:147:45:147:45 | access to local variable s | Conditions.cs:147:38:147:47 | $"..." |
+| Conditions.cs:147:44:147:46 | {...} | Conditions.cs:147:38:147:47 | $"..." |
+| Conditions.cs:147:45:147:45 | access to local variable s | Conditions.cs:147:44:147:46 | {...} |
| Conditions.cs:149:13:149:49 | ...; | Conditions.cs:149:40:149:43 | "b = " |
| Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:149:13:149:48 | call to method WriteLine |
| Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:149:45:149:45 | access to local variable s |
-| Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:38:149:47 | $"..." |
+| Conditions.cs:149:44:149:46 | {...} | Conditions.cs:149:38:149:47 | $"..." |
+| Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:44:149:46 | {...} |
| ExitMethods.cs:6:7:6:17 | call to constructor Object | ExitMethods.cs:6:7:6:17 | {...} |
| ExitMethods.cs:6:7:6:17 | enter ExitMethods | ExitMethods.cs:6:7:6:17 | call to constructor Object |
| ExitMethods.cs:6:7:6:17 | exit ExitMethods (normal) | ExitMethods.cs:6:7:6:17 | exit ExitMethods |
@@ -3147,7 +3149,8 @@ dominance
| Patterns.cs:10:13:10:43 | ...; | Patterns.cs:10:33:10:36 | "int " |
| Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:13:10:42 | call to method WriteLine |
| Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:38:10:39 | access to local variable i1 |
-| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:31:10:41 | $"..." |
+| Patterns.cs:10:37:10:40 | {...} | Patterns.cs:10:31:10:41 | $"..." |
+| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:37:10:40 | {...} |
| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:18:12:18 | access to local variable o |
| Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:12:23:12:31 | String s1 |
| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:16:14:18:9 | if (...) ... |
@@ -3158,7 +3161,8 @@ dominance
| Patterns.cs:14:13:14:46 | ...; | Patterns.cs:14:33:14:39 | "string " |
| Patterns.cs:14:31:14:44 | $"..." | Patterns.cs:14:13:14:45 | call to method WriteLine |
| Patterns.cs:14:33:14:39 | "string " | Patterns.cs:14:41:14:42 | access to local variable s1 |
-| Patterns.cs:14:41:14:42 | access to local variable s1 | Patterns.cs:14:31:14:44 | $"..." |
+| Patterns.cs:14:40:14:43 | {...} | Patterns.cs:14:31:14:44 | $"..." |
+| Patterns.cs:14:41:14:42 | access to local variable s1 | Patterns.cs:14:40:14:43 | {...} |
| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:16:18:16:18 | access to local variable o |
| Patterns.cs:16:18:16:18 | access to local variable o | Patterns.cs:16:23:16:28 | Object v1 |
| Patterns.cs:16:18:16:28 | [true] ... is ... | Patterns.cs:17:9:18:9 | {...} |
@@ -3179,7 +3183,8 @@ dominance
| Patterns.cs:25:17:25:52 | ...; | Patterns.cs:25:37:25:45 | "positive " |
| Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:17:25:51 | call to method WriteLine |
| Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:25:47:25:48 | access to local variable i2 |
-| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:35:25:50 | $"..." |
+| Patterns.cs:25:46:25:49 | {...} | Patterns.cs:25:35:25:50 | $"..." |
+| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:46:25:49 | {...} |
| Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:27:18:27:23 | Int32 i3 |
| Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:28:17:28:47 | ...; |
| Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:30:13:30:27 | case ...: |
@@ -3187,7 +3192,8 @@ dominance
| Patterns.cs:28:17:28:47 | ...; | Patterns.cs:28:37:28:40 | "int " |
| Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:17:28:46 | call to method WriteLine |
| Patterns.cs:28:37:28:40 | "int " | Patterns.cs:28:42:28:43 | access to local variable i3 |
-| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:35:28:45 | $"..." |
+| Patterns.cs:28:41:28:44 | {...} | Patterns.cs:28:35:28:45 | $"..." |
+| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:41:28:44 | {...} |
| Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:30:18:30:26 | String s2 |
| Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:31:17:31:50 | ...; |
| Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:33:13:33:24 | case ...: |
@@ -3195,7 +3201,8 @@ dominance
| Patterns.cs:31:17:31:50 | ...; | Patterns.cs:31:37:31:43 | "string " |
| Patterns.cs:31:35:31:48 | $"..." | Patterns.cs:31:17:31:49 | call to method WriteLine |
| Patterns.cs:31:37:31:43 | "string " | Patterns.cs:31:45:31:46 | access to local variable s2 |
-| Patterns.cs:31:45:31:46 | access to local variable s2 | Patterns.cs:31:35:31:48 | $"..." |
+| Patterns.cs:31:44:31:47 | {...} | Patterns.cs:31:35:31:48 | $"..." |
+| Patterns.cs:31:45:31:46 | access to local variable s2 | Patterns.cs:31:44:31:47 | {...} |
| Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:33:18:33:23 | Object v2 |
| Patterns.cs:33:18:33:23 | Object v2 | Patterns.cs:34:17:34:22 | break; |
| Patterns.cs:33:18:33:23 | Object v2 | Patterns.cs:35:13:35:20 | default: |
@@ -3664,11 +3671,13 @@ dominance
| Switch.cs:158:13:158:49 | ...; | Switch.cs:158:40:158:43 | "a = " |
| Switch.cs:158:38:158:47 | $"..." | Switch.cs:158:13:158:48 | call to method WriteLine |
| Switch.cs:158:40:158:43 | "a = " | Switch.cs:158:45:158:45 | access to local variable s |
-| Switch.cs:158:45:158:45 | access to local variable s | Switch.cs:158:38:158:47 | $"..." |
+| Switch.cs:158:44:158:46 | {...} | Switch.cs:158:38:158:47 | $"..." |
+| Switch.cs:158:45:158:45 | access to local variable s | Switch.cs:158:44:158:46 | {...} |
| Switch.cs:160:13:160:49 | ...; | Switch.cs:160:40:160:43 | "b = " |
| Switch.cs:160:38:160:47 | $"..." | Switch.cs:160:13:160:48 | call to method WriteLine |
| Switch.cs:160:40:160:43 | "b = " | Switch.cs:160:45:160:45 | access to local variable s |
-| Switch.cs:160:45:160:45 | access to local variable s | Switch.cs:160:38:160:47 | $"..." |
+| Switch.cs:160:44:160:46 | {...} | Switch.cs:160:38:160:47 | $"..." |
+| Switch.cs:160:45:160:45 | access to local variable s | Switch.cs:160:44:160:46 | {...} |
| TypeAccesses.cs:1:7:1:18 | call to constructor Object | TypeAccesses.cs:1:7:1:18 | {...} |
| TypeAccesses.cs:1:7:1:18 | enter TypeAccesses | TypeAccesses.cs:1:7:1:18 | call to constructor Object |
| TypeAccesses.cs:1:7:1:18 | exit TypeAccesses (normal) | TypeAccesses.cs:1:7:1:18 | exit TypeAccesses |
@@ -5858,13 +5867,15 @@ postDominance
| Conditions.cs:146:13:146:13 | [b (line 143): true] access to parameter b | Conditions.cs:146:9:149:49 | [b (line 143): true] if (...) ... |
| Conditions.cs:147:13:147:48 | call to method WriteLine | Conditions.cs:147:38:147:47 | $"..." |
| Conditions.cs:147:13:147:49 | ...; | Conditions.cs:146:13:146:13 | [b (line 143): true] access to parameter b |
-| Conditions.cs:147:38:147:47 | $"..." | Conditions.cs:147:45:147:45 | access to local variable s |
+| Conditions.cs:147:38:147:47 | $"..." | Conditions.cs:147:44:147:46 | {...} |
| Conditions.cs:147:40:147:43 | "a = " | Conditions.cs:147:13:147:49 | ...; |
+| Conditions.cs:147:44:147:46 | {...} | Conditions.cs:147:45:147:45 | access to local variable s |
| Conditions.cs:147:45:147:45 | access to local variable s | Conditions.cs:147:40:147:43 | "a = " |
| Conditions.cs:149:13:149:48 | call to method WriteLine | Conditions.cs:149:38:149:47 | $"..." |
| Conditions.cs:149:13:149:49 | ...; | Conditions.cs:146:13:146:13 | [b (line 143): false] access to parameter b |
-| Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:149:45:149:45 | access to local variable s |
+| Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:149:44:149:46 | {...} |
| Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:149:13:149:49 | ...; |
+| Conditions.cs:149:44:149:46 | {...} | Conditions.cs:149:45:149:45 | access to local variable s |
| Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:40:149:43 | "b = " |
| ExitMethods.cs:6:7:6:17 | call to constructor Object | ExitMethods.cs:6:7:6:17 | enter ExitMethods |
| ExitMethods.cs:6:7:6:17 | exit ExitMethods | ExitMethods.cs:6:7:6:17 | exit ExitMethods (normal) |
@@ -7341,8 +7352,9 @@ postDominance
| Patterns.cs:9:9:11:9 | {...} | Patterns.cs:8:13:8:23 | [true] ... is ... |
| Patterns.cs:10:13:10:42 | call to method WriteLine | Patterns.cs:10:31:10:41 | $"..." |
| Patterns.cs:10:13:10:43 | ...; | Patterns.cs:9:9:11:9 | {...} |
-| Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:38:10:39 | access to local variable i1 |
+| Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:37:10:40 | {...} |
| Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:13:10:43 | ...; |
+| Patterns.cs:10:37:10:40 | {...} | Patterns.cs:10:38:10:39 | access to local variable i1 |
| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:33:10:36 | "int " |
| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:8:13:8:23 | [false] ... is ... |
| Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:12:14:18:9 | if (...) ... |
@@ -7350,8 +7362,9 @@ postDominance
| Patterns.cs:13:9:15:9 | {...} | Patterns.cs:12:18:12:31 | [true] ... is ... |
| Patterns.cs:14:13:14:45 | call to method WriteLine | Patterns.cs:14:31:14:44 | $"..." |
| Patterns.cs:14:13:14:46 | ...; | Patterns.cs:13:9:15:9 | {...} |
-| Patterns.cs:14:31:14:44 | $"..." | Patterns.cs:14:41:14:42 | access to local variable s1 |
+| Patterns.cs:14:31:14:44 | $"..." | Patterns.cs:14:40:14:43 | {...} |
| Patterns.cs:14:33:14:39 | "string " | Patterns.cs:14:13:14:46 | ...; |
+| Patterns.cs:14:40:14:43 | {...} | Patterns.cs:14:41:14:42 | access to local variable s1 |
| Patterns.cs:14:41:14:42 | access to local variable s1 | Patterns.cs:14:33:14:39 | "string " |
| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:12:18:12:31 | [false] ... is ... |
| Patterns.cs:16:18:16:18 | access to local variable o | Patterns.cs:16:14:18:9 | if (...) ... |
@@ -7368,20 +7381,23 @@ postDominance
| Patterns.cs:24:30:24:35 | ... > ... | Patterns.cs:24:35:24:35 | 0 |
| Patterns.cs:24:35:24:35 | 0 | Patterns.cs:24:30:24:31 | access to local variable i2 |
| Patterns.cs:25:17:25:51 | call to method WriteLine | Patterns.cs:25:35:25:50 | $"..." |
-| Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:47:25:48 | access to local variable i2 |
+| Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:46:25:49 | {...} |
| Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:25:17:25:52 | ...; |
+| Patterns.cs:25:46:25:49 | {...} | Patterns.cs:25:47:25:48 | access to local variable i2 |
| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:37:25:45 | "positive " |
| Patterns.cs:26:17:26:22 | break; | Patterns.cs:25:17:25:51 | call to method WriteLine |
| Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:27:13:27:24 | case ...: |
| Patterns.cs:28:17:28:46 | call to method WriteLine | Patterns.cs:28:35:28:45 | $"..." |
-| Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:42:28:43 | access to local variable i3 |
+| Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:41:28:44 | {...} |
| Patterns.cs:28:37:28:40 | "int " | Patterns.cs:28:17:28:47 | ...; |
+| Patterns.cs:28:41:28:44 | {...} | Patterns.cs:28:42:28:43 | access to local variable i3 |
| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:37:28:40 | "int " |
| Patterns.cs:29:17:29:22 | break; | Patterns.cs:28:17:28:46 | call to method WriteLine |
| Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:30:13:30:27 | case ...: |
| Patterns.cs:31:17:31:49 | call to method WriteLine | Patterns.cs:31:35:31:48 | $"..." |
-| Patterns.cs:31:35:31:48 | $"..." | Patterns.cs:31:45:31:46 | access to local variable s2 |
+| Patterns.cs:31:35:31:48 | $"..." | Patterns.cs:31:44:31:47 | {...} |
| Patterns.cs:31:37:31:43 | "string " | Patterns.cs:31:17:31:50 | ...; |
+| Patterns.cs:31:44:31:47 | {...} | Patterns.cs:31:45:31:46 | access to local variable s2 |
| Patterns.cs:31:45:31:46 | access to local variable s2 | Patterns.cs:31:37:31:43 | "string " |
| Patterns.cs:32:17:32:22 | break; | Patterns.cs:31:17:31:49 | call to method WriteLine |
| Patterns.cs:33:18:33:23 | Object v2 | Patterns.cs:33:13:33:24 | case ...: |
@@ -7829,12 +7845,14 @@ postDominance
| Switch.cs:157:9:160:49 | if (...) ... | Switch.cs:156:13:156:54 | String s = ... |
| Switch.cs:157:13:157:13 | access to parameter b | Switch.cs:157:9:160:49 | if (...) ... |
| Switch.cs:158:13:158:48 | call to method WriteLine | Switch.cs:158:38:158:47 | $"..." |
-| Switch.cs:158:38:158:47 | $"..." | Switch.cs:158:45:158:45 | access to local variable s |
+| Switch.cs:158:38:158:47 | $"..." | Switch.cs:158:44:158:46 | {...} |
| Switch.cs:158:40:158:43 | "a = " | Switch.cs:158:13:158:49 | ...; |
+| Switch.cs:158:44:158:46 | {...} | Switch.cs:158:45:158:45 | access to local variable s |
| Switch.cs:158:45:158:45 | access to local variable s | Switch.cs:158:40:158:43 | "a = " |
| Switch.cs:160:13:160:48 | call to method WriteLine | Switch.cs:160:38:160:47 | $"..." |
-| Switch.cs:160:38:160:47 | $"..." | Switch.cs:160:45:160:45 | access to local variable s |
+| Switch.cs:160:38:160:47 | $"..." | Switch.cs:160:44:160:46 | {...} |
| Switch.cs:160:40:160:43 | "b = " | Switch.cs:160:13:160:49 | ...; |
+| Switch.cs:160:44:160:46 | {...} | Switch.cs:160:45:160:45 | access to local variable s |
| Switch.cs:160:45:160:45 | access to local variable s | Switch.cs:160:40:160:43 | "b = " |
| TypeAccesses.cs:1:7:1:18 | call to constructor Object | TypeAccesses.cs:1:7:1:18 | enter TypeAccesses |
| TypeAccesses.cs:1:7:1:18 | exit TypeAccesses | TypeAccesses.cs:1:7:1:18 | exit TypeAccesses (normal) |
diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected
index 4f208361ea1a..57e393adc39a 100644
--- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected
+++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected
@@ -1642,11 +1642,13 @@ nodeEnclosing
| Conditions.cs:147:13:147:49 | ...; | Conditions.cs:143:10:143:12 | M11 |
| Conditions.cs:147:38:147:47 | $"..." | Conditions.cs:143:10:143:12 | M11 |
| Conditions.cs:147:40:147:43 | "a = " | Conditions.cs:143:10:143:12 | M11 |
+| Conditions.cs:147:44:147:46 | {...} | Conditions.cs:143:10:143:12 | M11 |
| Conditions.cs:147:45:147:45 | access to local variable s | Conditions.cs:143:10:143:12 | M11 |
| Conditions.cs:149:13:149:48 | call to method WriteLine | Conditions.cs:143:10:143:12 | M11 |
| Conditions.cs:149:13:149:49 | ...; | Conditions.cs:143:10:143:12 | M11 |
| Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:143:10:143:12 | M11 |
| Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:143:10:143:12 | M11 |
+| Conditions.cs:149:44:149:46 | {...} | Conditions.cs:143:10:143:12 | M11 |
| Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:143:10:143:12 | M11 |
| ExitMethods.cs:6:7:6:17 | call to constructor Object | ExitMethods.cs:6:7:6:17 | ExitMethods |
| ExitMethods.cs:6:7:6:17 | enter ExitMethods | ExitMethods.cs:6:7:6:17 | ExitMethods |
@@ -3436,6 +3438,7 @@ nodeEnclosing
| Patterns.cs:10:13:10:43 | ...; | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:10:33:10:36 | "int " | Patterns.cs:5:10:5:11 | M1 |
+| Patterns.cs:10:37:10:40 | {...} | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:5:10:5:11 | M1 |
@@ -3447,6 +3450,7 @@ nodeEnclosing
| Patterns.cs:14:13:14:46 | ...; | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:14:31:14:44 | $"..." | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:14:33:14:39 | "string " | Patterns.cs:5:10:5:11 | M1 |
+| Patterns.cs:14:40:14:43 | {...} | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:14:41:14:42 | access to local variable s1 | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:16:18:16:18 | access to local variable o | Patterns.cs:5:10:5:11 | M1 |
@@ -3468,6 +3472,7 @@ nodeEnclosing
| Patterns.cs:25:17:25:52 | ...; | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:5:10:5:11 | M1 |
+| Patterns.cs:25:46:25:49 | {...} | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:26:17:26:22 | break; | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:5:10:5:11 | M1 |
@@ -3476,6 +3481,7 @@ nodeEnclosing
| Patterns.cs:28:17:28:47 | ...; | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:28:37:28:40 | "int " | Patterns.cs:5:10:5:11 | M1 |
+| Patterns.cs:28:41:28:44 | {...} | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:29:17:29:22 | break; | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:5:10:5:11 | M1 |
@@ -3484,6 +3490,7 @@ nodeEnclosing
| Patterns.cs:31:17:31:50 | ...; | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:31:35:31:48 | $"..." | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:31:37:31:43 | "string " | Patterns.cs:5:10:5:11 | M1 |
+| Patterns.cs:31:44:31:47 | {...} | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:31:45:31:46 | access to local variable s2 | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:32:17:32:22 | break; | Patterns.cs:5:10:5:11 | M1 |
| Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:5:10:5:11 | M1 |
@@ -4014,11 +4021,13 @@ nodeEnclosing
| Switch.cs:158:13:158:49 | ...; | Switch.cs:154:10:154:12 | M15 |
| Switch.cs:158:38:158:47 | $"..." | Switch.cs:154:10:154:12 | M15 |
| Switch.cs:158:40:158:43 | "a = " | Switch.cs:154:10:154:12 | M15 |
+| Switch.cs:158:44:158:46 | {...} | Switch.cs:154:10:154:12 | M15 |
| Switch.cs:158:45:158:45 | access to local variable s | Switch.cs:154:10:154:12 | M15 |
| Switch.cs:160:13:160:48 | call to method WriteLine | Switch.cs:154:10:154:12 | M15 |
| Switch.cs:160:13:160:49 | ...; | Switch.cs:154:10:154:12 | M15 |
| Switch.cs:160:38:160:47 | $"..." | Switch.cs:154:10:154:12 | M15 |
| Switch.cs:160:40:160:43 | "b = " | Switch.cs:154:10:154:12 | M15 |
+| Switch.cs:160:44:160:46 | {...} | Switch.cs:154:10:154:12 | M15 |
| Switch.cs:160:45:160:45 | access to local variable s | Switch.cs:154:10:154:12 | M15 |
| TypeAccesses.cs:1:7:1:18 | call to constructor Object | TypeAccesses.cs:1:7:1:18 | TypeAccesses |
| TypeAccesses.cs:1:7:1:18 | enter TypeAccesses | TypeAccesses.cs:1:7:1:18 | TypeAccesses |
diff --git a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected
index fddab21f2b62..cc26ecf7c8ed 100644
--- a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected
+++ b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected
@@ -1158,11 +1158,13 @@
| Conditions.cs:147:13:147:49 | ...; | Conditions.cs:147:13:147:49 | ...; |
| Conditions.cs:147:38:147:47 | $"..." | Conditions.cs:147:40:147:43 | "a = " |
| Conditions.cs:147:40:147:43 | "a = " | Conditions.cs:147:40:147:43 | "a = " |
+| Conditions.cs:147:44:147:46 | {...} | Conditions.cs:147:45:147:45 | access to local variable s |
| Conditions.cs:147:45:147:45 | access to local variable s | Conditions.cs:147:45:147:45 | access to local variable s |
| Conditions.cs:149:13:149:48 | call to method WriteLine | Conditions.cs:149:40:149:43 | "b = " |
| Conditions.cs:149:13:149:49 | ...; | Conditions.cs:149:13:149:49 | ...; |
| Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:149:40:149:43 | "b = " |
| Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:149:40:149:43 | "b = " |
+| Conditions.cs:149:44:149:46 | {...} | Conditions.cs:149:45:149:45 | access to local variable s |
| Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:45:149:45 | access to local variable s |
| ExitMethods.cs:6:7:6:17 | call to constructor Object | ExitMethods.cs:6:7:6:17 | call to constructor Object |
| ExitMethods.cs:6:7:6:17 | {...} | ExitMethods.cs:6:7:6:17 | {...} |
@@ -2238,6 +2240,7 @@
| Patterns.cs:10:13:10:43 | ...; | Patterns.cs:10:13:10:43 | ...; |
| Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:33:10:36 | "int " |
| Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:33:10:36 | "int " |
+| Patterns.cs:10:37:10:40 | {...} | Patterns.cs:10:38:10:39 | access to local variable i1 |
| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:38:10:39 | access to local variable i1 |
| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:14:18:9 | if (...) ... |
| Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:12:18:12:18 | access to local variable o |
@@ -2248,6 +2251,7 @@
| Patterns.cs:14:13:14:46 | ...; | Patterns.cs:14:13:14:46 | ...; |
| Patterns.cs:14:31:14:44 | $"..." | Patterns.cs:14:33:14:39 | "string " |
| Patterns.cs:14:33:14:39 | "string " | Patterns.cs:14:33:14:39 | "string " |
+| Patterns.cs:14:40:14:43 | {...} | Patterns.cs:14:41:14:42 | access to local variable s1 |
| Patterns.cs:14:41:14:42 | access to local variable s1 | Patterns.cs:14:41:14:42 | access to local variable s1 |
| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:16:14:18:9 | if (...) ... |
| Patterns.cs:16:18:16:18 | access to local variable o | Patterns.cs:16:18:16:18 | access to local variable o |
@@ -2268,6 +2272,7 @@
| Patterns.cs:25:17:25:52 | ...; | Patterns.cs:25:17:25:52 | ...; |
| Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:37:25:45 | "positive " |
| Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:25:37:25:45 | "positive " |
+| Patterns.cs:25:46:25:49 | {...} | Patterns.cs:25:47:25:48 | access to local variable i2 |
| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:47:25:48 | access to local variable i2 |
| Patterns.cs:26:17:26:22 | break; | Patterns.cs:26:17:26:22 | break; |
| Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:27:13:27:24 | case ...: |
@@ -2276,6 +2281,7 @@
| Patterns.cs:28:17:28:47 | ...; | Patterns.cs:28:17:28:47 | ...; |
| Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:37:28:40 | "int " |
| Patterns.cs:28:37:28:40 | "int " | Patterns.cs:28:37:28:40 | "int " |
+| Patterns.cs:28:41:28:44 | {...} | Patterns.cs:28:42:28:43 | access to local variable i3 |
| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:42:28:43 | access to local variable i3 |
| Patterns.cs:29:17:29:22 | break; | Patterns.cs:29:17:29:22 | break; |
| Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:30:13:30:27 | case ...: |
@@ -2284,6 +2290,7 @@
| Patterns.cs:31:17:31:50 | ...; | Patterns.cs:31:17:31:50 | ...; |
| Patterns.cs:31:35:31:48 | $"..." | Patterns.cs:31:37:31:43 | "string " |
| Patterns.cs:31:37:31:43 | "string " | Patterns.cs:31:37:31:43 | "string " |
+| Patterns.cs:31:44:31:47 | {...} | Patterns.cs:31:45:31:46 | access to local variable s2 |
| Patterns.cs:31:45:31:46 | access to local variable s2 | Patterns.cs:31:45:31:46 | access to local variable s2 |
| Patterns.cs:32:17:32:22 | break; | Patterns.cs:32:17:32:22 | break; |
| Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:33:13:33:24 | case ...: |
@@ -2696,11 +2703,13 @@
| Switch.cs:158:13:158:49 | ...; | Switch.cs:158:13:158:49 | ...; |
| Switch.cs:158:38:158:47 | $"..." | Switch.cs:158:40:158:43 | "a = " |
| Switch.cs:158:40:158:43 | "a = " | Switch.cs:158:40:158:43 | "a = " |
+| Switch.cs:158:44:158:46 | {...} | Switch.cs:158:45:158:45 | access to local variable s |
| Switch.cs:158:45:158:45 | access to local variable s | Switch.cs:158:45:158:45 | access to local variable s |
| Switch.cs:160:13:160:48 | call to method WriteLine | Switch.cs:160:40:160:43 | "b = " |
| Switch.cs:160:13:160:49 | ...; | Switch.cs:160:13:160:49 | ...; |
| Switch.cs:160:38:160:47 | $"..." | Switch.cs:160:40:160:43 | "b = " |
| Switch.cs:160:40:160:43 | "b = " | Switch.cs:160:40:160:43 | "b = " |
+| Switch.cs:160:44:160:46 | {...} | Switch.cs:160:45:160:45 | access to local variable s |
| Switch.cs:160:45:160:45 | access to local variable s | Switch.cs:160:45:160:45 | access to local variable s |
| TypeAccesses.cs:1:7:1:18 | call to constructor Object | TypeAccesses.cs:1:7:1:18 | call to constructor Object |
| TypeAccesses.cs:1:7:1:18 | {...} | TypeAccesses.cs:1:7:1:18 | {...} |
diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected
index 81ee139f6a68..bc47b5b3fa26 100644
--- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected
+++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected
@@ -1452,11 +1452,13 @@
| Conditions.cs:147:13:147:49 | ...; | Conditions.cs:147:13:147:48 | call to method WriteLine | normal |
| Conditions.cs:147:38:147:47 | $"..." | Conditions.cs:147:38:147:47 | $"..." | normal |
| Conditions.cs:147:40:147:43 | "a = " | Conditions.cs:147:40:147:43 | "a = " | normal |
+| Conditions.cs:147:44:147:46 | {...} | Conditions.cs:147:44:147:46 | {...} | normal |
| Conditions.cs:147:45:147:45 | access to local variable s | Conditions.cs:147:45:147:45 | access to local variable s | normal |
| Conditions.cs:149:13:149:48 | call to method WriteLine | Conditions.cs:149:13:149:48 | call to method WriteLine | normal |
| Conditions.cs:149:13:149:49 | ...; | Conditions.cs:149:13:149:48 | call to method WriteLine | normal |
| Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:149:38:149:47 | $"..." | normal |
| Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:149:40:149:43 | "b = " | normal |
+| Conditions.cs:149:44:149:46 | {...} | Conditions.cs:149:44:149:46 | {...} | normal |
| Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:45:149:45 | access to local variable s | normal |
| ExitMethods.cs:6:7:6:17 | call to constructor Object | ExitMethods.cs:6:7:6:17 | call to constructor Object | normal |
| ExitMethods.cs:6:7:6:17 | {...} | ExitMethods.cs:6:7:6:17 | {...} | normal |
@@ -2911,6 +2913,7 @@
| Patterns.cs:10:13:10:43 | ...; | Patterns.cs:10:13:10:42 | call to method WriteLine | normal |
| Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:31:10:41 | $"..." | normal |
| Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:33:10:36 | "int " | normal |
+| Patterns.cs:10:37:10:40 | {...} | Patterns.cs:10:37:10:40 | {...} | normal |
| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:38:10:39 | access to local variable i1 | normal |
| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:14:13:14:45 | call to method WriteLine | normal |
| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:16:18:16:28 | ... is ... | false |
@@ -2925,6 +2928,7 @@
| Patterns.cs:14:13:14:46 | ...; | Patterns.cs:14:13:14:45 | call to method WriteLine | normal |
| Patterns.cs:14:31:14:44 | $"..." | Patterns.cs:14:31:14:44 | $"..." | normal |
| Patterns.cs:14:33:14:39 | "string " | Patterns.cs:14:33:14:39 | "string " | normal |
+| Patterns.cs:14:40:14:43 | {...} | Patterns.cs:14:40:14:43 | {...} | normal |
| Patterns.cs:14:41:14:42 | access to local variable s1 | Patterns.cs:14:41:14:42 | access to local variable s1 | normal |
| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:16:18:16:28 | ... is ... | false |
| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:17:9:18:9 | {...} | normal |
@@ -2959,6 +2963,7 @@
| Patterns.cs:25:17:25:52 | ...; | Patterns.cs:25:17:25:51 | call to method WriteLine | normal |
| Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:35:25:50 | $"..." | normal |
| Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:25:37:25:45 | "positive " | normal |
+| Patterns.cs:25:46:25:49 | {...} | Patterns.cs:25:46:25:49 | {...} | normal |
| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:47:25:48 | access to local variable i2 | normal |
| Patterns.cs:26:17:26:22 | break; | Patterns.cs:26:17:26:22 | break; | break |
| Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:27:18:27:23 | Int32 i3 | no-match |
@@ -2969,6 +2974,7 @@
| Patterns.cs:28:17:28:47 | ...; | Patterns.cs:28:17:28:46 | call to method WriteLine | normal |
| Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:35:28:45 | $"..." | normal |
| Patterns.cs:28:37:28:40 | "int " | Patterns.cs:28:37:28:40 | "int " | normal |
+| Patterns.cs:28:41:28:44 | {...} | Patterns.cs:28:41:28:44 | {...} | normal |
| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:42:28:43 | access to local variable i3 | normal |
| Patterns.cs:29:17:29:22 | break; | Patterns.cs:29:17:29:22 | break; | break |
| Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:30:18:30:26 | String s2 | no-match |
@@ -2979,6 +2985,7 @@
| Patterns.cs:31:17:31:50 | ...; | Patterns.cs:31:17:31:49 | call to method WriteLine | normal |
| Patterns.cs:31:35:31:48 | $"..." | Patterns.cs:31:35:31:48 | $"..." | normal |
| Patterns.cs:31:37:31:43 | "string " | Patterns.cs:31:37:31:43 | "string " | normal |
+| Patterns.cs:31:44:31:47 | {...} | Patterns.cs:31:44:31:47 | {...} | normal |
| Patterns.cs:31:45:31:46 | access to local variable s2 | Patterns.cs:31:45:31:46 | access to local variable s2 | normal |
| Patterns.cs:32:17:32:22 | break; | Patterns.cs:32:17:32:22 | break; | break |
| Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:33:18:33:23 | Object v2 | no-match |
@@ -3566,11 +3573,13 @@
| Switch.cs:158:13:158:49 | ...; | Switch.cs:158:13:158:48 | call to method WriteLine | normal |
| Switch.cs:158:38:158:47 | $"..." | Switch.cs:158:38:158:47 | $"..." | normal |
| Switch.cs:158:40:158:43 | "a = " | Switch.cs:158:40:158:43 | "a = " | normal |
+| Switch.cs:158:44:158:46 | {...} | Switch.cs:158:44:158:46 | {...} | normal |
| Switch.cs:158:45:158:45 | access to local variable s | Switch.cs:158:45:158:45 | access to local variable s | normal |
| Switch.cs:160:13:160:48 | call to method WriteLine | Switch.cs:160:13:160:48 | call to method WriteLine | normal |
| Switch.cs:160:13:160:49 | ...; | Switch.cs:160:13:160:48 | call to method WriteLine | normal |
| Switch.cs:160:38:160:47 | $"..." | Switch.cs:160:38:160:47 | $"..." | normal |
| Switch.cs:160:40:160:43 | "b = " | Switch.cs:160:40:160:43 | "b = " | normal |
+| Switch.cs:160:44:160:46 | {...} | Switch.cs:160:44:160:46 | {...} | normal |
| Switch.cs:160:45:160:45 | access to local variable s | Switch.cs:160:45:160:45 | access to local variable s | normal |
| TypeAccesses.cs:1:7:1:18 | call to constructor Object | TypeAccesses.cs:1:7:1:18 | call to constructor Object | normal |
| TypeAccesses.cs:1:7:1:18 | {...} | TypeAccesses.cs:1:7:1:18 | {...} | normal |
diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected
index 0ae9a8a1e35c..5b3860e04ede 100644
--- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected
+++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected
@@ -1679,12 +1679,14 @@
| Conditions.cs:147:13:147:49 | ...; | Conditions.cs:147:40:147:43 | "a = " | |
| Conditions.cs:147:38:147:47 | $"..." | Conditions.cs:147:13:147:48 | call to method WriteLine | |
| Conditions.cs:147:40:147:43 | "a = " | Conditions.cs:147:45:147:45 | access to local variable s | |
-| Conditions.cs:147:45:147:45 | access to local variable s | Conditions.cs:147:38:147:47 | $"..." | |
+| Conditions.cs:147:44:147:46 | {...} | Conditions.cs:147:38:147:47 | $"..." | |
+| Conditions.cs:147:45:147:45 | access to local variable s | Conditions.cs:147:44:147:46 | {...} | |
| Conditions.cs:149:13:149:48 | call to method WriteLine | Conditions.cs:143:10:143:12 | exit M11 (normal) | |
| Conditions.cs:149:13:149:49 | ...; | Conditions.cs:149:40:149:43 | "b = " | |
| Conditions.cs:149:38:149:47 | $"..." | Conditions.cs:149:13:149:48 | call to method WriteLine | |
| Conditions.cs:149:40:149:43 | "b = " | Conditions.cs:149:45:149:45 | access to local variable s | |
-| Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:38:149:47 | $"..." | |
+| Conditions.cs:149:44:149:46 | {...} | Conditions.cs:149:38:149:47 | $"..." | |
+| Conditions.cs:149:45:149:45 | access to local variable s | Conditions.cs:149:44:149:46 | {...} | |
| ExitMethods.cs:6:7:6:17 | call to constructor Object | ExitMethods.cs:6:7:6:17 | {...} | |
| ExitMethods.cs:6:7:6:17 | enter ExitMethods | ExitMethods.cs:6:7:6:17 | call to constructor Object | |
| ExitMethods.cs:6:7:6:17 | exit ExitMethods (normal) | ExitMethods.cs:6:7:6:17 | exit ExitMethods | |
@@ -3528,7 +3530,8 @@
| Patterns.cs:10:13:10:43 | ...; | Patterns.cs:10:33:10:36 | "int " | |
| Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:13:10:42 | call to method WriteLine | |
| Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:38:10:39 | access to local variable i1 | |
-| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:31:10:41 | $"..." | |
+| Patterns.cs:10:37:10:40 | {...} | Patterns.cs:10:31:10:41 | $"..." | |
+| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:37:10:40 | {...} | |
| Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:18:12:18 | access to local variable o | |
| Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:12:23:12:31 | String s1 | |
| Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:16:14:18:9 | if (...) ... | false |
@@ -3540,7 +3543,8 @@
| Patterns.cs:14:13:14:46 | ...; | Patterns.cs:14:33:14:39 | "string " | |
| Patterns.cs:14:31:14:44 | $"..." | Patterns.cs:14:13:14:45 | call to method WriteLine | |
| Patterns.cs:14:33:14:39 | "string " | Patterns.cs:14:41:14:42 | access to local variable s1 | |
-| Patterns.cs:14:41:14:42 | access to local variable s1 | Patterns.cs:14:31:14:44 | $"..." | |
+| Patterns.cs:14:40:14:43 | {...} | Patterns.cs:14:31:14:44 | $"..." | |
+| Patterns.cs:14:41:14:42 | access to local variable s1 | Patterns.cs:14:40:14:43 | {...} | |
| Patterns.cs:16:14:18:9 | if (...) ... | Patterns.cs:16:18:16:18 | access to local variable o | |
| Patterns.cs:16:18:16:18 | access to local variable o | Patterns.cs:16:23:16:28 | Object v1 | |
| Patterns.cs:16:18:16:28 | [false] ... is ... | Patterns.cs:20:9:38:9 | switch (...) {...} | false |
@@ -3565,7 +3569,8 @@
| Patterns.cs:25:17:25:52 | ...; | Patterns.cs:25:37:25:45 | "positive " | |
| Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:17:25:51 | call to method WriteLine | |
| Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:25:47:25:48 | access to local variable i2 | |
-| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:35:25:50 | $"..." | |
+| Patterns.cs:25:46:25:49 | {...} | Patterns.cs:25:35:25:50 | $"..." | |
+| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:46:25:49 | {...} | |
| Patterns.cs:26:17:26:22 | break; | Patterns.cs:40:9:42:9 | switch (...) {...} | break |
| Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:27:18:27:23 | Int32 i3 | |
| Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:28:17:28:47 | ...; | match |
@@ -3574,7 +3579,8 @@
| Patterns.cs:28:17:28:47 | ...; | Patterns.cs:28:37:28:40 | "int " | |
| Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:17:28:46 | call to method WriteLine | |
| Patterns.cs:28:37:28:40 | "int " | Patterns.cs:28:42:28:43 | access to local variable i3 | |
-| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:35:28:45 | $"..." | |
+| Patterns.cs:28:41:28:44 | {...} | Patterns.cs:28:35:28:45 | $"..." | |
+| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:41:28:44 | {...} | |
| Patterns.cs:29:17:29:22 | break; | Patterns.cs:40:9:42:9 | switch (...) {...} | break |
| Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:30:18:30:26 | String s2 | |
| Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:31:17:31:50 | ...; | match |
@@ -3583,7 +3589,8 @@
| Patterns.cs:31:17:31:50 | ...; | Patterns.cs:31:37:31:43 | "string " | |
| Patterns.cs:31:35:31:48 | $"..." | Patterns.cs:31:17:31:49 | call to method WriteLine | |
| Patterns.cs:31:37:31:43 | "string " | Patterns.cs:31:45:31:46 | access to local variable s2 | |
-| Patterns.cs:31:45:31:46 | access to local variable s2 | Patterns.cs:31:35:31:48 | $"..." | |
+| Patterns.cs:31:44:31:47 | {...} | Patterns.cs:31:35:31:48 | $"..." | |
+| Patterns.cs:31:45:31:46 | access to local variable s2 | Patterns.cs:31:44:31:47 | {...} | |
| Patterns.cs:32:17:32:22 | break; | Patterns.cs:40:9:42:9 | switch (...) {...} | break |
| Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:33:18:33:23 | Object v2 | |
| Patterns.cs:33:18:33:23 | Object v2 | Patterns.cs:34:17:34:22 | break; | match |
@@ -4130,12 +4137,14 @@
| Switch.cs:158:13:158:49 | ...; | Switch.cs:158:40:158:43 | "a = " | |
| Switch.cs:158:38:158:47 | $"..." | Switch.cs:158:13:158:48 | call to method WriteLine | |
| Switch.cs:158:40:158:43 | "a = " | Switch.cs:158:45:158:45 | access to local variable s | |
-| Switch.cs:158:45:158:45 | access to local variable s | Switch.cs:158:38:158:47 | $"..." | |
+| Switch.cs:158:44:158:46 | {...} | Switch.cs:158:38:158:47 | $"..." | |
+| Switch.cs:158:45:158:45 | access to local variable s | Switch.cs:158:44:158:46 | {...} | |
| Switch.cs:160:13:160:48 | call to method WriteLine | Switch.cs:154:10:154:12 | exit M15 (normal) | |
| Switch.cs:160:13:160:49 | ...; | Switch.cs:160:40:160:43 | "b = " | |
| Switch.cs:160:38:160:47 | $"..." | Switch.cs:160:13:160:48 | call to method WriteLine | |
| Switch.cs:160:40:160:43 | "b = " | Switch.cs:160:45:160:45 | access to local variable s | |
-| Switch.cs:160:45:160:45 | access to local variable s | Switch.cs:160:38:160:47 | $"..." | |
+| Switch.cs:160:44:160:46 | {...} | Switch.cs:160:38:160:47 | $"..." | |
+| Switch.cs:160:45:160:45 | access to local variable s | Switch.cs:160:44:160:46 | {...} | |
| TypeAccesses.cs:1:7:1:18 | call to constructor Object | TypeAccesses.cs:1:7:1:18 | {...} | |
| TypeAccesses.cs:1:7:1:18 | enter TypeAccesses | TypeAccesses.cs:1:7:1:18 | call to constructor Object | |
| TypeAccesses.cs:1:7:1:18 | exit TypeAccesses (normal) | TypeAccesses.cs:1:7:1:18 | exit TypeAccesses | |
diff --git a/csharp/ql/test/library-tests/csharp11/PrintAst.expected b/csharp/ql/test/library-tests/csharp11/PrintAst.expected
index b10e2096489b..3a3f44974231 100644
--- a/csharp/ql/test/library-tests/csharp11/PrintAst.expected
+++ b/csharp/ql/test/library-tests/csharp11/PrintAst.expected
@@ -1332,14 +1332,15 @@ Strings.cs:
# 8| 0: [ReturnStmt] return ...;
# 8| 0: [InterpolatedStringExpr] $"..."
# 8| 0: [StringLiteralUtf16] "This is my int "
-# 8| 1: [SwitchExpr] ... switch { ... }
-# 8| -1: [ParameterAccess] access to parameter x
-# 10| 0: [SwitchCaseExpr] ... => ...
-# 10| 0: [ConstantPatternExpr,IntLiteral] 42
-# 10| 2: [StringLiteralUtf16] "forty two"
-# 11| 1: [SwitchCaseExpr] ... => ...
-# 11| 0: [DiscardPatternExpr] _
-# 11| 2: [StringLiteralUtf16] "something else"
+# 8| 1: [InterpolatedStringInsertExpr] {...}
+# 8| 0: [SwitchExpr] ... switch { ... }
+# 8| -1: [ParameterAccess] access to parameter x
+# 10| 0: [SwitchCaseExpr] ... => ...
+# 10| 0: [ConstantPatternExpr,IntLiteral] 42
+# 10| 2: [StringLiteralUtf16] "forty two"
+# 11| 1: [SwitchCaseExpr] ... => ...
+# 11| 0: [DiscardPatternExpr] _
+# 11| 2: [StringLiteralUtf16] "something else"
# 12| 2: [StringLiteralUtf16] "."
# 15| 6: [Method] M2
# 15| -1: [TypeMention] Void
@@ -1359,7 +1360,8 @@ Strings.cs:
# 26| 1: [InterpolatedStringExpr] $"..."
# 27| 0: [StringLiteralUtf16] "The nested message
# 27| is \""
-# 28| 1: [LocalVariableAccess] access to local variable message1
+# 28| 1: [InterpolatedStringInsertExpr] {...}
+# 28| 0: [LocalVariableAccess] access to local variable message1
# 28| 2: [StringLiteralUtf16] "\" and everything
# 28| spans multiple lines."
# 33| 2: [LocalVariableDeclStmt] ... ...;
@@ -1368,10 +1370,12 @@ Strings.cs:
# 33| 0: [LocalVariableAccess] access to local variable message3
# 33| 1: [InterpolatedStringExpr] $"..."
# 34| 0: [StringLiteralUtf16] "Show no curly braces: "
-# 34| 1: [LocalVariableAccess] access to local variable message1
+# 34| 1: [InterpolatedStringInsertExpr] {...}
+# 34| 0: [LocalVariableAccess] access to local variable message1
# 34| 2: [StringLiteralUtf16] "
# 34| Show matching set of curly braces: {"
-# 35| 3: [LocalVariableAccess] access to local variable message2
+# 35| 3: [InterpolatedStringInsertExpr] {...}
+# 35| 0: [LocalVariableAccess] access to local variable message2
# 35| 4: [StringLiteralUtf16] "}"
# 40| 7: [Method] M3
# 40| -1: [TypeMention] Void
diff --git a/csharp/ql/test/library-tests/csharp6/InterpolatedStringExpr.expected b/csharp/ql/test/library-tests/csharp6/InterpolatedStringExpr.expected
index d10365546bd9..a7c904f56867 100644
--- a/csharp/ql/test/library-tests/csharp6/InterpolatedStringExpr.expected
+++ b/csharp/ql/test/library-tests/csharp6/InterpolatedStringExpr.expected
@@ -1,14 +1,14 @@
-| csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:26:25:36 | nameof(...) |
+| csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:25:25:37 | {...} |
| csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:38:25:41 | " is " |
-| csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:43:25:45 | access to local variable foo |
+| csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:42:25:46 | {...} |
| csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:47:25:52 | ", and " |
-| csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:54:25:64 | nameof(...) |
+| csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:53:25:65 | {...} |
| csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:66:25:77 | " has length " |
-| csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:79:25:94 | ... ?? ... |
-| csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:20:27:30 | nameof(...) |
+| csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:78:25:95 | {...} |
+| csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:19:27:31 | {...} |
| csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:32:27:35 | " is " |
-| csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:37:27:39 | access to local variable foo |
+| csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:36:27:40 | {...} |
| csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:41:27:46 | ", and " |
-| csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:48:27:58 | nameof(...) |
+| csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:47:27:59 | {...} |
| csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:60:27:71 | " has length " |
-| csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:73:27:88 | ... ?? ... |
+| csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:72:27:89 | {...} |
diff --git a/csharp/ql/test/library-tests/csharp6/PrintAst.expected b/csharp/ql/test/library-tests/csharp6/PrintAst.expected
index 892ad6dd4b15..424a18bcb023 100644
--- a/csharp/ql/test/library-tests/csharp6/PrintAst.expected
+++ b/csharp/ql/test/library-tests/csharp6/PrintAst.expected
@@ -30,33 +30,41 @@ csharp6.cs:
# 25| 1: [ExprStmt] ...;
# 25| 0: [MethodCall] call to method WriteLine
# 25| 0: [InterpolatedStringExpr] $"..."
-# 25| 0: [NameOfExpr] nameof(...)
-# 25| 0: [LocalVariableAccess] access to local variable foo
+# 25| 0: [InterpolatedStringInsertExpr] {...}
+# 25| 0: [NameOfExpr] nameof(...)
+# 25| 0: [LocalVariableAccess] access to local variable foo
# 25| 1: [StringLiteralUtf16] " is "
-# 25| 2: [LocalVariableAccess] access to local variable foo
+# 25| 2: [InterpolatedStringInsertExpr] {...}
+# 25| 0: [LocalVariableAccess] access to local variable foo
# 25| 3: [StringLiteralUtf16] ", and "
-# 25| 4: [NameOfExpr] nameof(...)
-# 25| 0: [LocalVariableAccess] access to local variable bar
+# 25| 4: [InterpolatedStringInsertExpr] {...}
+# 25| 0: [NameOfExpr] nameof(...)
+# 25| 0: [LocalVariableAccess] access to local variable bar
# 25| 5: [StringLiteralUtf16] " has length "
-# 25| 6: [NullCoalescingExpr] ... ?? ...
-# 25| 0: [PropertyCall] access to property Length
-# 25| -1: [LocalVariableAccess] access to local variable bar
-# 25| 1: [IntLiteral] 0
+# 25| 6: [InterpolatedStringInsertExpr] {...}
+# 25| 0: [NullCoalescingExpr] ... ?? ...
+# 25| 0: [PropertyCall] access to property Length
+# 25| -1: [LocalVariableAccess] access to local variable bar
+# 25| 1: [IntLiteral] 0
# 27| 2: [ExprStmt] ...;
# 27| 0: [MethodCall] call to method Fn
# 27| 0: [InterpolatedStringExpr] $"..."
-# 27| 0: [NameOfExpr] nameof(...)
-# 27| 0: [LocalVariableAccess] access to local variable foo
+# 27| 0: [InterpolatedStringInsertExpr] {...}
+# 27| 0: [NameOfExpr] nameof(...)
+# 27| 0: [LocalVariableAccess] access to local variable foo
# 27| 1: [StringLiteralUtf16] " is "
-# 27| 2: [LocalVariableAccess] access to local variable foo
+# 27| 2: [InterpolatedStringInsertExpr] {...}
+# 27| 0: [LocalVariableAccess] access to local variable foo
# 27| 3: [StringLiteralUtf16] ", and "
-# 27| 4: [NameOfExpr] nameof(...)
-# 27| 0: [LocalVariableAccess] access to local variable bar
+# 27| 4: [InterpolatedStringInsertExpr] {...}
+# 27| 0: [NameOfExpr] nameof(...)
+# 27| 0: [LocalVariableAccess] access to local variable bar
# 27| 5: [StringLiteralUtf16] " has length "
-# 27| 6: [NullCoalescingExpr] ... ?? ...
-# 27| 0: [PropertyCall] access to property Length
-# 27| -1: [LocalVariableAccess] access to local variable bar
-# 27| 1: [IntLiteral] 0
+# 27| 6: [InterpolatedStringInsertExpr] {...}
+# 27| 0: [NullCoalescingExpr] ... ?? ...
+# 27| 0: [PropertyCall] access to property Length
+# 27| -1: [LocalVariableAccess] access to local variable bar
+# 27| 1: [IntLiteral] 0
# 29| 3: [LocalVariableDeclStmt] ... ...;
# 29| 0: [LocalVariableDeclAndInitExpr] Nullable anythingInBar = ...
# 29| -1: [TypeMention] bool?
diff --git a/csharp/ql/test/library-tests/csharp7.3/PrintAst.expected b/csharp/ql/test/library-tests/csharp7.3/PrintAst.expected
index d55d5d279ada..70bfee85c04b 100644
--- a/csharp/ql/test/library-tests/csharp7.3/PrintAst.expected
+++ b/csharp/ql/test/library-tests/csharp7.3/PrintAst.expected
@@ -110,4 +110,5 @@ csharp73.cs:
# 51| 0: [TypeMention] Console
# 51| 0: [InterpolatedStringExpr] $"..."
# 51| 0: [StringLiteralUtf16] "x is "
-# 51| 1: [LocalVariableAccess] access to local variable x
+# 51| 1: [InterpolatedStringInsertExpr] {...}
+# 51| 0: [LocalVariableAccess] access to local variable x
diff --git a/csharp/ql/test/library-tests/csharp7/IsFlow.expected b/csharp/ql/test/library-tests/csharp7/IsFlow.expected
index b3e283528457..ce37b655bb85 100644
--- a/csharp/ql/test/library-tests/csharp7/IsFlow.expected
+++ b/csharp/ql/test/library-tests/csharp7/IsFlow.expected
@@ -24,7 +24,8 @@
| CSharp7.cs:255:17:255:45 | ...; | CSharp7.cs:255:37:255:38 | "x " | semmle.label | successor |
| CSharp7.cs:255:35:255:43 | $"..." | CSharp7.cs:255:17:255:44 | call to method WriteLine | semmle.label | successor |
| CSharp7.cs:255:37:255:38 | "x " | CSharp7.cs:255:40:255:41 | access to local variable s4 | semmle.label | successor |
-| CSharp7.cs:255:40:255:41 | access to local variable s4 | CSharp7.cs:255:35:255:43 | $"..." | semmle.label | successor |
+| CSharp7.cs:255:39:255:42 | {...} | CSharp7.cs:255:35:255:43 | $"..." | semmle.label | successor |
+| CSharp7.cs:255:40:255:41 | access to local variable s4 | CSharp7.cs:255:39:255:42 | {...} | semmle.label | successor |
| CSharp7.cs:256:17:256:22 | break; | CSharp7.cs:230:10:230:13 | exit Test (normal) | semmle.label | break |
| CSharp7.cs:257:13:257:36 | case ...: | CSharp7.cs:257:18:257:23 | Int32 i2 | semmle.label | successor |
| CSharp7.cs:257:18:257:23 | Int32 i2 | CSharp7.cs:257:30:257:31 | access to local variable i2 | semmle.label | match |
@@ -37,7 +38,8 @@
| CSharp7.cs:258:17:258:52 | ...; | CSharp7.cs:258:37:258:45 | "positive " | semmle.label | successor |
| CSharp7.cs:258:35:258:50 | $"..." | CSharp7.cs:258:17:258:51 | call to method WriteLine | semmle.label | successor |
| CSharp7.cs:258:37:258:45 | "positive " | CSharp7.cs:258:47:258:48 | access to local variable i2 | semmle.label | successor |
-| CSharp7.cs:258:47:258:48 | access to local variable i2 | CSharp7.cs:258:35:258:50 | $"..." | semmle.label | successor |
+| CSharp7.cs:258:46:258:49 | {...} | CSharp7.cs:258:35:258:50 | $"..." | semmle.label | successor |
+| CSharp7.cs:258:47:258:48 | access to local variable i2 | CSharp7.cs:258:46:258:49 | {...} | semmle.label | successor |
| CSharp7.cs:259:17:259:22 | break; | CSharp7.cs:230:10:230:13 | exit Test (normal) | semmle.label | break |
| CSharp7.cs:260:13:260:24 | case ...: | CSharp7.cs:260:18:260:23 | Int32 i3 | semmle.label | successor |
| CSharp7.cs:260:18:260:23 | Int32 i3 | CSharp7.cs:261:17:261:47 | ...; | semmle.label | match |
@@ -46,7 +48,8 @@
| CSharp7.cs:261:17:261:47 | ...; | CSharp7.cs:261:37:261:40 | "int " | semmle.label | successor |
| CSharp7.cs:261:35:261:45 | $"..." | CSharp7.cs:261:17:261:46 | call to method WriteLine | semmle.label | successor |
| CSharp7.cs:261:37:261:40 | "int " | CSharp7.cs:261:42:261:43 | access to local variable i3 | semmle.label | successor |
-| CSharp7.cs:261:42:261:43 | access to local variable i3 | CSharp7.cs:261:35:261:45 | $"..." | semmle.label | successor |
+| CSharp7.cs:261:41:261:44 | {...} | CSharp7.cs:261:35:261:45 | $"..." | semmle.label | successor |
+| CSharp7.cs:261:42:261:43 | access to local variable i3 | CSharp7.cs:261:41:261:44 | {...} | semmle.label | successor |
| CSharp7.cs:262:17:262:22 | break; | CSharp7.cs:230:10:230:13 | exit Test (normal) | semmle.label | break |
| CSharp7.cs:263:13:263:27 | case ...: | CSharp7.cs:263:18:263:26 | String s2 | semmle.label | successor |
| CSharp7.cs:263:18:263:26 | String s2 | CSharp7.cs:264:17:264:50 | ...; | semmle.label | match |
@@ -55,7 +58,8 @@
| CSharp7.cs:264:17:264:50 | ...; | CSharp7.cs:264:37:264:43 | "string " | semmle.label | successor |
| CSharp7.cs:264:35:264:48 | $"..." | CSharp7.cs:264:17:264:49 | call to method WriteLine | semmle.label | successor |
| CSharp7.cs:264:37:264:43 | "string " | CSharp7.cs:264:45:264:46 | access to local variable s2 | semmle.label | successor |
-| CSharp7.cs:264:45:264:46 | access to local variable s2 | CSharp7.cs:264:35:264:48 | $"..." | semmle.label | successor |
+| CSharp7.cs:264:44:264:47 | {...} | CSharp7.cs:264:35:264:48 | $"..." | semmle.label | successor |
+| CSharp7.cs:264:45:264:46 | access to local variable s2 | CSharp7.cs:264:44:264:47 | {...} | semmle.label | successor |
| CSharp7.cs:265:17:265:22 | break; | CSharp7.cs:230:10:230:13 | exit Test (normal) | semmle.label | break |
| CSharp7.cs:266:13:266:26 | case ...: | CSharp7.cs:266:18:266:23 | access to type Double | semmle.label | successor |
| CSharp7.cs:266:18:266:23 | access to type Double | CSharp7.cs:267:17:267:44 | ...; | semmle.label | match |
diff --git a/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected b/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected
index 4a16e2491dfe..1bba9f6dd8ba 100644
--- a/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected
+++ b/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected
@@ -254,7 +254,8 @@
| CSharp7.cs:233:28:233:33 | ... > ... | CSharp7.cs:233:13:233:33 | [true] ... && ... |
| CSharp7.cs:235:13:235:42 | [input] SSA phi read(o) | CSharp7.cs:248:9:274:9 | SSA phi read(o) |
| CSharp7.cs:235:33:235:36 | "int " | CSharp7.cs:235:31:235:41 | $"..." |
-| CSharp7.cs:235:38:235:39 | access to local variable i1 | CSharp7.cs:235:31:235:41 | $"..." |
+| CSharp7.cs:235:37:235:40 | {...} | CSharp7.cs:235:31:235:41 | $"..." |
+| CSharp7.cs:235:38:235:39 | access to local variable i1 | CSharp7.cs:235:37:235:40 | {...} |
| CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:237:23:237:31 | String s1 |
| CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:239:13:239:45 | [input] SSA phi read(o) |
| CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:241:18:241:18 | access to local variable o |
@@ -262,7 +263,8 @@
| CSharp7.cs:237:23:237:31 | String s1 | CSharp7.cs:237:23:237:31 | SSA def(s1) |
| CSharp7.cs:239:13:239:45 | [input] SSA phi read(o) | CSharp7.cs:248:9:274:9 | SSA phi read(o) |
| CSharp7.cs:239:33:239:39 | "string " | CSharp7.cs:239:31:239:44 | $"..." |
-| CSharp7.cs:239:41:239:42 | access to local variable s1 | CSharp7.cs:239:31:239:44 | $"..." |
+| CSharp7.cs:239:40:239:43 | {...} | CSharp7.cs:239:31:239:44 | $"..." |
+| CSharp7.cs:239:41:239:42 | access to local variable s1 | CSharp7.cs:239:40:239:43 | {...} |
| CSharp7.cs:241:18:241:18 | access to local variable o | CSharp7.cs:242:9:243:9 | [input] SSA phi read(o) |
| CSharp7.cs:241:18:241:18 | access to local variable o | CSharp7.cs:244:18:244:18 | access to local variable o |
| CSharp7.cs:242:9:243:9 | [input] SSA phi read(o) | CSharp7.cs:248:9:274:9 | SSA phi read(o) |
@@ -283,21 +285,25 @@
| CSharp7.cs:254:32:254:40 | SSA def(s4) | CSharp7.cs:255:40:255:41 | access to local variable s4 |
| CSharp7.cs:254:32:254:40 | String s4 | CSharp7.cs:254:32:254:40 | SSA def(s4) |
| CSharp7.cs:255:37:255:38 | "x " | CSharp7.cs:255:35:255:43 | $"..." |
-| CSharp7.cs:255:40:255:41 | access to local variable s4 | CSharp7.cs:255:35:255:43 | $"..." |
+| CSharp7.cs:255:39:255:42 | {...} | CSharp7.cs:255:35:255:43 | $"..." |
+| CSharp7.cs:255:40:255:41 | access to local variable s4 | CSharp7.cs:255:39:255:42 | {...} |
| CSharp7.cs:257:18:257:23 | Int32 i2 | CSharp7.cs:257:18:257:23 | SSA def(i2) |
| CSharp7.cs:257:18:257:23 | SSA def(i2) | CSharp7.cs:257:30:257:31 | access to local variable i2 |
| CSharp7.cs:257:30:257:31 | access to local variable i2 | CSharp7.cs:257:30:257:35 | ... > ... |
| CSharp7.cs:257:30:257:31 | access to local variable i2 | CSharp7.cs:258:47:258:48 | access to local variable i2 |
| CSharp7.cs:258:37:258:45 | "positive " | CSharp7.cs:258:35:258:50 | $"..." |
-| CSharp7.cs:258:47:258:48 | access to local variable i2 | CSharp7.cs:258:35:258:50 | $"..." |
+| CSharp7.cs:258:46:258:49 | {...} | CSharp7.cs:258:35:258:50 | $"..." |
+| CSharp7.cs:258:47:258:48 | access to local variable i2 | CSharp7.cs:258:46:258:49 | {...} |
| CSharp7.cs:260:18:260:23 | Int32 i3 | CSharp7.cs:260:18:260:23 | SSA def(i3) |
| CSharp7.cs:260:18:260:23 | SSA def(i3) | CSharp7.cs:261:42:261:43 | access to local variable i3 |
| CSharp7.cs:261:37:261:40 | "int " | CSharp7.cs:261:35:261:45 | $"..." |
-| CSharp7.cs:261:42:261:43 | access to local variable i3 | CSharp7.cs:261:35:261:45 | $"..." |
+| CSharp7.cs:261:41:261:44 | {...} | CSharp7.cs:261:35:261:45 | $"..." |
+| CSharp7.cs:261:42:261:43 | access to local variable i3 | CSharp7.cs:261:41:261:44 | {...} |
| CSharp7.cs:263:18:263:26 | SSA def(s2) | CSharp7.cs:264:45:264:46 | access to local variable s2 |
| CSharp7.cs:263:18:263:26 | String s2 | CSharp7.cs:263:18:263:26 | SSA def(s2) |
| CSharp7.cs:264:37:264:43 | "string " | CSharp7.cs:264:35:264:48 | $"..." |
-| CSharp7.cs:264:45:264:46 | access to local variable s2 | CSharp7.cs:264:35:264:48 | $"..." |
+| CSharp7.cs:264:44:264:47 | {...} | CSharp7.cs:264:35:264:48 | $"..." |
+| CSharp7.cs:264:45:264:46 | access to local variable s2 | CSharp7.cs:264:44:264:47 | {...} |
| CSharp7.cs:282:13:282:16 | access to local variable dict | CSharp7.cs:282:13:282:48 | SSA def(dict) |
| CSharp7.cs:282:13:282:48 | SSA def(dict) | CSharp7.cs:283:20:283:23 | access to local variable dict |
| CSharp7.cs:282:20:282:48 | object creation of type Dictionary | CSharp7.cs:282:13:282:16 | access to local variable dict |
diff --git a/csharp/ql/test/library-tests/csharp7/PrintAst.expected b/csharp/ql/test/library-tests/csharp7/PrintAst.expected
index e5d009e0df63..bf0b07abbeb8 100644
--- a/csharp/ql/test/library-tests/csharp7/PrintAst.expected
+++ b/csharp/ql/test/library-tests/csharp7/PrintAst.expected
@@ -727,7 +727,8 @@ CSharp7.cs:
# 235| 0: [TypeMention] Console
# 235| 0: [InterpolatedStringExpr] $"..."
# 235| 0: [StringLiteralUtf16] "int "
-# 235| 1: [LocalVariableAccess] access to local variable i1
+# 235| 1: [InterpolatedStringInsertExpr] {...}
+# 235| 0: [LocalVariableAccess] access to local variable i1
# 237| 2: [IfStmt] if (...) ...
# 237| 0: [IsExpr] ... is ...
# 237| 0: [LocalVariableAccess] access to local variable o
@@ -740,7 +741,8 @@ CSharp7.cs:
# 239| 0: [TypeMention] Console
# 239| 0: [InterpolatedStringExpr] $"..."
# 239| 0: [StringLiteralUtf16] "string "
-# 239| 1: [LocalVariableAccess] access to local variable s1
+# 239| 1: [InterpolatedStringInsertExpr] {...}
+# 239| 0: [LocalVariableAccess] access to local variable s1
# 241| 2: [IfStmt] if (...) ...
# 241| 0: [IsExpr] ... is ...
# 241| 0: [LocalVariableAccess] access to local variable o
@@ -775,7 +777,8 @@ CSharp7.cs:
# 255| 0: [TypeMention] Console
# 255| 0: [InterpolatedStringExpr] $"..."
# 255| 0: [StringLiteralUtf16] "x "
-# 255| 1: [LocalVariableAccess] access to local variable s4
+# 255| 1: [InterpolatedStringInsertExpr] {...}
+# 255| 0: [LocalVariableAccess] access to local variable s4
# 256| 6: [BreakStmt] break;
# 257| 7: [CaseStmt] case ...:
# 257| 0: [VariablePatternExpr] Int32 i2
@@ -789,7 +792,8 @@ CSharp7.cs:
# 258| 0: [TypeMention] Console
# 258| 0: [InterpolatedStringExpr] $"..."
# 258| 0: [StringLiteralUtf16] "positive "
-# 258| 1: [LocalVariableAccess] access to local variable i2
+# 258| 1: [InterpolatedStringInsertExpr] {...}
+# 258| 0: [LocalVariableAccess] access to local variable i2
# 259| 9: [BreakStmt] break;
# 260| 10: [CaseStmt] case ...:
# 260| 0: [VariablePatternExpr] Int32 i3
@@ -800,7 +804,8 @@ CSharp7.cs:
# 261| 0: [TypeMention] Console
# 261| 0: [InterpolatedStringExpr] $"..."
# 261| 0: [StringLiteralUtf16] "int "
-# 261| 1: [LocalVariableAccess] access to local variable i3
+# 261| 1: [InterpolatedStringInsertExpr] {...}
+# 261| 0: [LocalVariableAccess] access to local variable i3
# 262| 12: [BreakStmt] break;
# 263| 13: [CaseStmt] case ...:
# 263| 0: [VariablePatternExpr] String s2
@@ -811,7 +816,8 @@ CSharp7.cs:
# 264| 0: [TypeMention] Console
# 264| 0: [InterpolatedStringExpr] $"..."
# 264| 0: [StringLiteralUtf16] "string "
-# 264| 1: [LocalVariableAccess] access to local variable s2
+# 264| 1: [InterpolatedStringInsertExpr] {...}
+# 264| 0: [LocalVariableAccess] access to local variable s2
# 265| 15: [BreakStmt] break;
# 266| 16: [CaseStmt] case ...:
# 266| 0: [TypeAccessPatternExpr] access to type Double
diff --git a/csharp/ql/test/library-tests/csharp8/PrintAst.expected b/csharp/ql/test/library-tests/csharp8/PrintAst.expected
index c33374e4761d..4ec30c915b3a 100644
--- a/csharp/ql/test/library-tests/csharp8/PrintAst.expected
+++ b/csharp/ql/test/library-tests/csharp8/PrintAst.expected
@@ -4,12 +4,14 @@ AlternateInterpolatedStrings.cs:
# 5| -1: [TypeMention] string
# 5| 1: [InterpolatedStringExpr] $"..."
# 5| 0: [StringLiteralUtf16] "C:"
-# 5| 1: [IntLiteral] 12
+# 5| 1: [InterpolatedStringInsertExpr] {...}
+# 5| 0: [IntLiteral] 12
# 6| 6: [Field] s2
# 6| -1: [TypeMention] string
# 6| 1: [InterpolatedStringExpr] $"..."
# 6| 0: [StringLiteralUtf16] "C:"
-# 6| 1: [IntLiteral] 12
+# 6| 1: [InterpolatedStringInsertExpr] {...}
+# 6| 0: [IntLiteral] 12
AsyncStreams.cs:
# 6| [Class] AsyncStreams
# 8| 5: [Method] Items
diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected
index a1ecbd0a2123..e3b89de20096 100644
--- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected
+++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected
@@ -1008,8 +1008,9 @@ Record.cs:
# 49| 0: [LocalVariableAccess] access to local variable s
# 50| 2: [ReturnStmt] return ...;
# 50| 0: [InterpolatedStringExpr] $"..."
-# 50| 0: [MethodCall] call to method ToString
-# 50| -1: [LocalVariableAccess] access to local variable s
+# 50| 0: [InterpolatedStringInsertExpr] {...}
+# 50| 0: [MethodCall] call to method ToString
+# 50| -1: [LocalVariableAccess] access to local variable s
# 50| 1: [StringLiteralUtf16] " is a dog"
# 54| [RecordClass] R1
# 54| 12: [NEOperator] !=
diff --git a/csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.expected b/csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.expected
index bf2a515a8895..cd7658f6f5e9 100644
--- a/csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.expected
+++ b/csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.expected
@@ -68,8 +68,9 @@ implicitToString.cs:
# 32| 0: [LocalVariableAccess] access to local variable x2
# 32| 1: [InterpolatedStringExpr] $"..."
# 32| 0: [StringLiteralUtf16] "Hello "
-# 32| 1: [MethodCall] call to method ToString
-# 32| -1: [LocalVariableAccess] access to local variable x1
+# 32| 1: [InterpolatedStringInsertExpr] {...}
+# 32| 0: [MethodCall] call to method ToString
+# 32| -1: [LocalVariableAccess] access to local variable x1
# 33| 2: [ExprStmt] ...;
# 33| 0: [MethodCall] call to method Sink
# 33| 0: [LocalVariableAccess] access to local variable x2
@@ -88,8 +89,9 @@ implicitToString.cs:
# 39| 0: [LocalVariableAccess] access to local variable x2
# 39| 1: [InterpolatedStringExpr] $"..."
# 39| 0: [StringLiteralUtf16] "Hello "
-# 39| 1: [MethodCall] call to method ToString
-# 39| -1: [LocalVariableAccess] access to local variable x1
+# 39| 1: [InterpolatedStringInsertExpr] {...}
+# 39| 0: [MethodCall] call to method ToString
+# 39| -1: [LocalVariableAccess] access to local variable x1
# 40| 2: [ExprStmt] ...;
# 40| 0: [MethodCall] call to method Sink
# 40| 0: [LocalVariableAccess] access to local variable x2
diff --git a/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected b/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected
index ea0ae7f9da73..7187280f7555 100644
--- a/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected
+++ b/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected
@@ -547,12 +547,14 @@
| LocalDataFlow.cs:273:13:273:36 | SSA def(sink69) | LocalDataFlow.cs:274:15:274:20 | access to local variable sink69 |
| LocalDataFlow.cs:273:22:273:36 | $"..." | LocalDataFlow.cs:273:13:273:18 | access to local variable sink69 |
| LocalDataFlow.cs:273:24:273:28 | "test " | LocalDataFlow.cs:273:22:273:36 | $"..." |
-| LocalDataFlow.cs:273:30:273:34 | access to local variable sink1 | LocalDataFlow.cs:273:22:273:36 | $"..." |
+| LocalDataFlow.cs:273:29:273:35 | {...} | LocalDataFlow.cs:273:22:273:36 | $"..." |
+| LocalDataFlow.cs:273:30:273:34 | access to local variable sink1 | LocalDataFlow.cs:273:29:273:35 | {...} |
| LocalDataFlow.cs:277:9:277:16 | access to local variable nonSink0 | LocalDataFlow.cs:277:9:277:37 | SSA def(nonSink0) |
| LocalDataFlow.cs:277:9:277:37 | SSA def(nonSink0) | LocalDataFlow.cs:278:15:278:22 | access to local variable nonSink0 |
| LocalDataFlow.cs:277:20:277:37 | $"..." | LocalDataFlow.cs:277:9:277:16 | access to local variable nonSink0 |
| LocalDataFlow.cs:277:22:277:26 | "test " | LocalDataFlow.cs:277:20:277:37 | $"..." |
-| LocalDataFlow.cs:277:28:277:35 | access to local variable nonSink0 | LocalDataFlow.cs:277:20:277:37 | $"..." |
+| LocalDataFlow.cs:277:27:277:36 | {...} | LocalDataFlow.cs:277:20:277:37 | $"..." |
+| LocalDataFlow.cs:277:28:277:35 | access to local variable nonSink0 | LocalDataFlow.cs:277:27:277:36 | {...} |
| LocalDataFlow.cs:278:15:278:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:285:31:285:38 | access to local variable nonSink0 |
| LocalDataFlow.cs:278:15:278:22 | access to local variable nonSink0 | LocalDataFlow.cs:285:31:285:38 | access to local variable nonSink0 |
| LocalDataFlow.cs:281:13:281:18 | access to local variable sink70 | LocalDataFlow.cs:281:13:281:34 | SSA def(sink70) |
@@ -1237,8 +1239,10 @@
| Splitting.cs:56:13:56:19 | [b (line 46): true] $"..." | Splitting.cs:56:9:56:9 | access to local variable x |
| Splitting.cs:56:15:56:15 | [b (line 46): false] "c" | Splitting.cs:56:13:56:19 | [b (line 46): false] $"..." |
| Splitting.cs:56:15:56:15 | [b (line 46): true] "c" | Splitting.cs:56:13:56:19 | [b (line 46): true] $"..." |
-| Splitting.cs:56:17:56:17 | [b (line 46): false] access to local variable x | Splitting.cs:56:13:56:19 | [b (line 46): false] $"..." |
-| Splitting.cs:56:17:56:17 | [b (line 46): true] access to local variable x | Splitting.cs:56:13:56:19 | [b (line 46): true] $"..." |
+| Splitting.cs:56:16:56:18 | [b (line 46): false] {...} | Splitting.cs:56:13:56:19 | [b (line 46): false] $"..." |
+| Splitting.cs:56:16:56:18 | [b (line 46): true] {...} | Splitting.cs:56:13:56:19 | [b (line 46): true] $"..." |
+| Splitting.cs:56:17:56:17 | [b (line 46): false] access to local variable x | Splitting.cs:56:16:56:18 | [b (line 46): false] {...} |
+| Splitting.cs:56:17:56:17 | [b (line 46): true] access to local variable x | Splitting.cs:56:16:56:18 | [b (line 46): true] {...} |
| Splitting.cs:57:13:57:24 | [b (line 46): false] access to field Item1 | Splitting.cs:57:9:57:9 | access to local variable x |
| Splitting.cs:57:13:57:24 | [b (line 46): true] access to field Item1 | Splitting.cs:57:9:57:9 | access to local variable x |
| Splitting.cs:57:17:57:17 | [b (line 46): false] access to local variable y | Splitting.cs:58:27:58:27 | [b (line 46): false] access to local variable y |
From acec97db94fe79f3928f5d58b62045436be58f88 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Fri, 21 Mar 2025 13:32:44 +0100
Subject: [PATCH 028/409] C#: Add change-note.
---
csharp/ql/lib/change-notes/2025-03-21-string-interpolation.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 csharp/ql/lib/change-notes/2025-03-21-string-interpolation.md
diff --git a/csharp/ql/lib/change-notes/2025-03-21-string-interpolation.md b/csharp/ql/lib/change-notes/2025-03-21-string-interpolation.md
new file mode 100644
index 000000000000..3507d35b5135
--- /dev/null
+++ b/csharp/ql/lib/change-notes/2025-03-21-string-interpolation.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* The *alignment* and *format* clauses in string interpolation expressions are now extracted. That is, in `$"Hello {name,align:format}"` *name*, *align* and *format* are extracted as children of the string interpolation *insert* `{name,align:format}`.
From d1ef2b50fbedf90d1c3a1c8c0a157f0eb97fe002 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 12 Feb 2025 15:46:16 +0000
Subject: [PATCH 029/409] Rust: Model futures::executor::block_on.
---
rust/ql/lib/codeql/rust/frameworks/futures.model.yml | 6 ++++++
.../dataflow/global/inline-flow.expected | 12 ++++++++++++
rust/ql/test/library-tests/dataflow/global/main.rs | 2 +-
.../dataflow/global/viableCallable.expected | 2 ++
.../dataflow/local/DataFlowStep.expected | 1 +
.../security/CWE-020/RegexInjection.expected | 8 ++++----
6 files changed, 26 insertions(+), 5 deletions(-)
create mode 100644 rust/ql/lib/codeql/rust/frameworks/futures.model.yml
diff --git a/rust/ql/lib/codeql/rust/frameworks/futures.model.yml b/rust/ql/lib/codeql/rust/frameworks/futures.model.yml
new file mode 100644
index 000000000000..1361ff9aeb2e
--- /dev/null
+++ b/rust/ql/lib/codeql/rust/frameworks/futures.model.yml
@@ -0,0 +1,6 @@
+extensions:
+ - addsTo:
+ pack: codeql/rust-all
+ extensible: summaryModel
+ data:
+ - ["repo:https://github.com/rust-lang/futures-rs:futures-executor", "crate::local_pool::block_on", "Argument[0]", "ReturnValue", "value", "manual"]
diff --git a/rust/ql/test/library-tests/dataflow/global/inline-flow.expected b/rust/ql/test/library-tests/dataflow/global/inline-flow.expected
index 54b70e0ac128..4a095c7142f5 100644
--- a/rust/ql/test/library-tests/dataflow/global/inline-flow.expected
+++ b/rust/ql/test/library-tests/dataflow/global/inline-flow.expected
@@ -1,4 +1,5 @@
models
+| 1 | Summary: repo:https://github.com/rust-lang/futures-rs:futures-executor; crate::local_pool::block_on; Argument[0]; ReturnValue; value |
edges
| main.rs:12:28:14:1 | { ... } | main.rs:17:13:17:23 | get_data(...) | provenance | |
| main.rs:13:5:13:13 | source(...) | main.rs:12:28:14:1 | { ... } | provenance | |
@@ -71,10 +72,15 @@ edges
| main.rs:161:9:161:9 | d [MyInt] | main.rs:162:10:162:10 | d [MyInt] | provenance | |
| main.rs:161:13:161:20 | a.add(...) [MyInt] | main.rs:161:9:161:9 | d [MyInt] | provenance | |
| main.rs:162:10:162:10 | d [MyInt] | main.rs:162:10:162:16 | d.value | provenance | |
+| main.rs:200:32:204:1 | { ... } | main.rs:219:41:219:54 | async_source(...) | provenance | |
+| main.rs:201:9:201:9 | a | main.rs:200:32:204:1 | { ... } | provenance | |
| main.rs:201:9:201:9 | a | main.rs:202:10:202:10 | a | provenance | |
| main.rs:201:13:201:21 | source(...) | main.rs:201:9:201:9 | a | provenance | |
| main.rs:211:13:211:13 | c | main.rs:212:14:212:14 | c | provenance | |
| main.rs:211:17:211:25 | source(...) | main.rs:211:13:211:13 | c | provenance | |
+| main.rs:219:9:219:9 | a | main.rs:220:10:220:10 | a | provenance | |
+| main.rs:219:13:219:55 | ...::block_on(...) | main.rs:219:9:219:9 | a | provenance | |
+| main.rs:219:41:219:54 | async_source(...) | main.rs:219:13:219:55 | ...::block_on(...) | provenance | MaD:1 |
nodes
| main.rs:12:28:14:1 | { ... } | semmle.label | { ... } |
| main.rs:13:5:13:13 | source(...) | semmle.label | source(...) |
@@ -156,12 +162,17 @@ nodes
| main.rs:161:13:161:20 | a.add(...) [MyInt] | semmle.label | a.add(...) [MyInt] |
| main.rs:162:10:162:10 | d [MyInt] | semmle.label | d [MyInt] |
| main.rs:162:10:162:16 | d.value | semmle.label | d.value |
+| main.rs:200:32:204:1 | { ... } | semmle.label | { ... } |
| main.rs:201:9:201:9 | a | semmle.label | a |
| main.rs:201:13:201:21 | source(...) | semmle.label | source(...) |
| main.rs:202:10:202:10 | a | semmle.label | a |
| main.rs:211:13:211:13 | c | semmle.label | c |
| main.rs:211:17:211:25 | source(...) | semmle.label | source(...) |
| main.rs:212:14:212:14 | c | semmle.label | c |
+| main.rs:219:9:219:9 | a | semmle.label | a |
+| main.rs:219:13:219:55 | ...::block_on(...) | semmle.label | ...::block_on(...) |
+| main.rs:219:41:219:54 | async_source(...) | semmle.label | async_source(...) |
+| main.rs:220:10:220:10 | a | semmle.label | a |
subpaths
| main.rs:36:26:36:26 | a | main.rs:30:17:30:22 | ...: i64 | main.rs:30:32:32:1 | { ... } | main.rs:36:13:36:27 | pass_through(...) |
| main.rs:41:26:44:5 | { ... } | main.rs:30:17:30:22 | ...: i64 | main.rs:30:32:32:1 | { ... } | main.rs:41:13:44:6 | pass_through(...) |
@@ -186,3 +197,4 @@ testFailures
| main.rs:162:10:162:16 | d.value | main.rs:159:28:159:36 | source(...) | main.rs:162:10:162:16 | d.value | $@ | main.rs:159:28:159:36 | source(...) | source(...) |
| main.rs:202:10:202:10 | a | main.rs:201:13:201:21 | source(...) | main.rs:202:10:202:10 | a | $@ | main.rs:201:13:201:21 | source(...) | source(...) |
| main.rs:212:14:212:14 | c | main.rs:211:17:211:25 | source(...) | main.rs:212:14:212:14 | c | $@ | main.rs:211:17:211:25 | source(...) | source(...) |
+| main.rs:220:10:220:10 | a | main.rs:201:13:201:21 | source(...) | main.rs:220:10:220:10 | a | $@ | main.rs:201:13:201:21 | source(...) | source(...) |
diff --git a/rust/ql/test/library-tests/dataflow/global/main.rs b/rust/ql/test/library-tests/dataflow/global/main.rs
index c1e3ee4e8387..15a48ba9b78e 100644
--- a/rust/ql/test/library-tests/dataflow/global/main.rs
+++ b/rust/ql/test/library-tests/dataflow/global/main.rs
@@ -217,7 +217,7 @@ async fn test_async_await_async_part() {
fn test_async_await() {
let a = futures::executor::block_on(async_source());
- sink(a); // $ MISSING: hasValueFlow=1
+ sink(a); // $ hasValueFlow=1
futures::executor::block_on(test_async_await_async_part());
}
diff --git a/rust/ql/test/library-tests/dataflow/global/viableCallable.expected b/rust/ql/test/library-tests/dataflow/global/viableCallable.expected
index 2bbff8e33c3f..aa3ae0af0219 100644
--- a/rust/ql/test/library-tests/dataflow/global/viableCallable.expected
+++ b/rust/ql/test/library-tests/dataflow/global/viableCallable.expected
@@ -50,8 +50,10 @@
| main.rs:211:17:211:25 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:212:9:212:15 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:215:5:215:17 | sink(...) | main.rs:5:1:7:1 | fn sink |
+| main.rs:219:13:219:55 | ...::block_on(...) | file://:0:0:0:0 | repo:https://github.com/rust-lang/futures-rs:futures-executor::_::crate::local_pool::block_on |
| main.rs:219:41:219:54 | async_source(...) | main.rs:200:1:204:1 | fn async_source |
| main.rs:220:5:220:11 | sink(...) | main.rs:5:1:7:1 | fn sink |
+| main.rs:222:5:222:62 | ...::block_on(...) | file://:0:0:0:0 | repo:https://github.com/rust-lang/futures-rs:futures-executor::_::crate::local_pool::block_on |
| main.rs:222:33:222:61 | test_async_await_async_part(...) | main.rs:206:1:216:1 | fn test_async_await_async_part |
| main.rs:226:5:226:22 | data_out_of_call(...) | main.rs:16:1:19:1 | fn data_out_of_call |
| main.rs:227:5:227:21 | data_in_to_call(...) | main.rs:25:1:28:1 | fn data_in_to_call |
diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected
index 23270af042a6..9c7be9664332 100644
--- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected
+++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected
@@ -1909,6 +1909,7 @@ models
| 1058 | Summary: lang:std; crate::thread::current::set_current; Argument[0]; ReturnValue.Field[crate::result::Result::Err(0)]; value |
| 1059 | Summary: lang:std; crate::thread::current::try_with_current; Argument[0].ReturnValue; ReturnValue; value |
| 1060 | Summary: lang:std; crate::thread::with_current_name; Argument[0].ReturnValue; ReturnValue; value |
+| 1061 | Summary: repo:https://github.com/rust-lang/futures-rs:futures-executor; crate::local_pool::block_on; Argument[0]; ReturnValue; value |
storeStep
| file://:0:0:0:0 | [summary] to write: Argument[0].Field[crate::option::Option::Some(0)] in lang:core::_::::zip_with | Some | file://:0:0:0:0 | [post] [summary param] 0 in lang:core::_::::zip_with |
| file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0].Reference in lang:alloc::_::::retain | &ref | file://:0:0:0:0 | [summary] to write: Argument[0].Parameter[0] in lang:alloc::_::::retain |
diff --git a/rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected b/rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected
index e204b5a39264..5fc4c55e0032 100644
--- a/rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected
+++ b/rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected
@@ -2,15 +2,15 @@
| main.rs:6:25:6:30 | ®ex | main.rs:4:20:4:32 | ...::var | main.rs:6:25:6:30 | ®ex | This regular expression is constructed from a $@. | main.rs:4:20:4:32 | ...::var | user-provided value |
edges
| main.rs:4:9:4:16 | username | main.rs:5:25:5:44 | MacroExpr | provenance | |
-| main.rs:4:20:4:32 | ...::var | main.rs:4:20:4:40 | ...::var(...) [Ok] | provenance | Src:MaD:62 |
-| main.rs:4:20:4:40 | ...::var(...) [Ok] | main.rs:4:20:4:66 | ... .unwrap_or(...) | provenance | MaD:1593 |
+| main.rs:4:20:4:32 | ...::var | main.rs:4:20:4:40 | ...::var(...) [Ok] | provenance | Src:MaD:63 |
+| main.rs:4:20:4:40 | ...::var(...) [Ok] | main.rs:4:20:4:66 | ... .unwrap_or(...) | provenance | MaD:1594 |
| main.rs:4:20:4:66 | ... .unwrap_or(...) | main.rs:4:9:4:16 | username | provenance | |
| main.rs:5:9:5:13 | regex | main.rs:6:26:6:30 | regex | provenance | |
| main.rs:5:17:5:45 | res | main.rs:5:25:5:44 | { ... } | provenance | |
| main.rs:5:25:5:44 | ...::format(...) | main.rs:5:17:5:45 | res | provenance | |
| main.rs:5:25:5:44 | ...::must_use(...) | main.rs:5:9:5:13 | regex | provenance | |
-| main.rs:5:25:5:44 | MacroExpr | main.rs:5:25:5:44 | ...::format(...) | provenance | MaD:66 |
-| main.rs:5:25:5:44 | { ... } | main.rs:5:25:5:44 | ...::must_use(...) | provenance | MaD:3016 |
+| main.rs:5:25:5:44 | MacroExpr | main.rs:5:25:5:44 | ...::format(...) | provenance | MaD:67 |
+| main.rs:5:25:5:44 | { ... } | main.rs:5:25:5:44 | ...::must_use(...) | provenance | MaD:3017 |
| main.rs:6:26:6:30 | regex | main.rs:6:25:6:30 | ®ex | provenance | |
nodes
| main.rs:4:9:4:16 | username | semmle.label | username |
From d9fb13790994686a480cdf824b53901bbdf4acd3 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Mon, 24 Mar 2025 11:56:00 +0100
Subject: [PATCH 030/409] C#: Add upgrade- and downgrade scripts.
---
.../expressions.ql | 13 +
.../old.dbscheme | 1460 +++++++++++++++++
.../semmlecode.csharp.dbscheme | 1459 ++++++++++++++++
.../upgrade.properties | 3 +
.../old.dbscheme | 1459 ++++++++++++++++
.../semmlecode.csharp.dbscheme | 1460 +++++++++++++++++
.../upgrade.properties | 2 +
7 files changed, 5856 insertions(+)
create mode 100644 csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/expressions.ql
create mode 100644 csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/old.dbscheme
create mode 100644 csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/semmlecode.csharp.dbscheme
create mode 100644 csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/upgrade.properties
create mode 100644 csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/old.dbscheme
create mode 100644 csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/semmlecode.csharp.dbscheme
create mode 100644 csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/upgrade.properties
diff --git a/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/expressions.ql b/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/expressions.ql
new file mode 100644
index 000000000000..4f516d1d5cba
--- /dev/null
+++ b/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/expressions.ql
@@ -0,0 +1,13 @@
+class Expression extends @expr {
+ string toString() { none() }
+}
+
+class TypeOrRef extends @type_or_ref {
+ string toString() { none() }
+}
+
+from Expression e, int k, int kind, TypeOrRef t
+where
+ expressions(e, k, t) and
+ if k = 138 then kind = 106 else kind = k
+select e, kind, t
diff --git a/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/old.dbscheme b/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/old.dbscheme
new file mode 100644
index 000000000000..66044cfa5bbf
--- /dev/null
+++ b/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/old.dbscheme
@@ -0,0 +1,1460 @@
+/* This is a dummy line to alter the dbscheme, so we can make a database upgrade
+ * without actually changing any of the dbscheme predicates. It contains a date
+ * to allow for such updates in the future as well.
+ *
+ * 2021-07-14
+ *
+ * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a
+ * previously seen state (matching a previously seen SHA), which would make the upgrade
+ * mechanism not work properly.
+ */
+
+/**
+ * An invocation of the compiler. Note that more than one file may be
+ * compiled per invocation. For example, this command compiles three
+ * source files:
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * The `id` simply identifies the invocation, while `cwd` is the working
+ * directory from which the compiler was invoked.
+ */
+compilations(
+ unique int id : @compilation,
+ string cwd : string ref
+);
+
+compilation_info(
+ int id : @compilation ref,
+ string info_key: string ref,
+ string info_value: string ref
+)
+
+/**
+ * The arguments that were passed to the extractor for a compiler
+ * invocation. If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then typically there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | --compiler
+ * 1 | *path to compiler*
+ * 2 | f1.cs
+ * 3 | f2.cs
+ * 4 | f3.cs
+ */
+#keyset[id, num]
+compilation_args(
+ int id : @compilation ref,
+ int num : int ref,
+ string arg : string ref
+);
+
+/**
+ * The expanded arguments that were passed to the extractor for a
+ * compiler invocation. This is similar to `compilation_args`, but
+ * for a `@someFile.rsp` argument, it includes the arguments from that
+ * file, rather than just taking the argument literally.
+ */
+#keyset[id, num]
+compilation_expanded_args(
+ int id : @compilation ref,
+ int num : int ref,
+ string arg : string ref
+);
+
+/**
+ * The source files that are compiled by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | f1.cs
+ * 1 | f2.cs
+ * 2 | f3.cs
+ */
+#keyset[id, num]
+compilation_compiling_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The references used by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | ref1.dll
+ * 1 | ref2.dll
+ * 2 | ref3.dll
+ */
+#keyset[id, num]
+compilation_referencing_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The time taken by the extractor for a compiler invocation.
+ *
+ * For each file `num`, there will be rows for
+ *
+ * kind | seconds
+ * ---- | ---
+ * 1 | CPU seconds used by the extractor frontend
+ * 2 | Elapsed seconds during the extractor frontend
+ * 3 | CPU seconds used by the extractor backend
+ * 4 | Elapsed seconds during the extractor backend
+ */
+#keyset[id, num, kind]
+compilation_time(
+ int id : @compilation ref,
+ int num : int ref,
+ /* kind:
+ 1 = frontend_cpu_seconds
+ 2 = frontend_elapsed_seconds
+ 3 = extractor_cpu_seconds
+ 4 = extractor_elapsed_seconds
+ */
+ int kind : int ref,
+ float seconds : float ref
+);
+
+/**
+ * An error or warning generated by the extractor.
+ * The diagnostic message `diagnostic` was generated during compiler
+ * invocation `compilation`, and is the `file_number_diagnostic_number`th
+ * message generated while extracting the `file_number`th file of that
+ * invocation.
+ */
+#keyset[compilation, file_number, file_number_diagnostic_number]
+diagnostic_for(
+ unique int diagnostic : @diagnostic ref,
+ int compilation : @compilation ref,
+ int file_number : int ref,
+ int file_number_diagnostic_number : int ref
+);
+
+diagnostics(
+ unique int id: @diagnostic,
+ int severity: int ref,
+ string error_tag: string ref,
+ string error_message: string ref,
+ string full_error_message: string ref,
+ int location: @location ref
+);
+
+extractor_messages(
+ unique int id: @extractor_message,
+ int severity: int ref,
+ string origin : string ref,
+ string text : string ref,
+ string entity : string ref,
+ int location: @location ref,
+ string stack_trace : string ref
+);
+
+/**
+ * If extraction was successful, then `cpu_seconds` and
+ * `elapsed_seconds` are the CPU time and elapsed time (respectively)
+ * that extraction took for compiler invocation `id`.
+ */
+compilation_finished(
+ unique int id : @compilation ref,
+ float cpu_seconds : float ref,
+ float elapsed_seconds : float ref
+);
+
+compilation_assembly(
+ unique int id : @compilation ref,
+ int assembly: @assembly ref
+)
+
+// Populated by the CSV extractor
+externalData(
+ int id: @externalDataElement,
+ string path: string ref,
+ int column: int ref,
+ string value: string ref);
+
+sourceLocationPrefix(
+ string prefix: string ref);
+
+/*
+ * C# dbscheme
+ */
+
+/** ELEMENTS **/
+
+@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration
+ | @using_directive | @type_parameter_constraints | @externalDataElement
+ | @xmllocatable | @asp_element | @namespace | @preprocessor_directive;
+
+@declaration = @callable | @generic | @assignable | @namespace;
+
+@named_element = @namespace | @declaration;
+
+@declaration_with_accessors = @property | @indexer | @event;
+
+@assignable = @variable | @assignable_with_accessors | @event;
+
+@assignable_with_accessors = @property | @indexer;
+
+@attributable = @assembly | @field | @parameter | @operator | @method | @constructor
+ | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors
+ | @local_function | @lambda_expr;
+
+/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/
+
+@location = @location_default | @assembly;
+
+locations_default(
+ unique int id: @location_default,
+ int file: @file ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+locations_mapped(
+ unique int id: @location_default ref,
+ int mapped_to: @location_default ref);
+
+@sourceline = @file | @callable | @xmllocatable;
+
+numlines(
+ int element_id: @sourceline ref,
+ int num_lines: int ref,
+ int num_code: int ref,
+ int num_comment: int ref);
+
+assemblies(
+ unique int id: @assembly,
+ int file: @file ref,
+ string fullname: string ref,
+ string name: string ref,
+ string version: string ref);
+
+files(
+ unique int id: @file,
+ string name: string ref);
+
+folders(
+ unique int id: @folder,
+ string name: string ref);
+
+@container = @folder | @file ;
+
+containerparent(
+ int parent: @container ref,
+ unique int child: @container ref);
+
+file_extraction_mode(
+ unique int file: @file ref,
+ int mode: int ref
+ /* 0 = normal, 1 = standalone extractor */
+ );
+
+/** NAMESPACES **/
+
+@type_container = @namespace | @type;
+
+namespaces(
+ unique int id: @namespace,
+ string name: string ref);
+
+namespace_declarations(
+ unique int id: @namespace_declaration,
+ int namespace_id: @namespace ref);
+
+namespace_declaration_location(
+ unique int id: @namespace_declaration ref,
+ int loc: @location ref);
+
+parent_namespace(
+ unique int child_id: @type_container ref,
+ int namespace_id: @namespace ref);
+
+@declaration_or_directive = @namespace_declaration | @type | @using_directive;
+
+parent_namespace_declaration(
+ int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes
+ int namespace_id: @namespace_declaration ref);
+
+@using_directive = @using_namespace_directive | @using_static_directive;
+
+using_global(
+ unique int id: @using_directive ref
+);
+
+using_namespace_directives(
+ unique int id: @using_namespace_directive,
+ int namespace_id: @namespace ref);
+
+using_static_directives(
+ unique int id: @using_static_directive,
+ int type_id: @type_or_ref ref);
+
+using_directive_location(
+ unique int id: @using_directive ref,
+ int loc: @location ref);
+
+@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning
+ | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if
+ | @directive_elif | @directive_else | @directive_endif;
+
+@conditional_directive = @directive_if | @directive_elif;
+@branch_directive = @directive_if | @directive_elif | @directive_else;
+
+directive_ifs(
+ unique int id: @directive_if,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref); /* 0: false, 1: true */
+
+directive_elifs(
+ unique int id: @directive_elif,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+directive_elses(
+ unique int id: @directive_else,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+#keyset[id, start]
+directive_endifs(
+ unique int id: @directive_endif,
+ unique int start: @directive_if ref);
+
+directive_define_symbols(
+ unique int id: @define_symbol_expr ref,
+ string name: string ref);
+
+directive_regions(
+ unique int id: @directive_region,
+ string name: string ref);
+
+#keyset[id, start]
+directive_endregions(
+ unique int id: @directive_endregion,
+ unique int start: @directive_region ref);
+
+directive_lines(
+ unique int id: @directive_line,
+ int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */
+
+directive_line_value(
+ unique int id: @directive_line ref,
+ int line: int ref);
+
+directive_line_file(
+ unique int id: @directive_line ref,
+ int file: @file ref);
+
+directive_line_offset(
+ unique int id: @directive_line ref,
+ int offset: int ref);
+
+directive_line_span(
+ unique int id: @directive_line ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+directive_nullables(
+ unique int id: @directive_nullable,
+ int setting: int ref, /* 0: disable, 1: enable, 2: restore */
+ int target: int ref); /* 0: none, 1: annotations, 2: warnings */
+
+directive_warnings(
+ unique int id: @directive_warning,
+ string message: string ref);
+
+directive_errors(
+ unique int id: @directive_error,
+ string message: string ref);
+
+directive_undefines(
+ unique int id: @directive_undefine,
+ string name: string ref);
+
+directive_defines(
+ unique int id: @directive_define,
+ string name: string ref);
+
+pragma_checksums(
+ unique int id: @pragma_checksum,
+ int file: @file ref,
+ string guid: string ref,
+ string bytes: string ref);
+
+pragma_warnings(
+ unique int id: @pragma_warning,
+ int kind: int ref /* 0 = disable, 1 = restore */);
+
+#keyset[id, index]
+pragma_warning_error_codes(
+ int id: @pragma_warning ref,
+ string errorCode: string ref,
+ int index: int ref);
+
+preprocessor_directive_location(
+ unique int id: @preprocessor_directive ref,
+ int loc: @location ref);
+
+preprocessor_directive_compilation(
+ int id: @preprocessor_directive ref,
+ int compilation: @compilation ref);
+
+preprocessor_directive_active(
+ unique int id: @preprocessor_directive ref,
+ int active: int ref); /* 0: false, 1: true */
+
+/** TYPES **/
+
+types(
+ unique int id: @type,
+ int kind: int ref,
+ string name: string ref);
+
+case @type.kind of
+ 1 = @bool_type
+| 2 = @char_type
+| 3 = @decimal_type
+| 4 = @sbyte_type
+| 5 = @short_type
+| 6 = @int_type
+| 7 = @long_type
+| 8 = @byte_type
+| 9 = @ushort_type
+| 10 = @uint_type
+| 11 = @ulong_type
+| 12 = @float_type
+| 13 = @double_type
+| 14 = @enum_type
+| 15 = @struct_type
+| 17 = @class_type
+| 19 = @interface_type
+| 20 = @delegate_type
+| 21 = @null_type
+| 22 = @type_parameter
+| 23 = @pointer_type
+| 24 = @nullable_type
+| 25 = @array_type
+| 26 = @void_type
+| 27 = @int_ptr_type
+| 28 = @uint_ptr_type
+| 29 = @dynamic_type
+| 30 = @arglist_type
+| 31 = @unknown_type
+| 32 = @tuple_type
+| 33 = @function_pointer_type
+| 34 = @inline_array_type
+ ;
+
+@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type;
+@integral_type = @signed_integral_type | @unsigned_integral_type;
+@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type;
+@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type;
+@floating_point_type = @float_type | @double_type;
+@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type
+ | @uint_ptr_type | @tuple_type | @void_type | @inline_array_type;
+@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type
+ | @dynamic_type;
+@value_or_ref_type = @value_type | @ref_type;
+
+typerefs(
+ unique int id: @typeref,
+ string name: string ref);
+
+typeref_type(
+ int id: @typeref ref,
+ unique int typeId: @type ref);
+
+@type_or_ref = @type | @typeref;
+
+array_element_type(
+ unique int array: @array_type ref,
+ int dimension: int ref,
+ int rank: int ref,
+ int element: @type_or_ref ref);
+
+nullable_underlying_type(
+ unique int nullable: @nullable_type ref,
+ int underlying: @type_or_ref ref);
+
+pointer_referent_type(
+ unique int pointer: @pointer_type ref,
+ int referent: @type_or_ref ref);
+
+enum_underlying_type(
+ unique int enum_id: @enum_type ref,
+ int underlying_type_id: @type_or_ref ref);
+
+delegate_return_type(
+ unique int delegate_id: @delegate_type ref,
+ int return_type_id: @type_or_ref ref);
+
+function_pointer_return_type(
+ unique int function_pointer_id: @function_pointer_type ref,
+ int return_type_id: @type_or_ref ref);
+
+extend(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+anonymous_types(
+ unique int id: @type ref);
+
+@interface_or_ref = @interface_type | @typeref;
+
+implement(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+type_location(
+ int id: @type ref,
+ int loc: @location ref);
+
+tuple_underlying_type(
+ unique int tuple: @tuple_type ref,
+ int struct: @type_or_ref ref);
+
+#keyset[tuple, index]
+tuple_element(
+ int tuple: @tuple_type ref,
+ int index: int ref,
+ unique int field: @field ref);
+
+attributes(
+ unique int id: @attribute,
+ int kind: int ref,
+ int type_id: @type_or_ref ref,
+ int target: @attributable ref);
+
+case @attribute.kind of
+ 0 = @attribute_default
+| 1 = @attribute_return
+| 2 = @attribute_assembly
+| 3 = @attribute_module
+;
+
+attribute_location(
+ int id: @attribute ref,
+ int loc: @location ref);
+
+@type_mention_parent = @element | @type_mention;
+
+type_mention(
+ unique int id: @type_mention,
+ int type_id: @type_or_ref ref,
+ int parent: @type_mention_parent ref);
+
+type_mention_location(
+ unique int id: @type_mention ref,
+ int loc: @location ref);
+
+@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type;
+
+/**
+ * A direct annotation on an entity, for example `string? x;`.
+ *
+ * Annotations:
+ * 2 = reftype is not annotated "!"
+ * 3 = reftype is annotated "?"
+ * 4 = readonly ref type / in parameter
+ * 5 = ref type parameter, return or local variable
+ * 6 = out parameter
+ *
+ * Note that the annotation depends on the element it annotates.
+ * @assignable: The annotation is on the type of the assignable, for example the variable type.
+ * @type_parameter: The annotation is on the reftype constraint
+ * @callable: The annotation is on the return type
+ * @array_type: The annotation is on the element type
+ */
+type_annotation(int id: @has_type_annotation ref, int annotation: int ref);
+
+nullability(unique int nullability: @nullability, int kind: int ref);
+
+case @nullability.kind of
+ 0 = @oblivious
+| 1 = @not_annotated
+| 2 = @annotated
+;
+
+#keyset[parent, index]
+nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref)
+
+type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref);
+
+/**
+ * The nullable flow state of an expression, as determined by Roslyn.
+ * 0 = none (default, not populated)
+ * 1 = not null
+ * 2 = maybe null
+ */
+expr_flowstate(unique int id: @expr ref, int state: int ref);
+
+/** GENERICS **/
+
+@generic = @type | @method | @local_function;
+
+type_parameters(
+ unique int id: @type_parameter ref,
+ int index: int ref,
+ int generic_id: @generic ref,
+ int variance: int ref /* none = 0, out = 1, in = 2 */);
+
+#keyset[constructed_id, index]
+type_arguments(
+ int id: @type_or_ref ref,
+ int index: int ref,
+ int constructed_id: @generic_or_ref ref);
+
+@generic_or_ref = @generic | @typeref;
+
+constructed_generic(
+ unique int constructed: @generic ref,
+ int generic: @generic_or_ref ref);
+
+type_parameter_constraints(
+ unique int id: @type_parameter_constraints,
+ int param_id: @type_parameter ref);
+
+type_parameter_constraints_location(
+ int id: @type_parameter_constraints ref,
+ int loc: @location ref);
+
+general_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int kind: int ref /* class = 1, struct = 2, new = 3 */);
+
+specific_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref);
+
+specific_type_parameter_nullability(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref,
+ int nullability: @nullability ref);
+
+/** FUNCTION POINTERS */
+
+function_pointer_calling_conventions(
+ int id: @function_pointer_type ref,
+ int kind: int ref);
+
+#keyset[id, index]
+has_unmanaged_calling_conventions(
+ int id: @function_pointer_type ref,
+ int index: int ref,
+ int conv_id: @type_or_ref ref);
+
+/** MODIFIERS */
+
+@modifiable = @modifiable_direct | @event_accessor;
+
+@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr;
+
+modifiers(
+ unique int id: @modifier,
+ string name: string ref);
+
+has_modifiers(
+ int id: @modifiable_direct ref,
+ int mod_id: @modifier ref);
+
+/** MEMBERS **/
+
+@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type;
+
+@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr;
+
+@virtualizable = @method | @property | @indexer | @event | @operator;
+
+exprorstmt_name(
+ unique int parent_id: @named_exprorstmt ref,
+ string name: string ref);
+
+nested_types(
+ unique int id: @type ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @type ref);
+
+properties(
+ unique int id: @property,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @property ref);
+
+property_location(
+ int id: @property ref,
+ int loc: @location ref);
+
+indexers(
+ unique int id: @indexer,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @indexer ref);
+
+indexer_location(
+ int id: @indexer ref,
+ int loc: @location ref);
+
+accessors(
+ unique int id: @accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_member_id: @member ref,
+ int unbound_id: @accessor ref);
+
+case @accessor.kind of
+ 1 = @getter
+| 2 = @setter
+ ;
+
+init_only_accessors(
+ unique int id: @accessor ref);
+
+accessor_location(
+ int id: @accessor ref,
+ int loc: @location ref);
+
+events(
+ unique int id: @event,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @event ref);
+
+event_location(
+ int id: @event ref,
+ int loc: @location ref);
+
+event_accessors(
+ unique int id: @event_accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_event_id: @event ref,
+ int unbound_id: @event_accessor ref);
+
+case @event_accessor.kind of
+ 1 = @add_event_accessor
+| 2 = @remove_event_accessor
+ ;
+
+event_accessor_location(
+ int id: @event_accessor ref,
+ int loc: @location ref);
+
+operators(
+ unique int id: @operator,
+ string name: string ref,
+ string symbol: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @operator ref);
+
+operator_location(
+ int id: @operator ref,
+ int loc: @location ref);
+
+constant_value(
+ int id: @variable ref,
+ string value: string ref);
+
+/** CALLABLES **/
+
+@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function;
+
+@callable_accessor = @accessor | @event_accessor;
+
+methods(
+ unique int id: @method,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @method ref);
+
+method_location(
+ int id: @method ref,
+ int loc: @location ref);
+
+constructors(
+ unique int id: @constructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @constructor ref);
+
+constructor_location(
+ int id: @constructor ref,
+ int loc: @location ref);
+
+destructors(
+ unique int id: @destructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @destructor ref);
+
+destructor_location(
+ int id: @destructor ref,
+ int loc: @location ref);
+
+overrides(
+ int id: @callable ref,
+ int base_id: @callable ref);
+
+explicitly_implements(
+ int id: @member ref,
+ int interface_id: @interface_or_ref ref);
+
+local_functions(
+ unique int id: @local_function,
+ string name: string ref,
+ int return_type: @type ref,
+ int unbound_id: @local_function ref);
+
+local_function_stmts(
+ unique int fn: @local_function_stmt ref,
+ int stmt: @local_function ref);
+
+/** VARIABLES **/
+
+@variable = @local_scope_variable | @field;
+
+@local_scope_variable = @local_variable | @parameter;
+
+fields(
+ unique int id: @field,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @field ref);
+
+case @field.kind of
+ 1 = @addressable_field
+| 2 = @constant
+ ;
+
+field_location(
+ int id: @field ref,
+ int loc: @location ref);
+
+localvars(
+ unique int id: @local_variable,
+ int kind: int ref,
+ string name: string ref,
+ int implicitly_typed: int ref /* 0 = no, 1 = yes */,
+ int type_id: @type_or_ref ref,
+ int parent_id: @local_var_decl_expr ref);
+
+case @local_variable.kind of
+ 1 = @addressable_local_variable
+| 2 = @local_constant
+| 3 = @local_variable_ref
+ ;
+
+localvar_location(
+ unique int id: @local_variable ref,
+ int loc: @location ref);
+
+@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type;
+
+#keyset[name, parent_id]
+#keyset[index, parent_id]
+params(
+ unique int id: @parameter,
+ string name: string ref,
+ int type_id: @type_or_ref ref,
+ int index: int ref,
+ int mode: int ref, /* value = 0, ref = 1, out = 2, params/array = 3, this = 4, in = 5, ref readonly = 6 */
+ int parent_id: @parameterizable ref,
+ int unbound_id: @parameter ref);
+
+param_location(
+ int id: @parameter ref,
+ int loc: @location ref);
+
+@has_scoped_annotation = @local_scope_variable
+
+scoped_annotation(
+ int id: @has_scoped_annotation ref,
+ int kind: int ref // scoped ref = 1, scoped value = 2
+ );
+
+/** STATEMENTS **/
+
+@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent;
+
+statements(
+ unique int id: @stmt,
+ int kind: int ref);
+
+#keyset[index, parent]
+stmt_parent(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_stmt_parent = @callable;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+stmt_parent_top_level(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @top_level_stmt_parent ref);
+
+case @stmt.kind of
+ 1 = @block_stmt
+| 2 = @expr_stmt
+| 3 = @if_stmt
+| 4 = @switch_stmt
+| 5 = @while_stmt
+| 6 = @do_stmt
+| 7 = @for_stmt
+| 8 = @foreach_stmt
+| 9 = @break_stmt
+| 10 = @continue_stmt
+| 11 = @goto_stmt
+| 12 = @goto_case_stmt
+| 13 = @goto_default_stmt
+| 14 = @throw_stmt
+| 15 = @return_stmt
+| 16 = @yield_stmt
+| 17 = @try_stmt
+| 18 = @checked_stmt
+| 19 = @unchecked_stmt
+| 20 = @lock_stmt
+| 21 = @using_block_stmt
+| 22 = @var_decl_stmt
+| 23 = @const_decl_stmt
+| 24 = @empty_stmt
+| 25 = @unsafe_stmt
+| 26 = @fixed_stmt
+| 27 = @label_stmt
+| 28 = @catch
+| 29 = @case_stmt
+| 30 = @local_function_stmt
+| 31 = @using_decl_stmt
+ ;
+
+@using_stmt = @using_block_stmt | @using_decl_stmt;
+
+@labeled_stmt = @label_stmt | @case;
+
+@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt;
+
+@cond_stmt = @if_stmt | @switch_stmt;
+
+@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt;
+
+@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt
+ | @yield_stmt;
+
+@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt;
+
+
+stmt_location(
+ unique int id: @stmt ref,
+ int loc: @location ref);
+
+catch_type(
+ unique int catch_id: @catch ref,
+ int type_id: @type_or_ref ref,
+ int kind: int ref /* explicit = 1, implicit = 2 */);
+
+foreach_stmt_info(
+ unique int id: @foreach_stmt ref,
+ int kind: int ref /* non-async = 1, async = 2 */);
+
+@foreach_symbol = @method | @property | @type_or_ref;
+
+#keyset[id, kind]
+foreach_stmt_desugar(
+ int id: @foreach_stmt ref,
+ int symbol: @foreach_symbol ref,
+ int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */);
+
+/** EXPRESSIONS **/
+
+expressions(
+ unique int id: @expr,
+ int kind: int ref,
+ int type_id: @type_or_ref ref);
+
+#keyset[index, parent]
+expr_parent(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif;
+
+@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+expr_parent_top_level(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @top_level_exprorstmt_parent ref);
+
+case @expr.kind of
+/* literal */
+ 1 = @bool_literal_expr
+| 2 = @char_literal_expr
+| 3 = @decimal_literal_expr
+| 4 = @int_literal_expr
+| 5 = @long_literal_expr
+| 6 = @uint_literal_expr
+| 7 = @ulong_literal_expr
+| 8 = @float_literal_expr
+| 9 = @double_literal_expr
+| 10 = @utf16_string_literal_expr
+| 11 = @null_literal_expr
+/* primary & unary */
+| 12 = @this_access_expr
+| 13 = @base_access_expr
+| 14 = @local_variable_access_expr
+| 15 = @parameter_access_expr
+| 16 = @field_access_expr
+| 17 = @property_access_expr
+| 18 = @method_access_expr
+| 19 = @event_access_expr
+| 20 = @indexer_access_expr
+| 21 = @array_access_expr
+| 22 = @type_access_expr
+| 23 = @typeof_expr
+| 24 = @method_invocation_expr
+| 25 = @delegate_invocation_expr
+| 26 = @operator_invocation_expr
+| 27 = @cast_expr
+| 28 = @object_creation_expr
+| 29 = @explicit_delegate_creation_expr
+| 30 = @implicit_delegate_creation_expr
+| 31 = @array_creation_expr
+| 32 = @default_expr
+| 33 = @plus_expr
+| 34 = @minus_expr
+| 35 = @bit_not_expr
+| 36 = @log_not_expr
+| 37 = @post_incr_expr
+| 38 = @post_decr_expr
+| 39 = @pre_incr_expr
+| 40 = @pre_decr_expr
+/* multiplicative */
+| 41 = @mul_expr
+| 42 = @div_expr
+| 43 = @rem_expr
+/* additive */
+| 44 = @add_expr
+| 45 = @sub_expr
+/* shift */
+| 46 = @lshift_expr
+| 47 = @rshift_expr
+/* relational */
+| 48 = @lt_expr
+| 49 = @gt_expr
+| 50 = @le_expr
+| 51 = @ge_expr
+/* equality */
+| 52 = @eq_expr
+| 53 = @ne_expr
+/* logical */
+| 54 = @bit_and_expr
+| 55 = @bit_xor_expr
+| 56 = @bit_or_expr
+| 57 = @log_and_expr
+| 58 = @log_or_expr
+/* type testing */
+| 59 = @is_expr
+| 60 = @as_expr
+/* null coalescing */
+| 61 = @null_coalescing_expr
+/* conditional */
+| 62 = @conditional_expr
+/* assignment */
+| 63 = @simple_assign_expr
+| 64 = @assign_add_expr
+| 65 = @assign_sub_expr
+| 66 = @assign_mul_expr
+| 67 = @assign_div_expr
+| 68 = @assign_rem_expr
+| 69 = @assign_and_expr
+| 70 = @assign_xor_expr
+| 71 = @assign_or_expr
+| 72 = @assign_lshift_expr
+| 73 = @assign_rshift_expr
+/* more */
+| 74 = @object_init_expr
+| 75 = @collection_init_expr
+| 76 = @array_init_expr
+| 77 = @checked_expr
+| 78 = @unchecked_expr
+| 79 = @constructor_init_expr
+| 80 = @add_event_expr
+| 81 = @remove_event_expr
+| 82 = @par_expr
+| 83 = @local_var_decl_expr
+| 84 = @lambda_expr
+| 85 = @anonymous_method_expr
+| 86 = @namespace_expr
+/* dynamic */
+| 92 = @dynamic_element_access_expr
+| 93 = @dynamic_member_access_expr
+/* unsafe */
+| 100 = @pointer_indirection_expr
+| 101 = @address_of_expr
+| 102 = @sizeof_expr
+/* async */
+| 103 = @await_expr
+/* C# 6.0 */
+| 104 = @nameof_expr
+| 105 = @interpolated_string_expr
+| 106 = @unknown_expr
+/* C# 7.0 */
+| 107 = @throw_expr
+| 108 = @tuple_expr
+| 109 = @local_function_invocation_expr
+| 110 = @ref_expr
+| 111 = @discard_expr
+/* C# 8.0 */
+| 112 = @range_expr
+| 113 = @index_expr
+| 114 = @switch_expr
+| 115 = @recursive_pattern_expr
+| 116 = @property_pattern_expr
+| 117 = @positional_pattern_expr
+| 118 = @switch_case_expr
+| 119 = @assign_coalesce_expr
+| 120 = @suppress_nullable_warning_expr
+| 121 = @namespace_access_expr
+/* C# 9.0 */
+| 122 = @lt_pattern_expr
+| 123 = @gt_pattern_expr
+| 124 = @le_pattern_expr
+| 125 = @ge_pattern_expr
+| 126 = @not_pattern_expr
+| 127 = @and_pattern_expr
+| 128 = @or_pattern_expr
+| 129 = @function_pointer_invocation_expr
+| 130 = @with_expr
+/* C# 11.0 */
+| 131 = @list_pattern_expr
+| 132 = @slice_pattern_expr
+| 133 = @urshift_expr
+| 134 = @assign_urshift_expr
+| 135 = @utf8_string_literal_expr
+/* C# 12.0 */
+| 136 = @collection_expr
+| 137 = @spread_element_expr
+| 138 = @interpolated_string_insert_expr
+/* Preprocessor */
+| 999 = @define_symbol_expr
+;
+
+@switch = @switch_stmt | @switch_expr;
+@case = @case_stmt | @switch_case_expr;
+@pattern_match = @case | @is_expr;
+@unary_pattern_expr = @not_pattern_expr;
+@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr;
+@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr;
+
+@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr;
+@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr;
+@string_literal_expr = @utf16_string_literal_expr | @utf8_string_literal_expr;
+@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr
+ | @string_literal_expr | @null_literal_expr;
+
+@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr;
+@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr;
+@assign_event_expr = @add_event_expr | @remove_event_expr;
+
+@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr
+ | @assign_rem_expr
+@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr
+ | @assign_lshift_expr | @assign_rshift_expr | @assign_urshift_expr;
+
+@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr
+ | @method_access_expr | @type_access_expr | @dynamic_member_access_expr;
+@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr;
+@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr;
+
+@local_variable_access = @local_variable_access_expr | @local_var_decl_expr;
+@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access;
+@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr;
+
+@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr
+ | @event_access_expr | @dynamic_member_access_expr;
+
+@objectorcollection_init_expr = @object_init_expr | @collection_init_expr;
+
+@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr;
+
+@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
+@incr_op_expr = @pre_incr_expr | @post_incr_expr;
+@decr_op_expr = @pre_decr_expr | @post_decr_expr;
+@mut_op_expr = @incr_op_expr | @decr_op_expr;
+@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr;
+@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr;
+
+@ternary_log_op_expr = @conditional_expr;
+@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr;
+@un_log_op_expr = @log_not_expr;
+@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr;
+
+@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
+ | @rshift_expr | @urshift_expr;
+@un_bit_op_expr = @bit_not_expr;
+@bit_expr = @un_bit_op_expr | @bin_bit_op_expr;
+
+@equality_op_expr = @eq_expr | @ne_expr;
+@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr;
+@comp_expr = @equality_op_expr | @rel_op_expr;
+
+@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op;
+
+@ternary_op = @ternary_log_op_expr;
+@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr;
+@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr
+ | @pointer_indirection_expr | @address_of_expr;
+
+@anonymous_function_expr = @lambda_expr | @anonymous_method_expr;
+
+@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr
+ | @delegate_invocation_expr | @object_creation_expr | @call_access_expr
+ | @local_function_invocation_expr | @function_pointer_invocation_expr;
+
+@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr;
+
+@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr
+ | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr;
+
+@throw_element = @throw_expr | @throw_stmt;
+
+@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr;
+
+implicitly_typed_array_creation(
+ unique int id: @array_creation_expr ref);
+
+explicitly_sized_array_creation(
+ unique int id: @array_creation_expr ref);
+
+stackalloc_array_creation(
+ unique int id: @array_creation_expr ref);
+
+implicitly_typed_object_creation(
+ unique int id: @implicitly_typeable_object_creation_expr ref);
+
+mutator_invocation_mode(
+ unique int id: @operator_invocation_expr ref,
+ int mode: int ref /* prefix = 1, postfix = 2*/);
+
+expr_value(
+ unique int id: @expr ref,
+ string value: string ref);
+
+expr_call(
+ unique int caller_id: @expr ref,
+ int target_id: @callable ref);
+
+expr_access(
+ unique int accesser_id: @access_expr ref,
+ int target_id: @accessible ref);
+
+@accessible = @method | @assignable | @local_function | @namespace;
+
+expr_location(
+ unique int id: @expr ref,
+ int loc: @location ref);
+
+dynamic_member_name(
+ unique int id: @late_bindable_expr ref,
+ string name: string ref);
+
+@qualifiable_expr = @member_access_expr
+ | @method_invocation_expr
+ | @element_access_expr;
+
+conditional_access(
+ unique int id: @qualifiable_expr ref);
+
+expr_argument(
+ unique int id: @expr ref,
+ int mode: int ref);
+ /* mode is the same as params: value = 0, ref = 1, out = 2 */
+
+expr_argument_name(
+ unique int id: @expr ref,
+ string name: string ref);
+
+lambda_expr_return_type(
+ unique int id: @lambda_expr ref,
+ int type_id: @type_or_ref ref);
+
+/* Compiler generated */
+
+compiler_generated(unique int id: @element ref);
+
+/** CONTROL/DATA FLOW **/
+
+@control_flow_element = @stmt | @expr;
+
+/* XML Files */
+
+xmlEncoding (
+ unique int id: @file ref,
+ string encoding: string ref);
+
+xmlDTDs(
+ unique int id: @xmldtd,
+ string root: string ref,
+ string publicId: string ref,
+ string systemId: string ref,
+ int fileid: @file ref);
+
+xmlElements(
+ unique int id: @xmlelement,
+ string name: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlAttrs(
+ unique int id: @xmlattribute,
+ int elementid: @xmlelement ref,
+ string name: string ref,
+ string value: string ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlNs(
+ int id: @xmlnamespace,
+ string prefixName: string ref,
+ string URI: string ref,
+ int fileid: @file ref);
+
+xmlHasNs(
+ int elementId: @xmlnamespaceable ref,
+ int nsId: @xmlnamespace ref,
+ int fileid: @file ref);
+
+xmlComments(
+ unique int id: @xmlcomment,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int fileid: @file ref);
+
+xmlChars(
+ unique int id: @xmlcharacters,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int isCDATA: int ref,
+ int fileid: @file ref);
+
+@xmlparent = @file | @xmlelement;
+@xmlnamespaceable = @xmlelement | @xmlattribute;
+
+xmllocations(
+ int xmlElement: @xmllocatable ref,
+ int location: @location_default ref);
+
+@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
+
+/* Comments */
+
+commentline(
+ unique int id: @commentline,
+ int kind: int ref,
+ string text: string ref,
+ string rawtext: string ref);
+
+case @commentline.kind of
+ 0 = @singlelinecomment
+| 1 = @xmldoccomment
+| 2 = @multilinecomment;
+
+commentline_location(
+ unique int id: @commentline ref,
+ int loc: @location ref);
+
+commentblock(
+ unique int id : @commentblock);
+
+commentblock_location(
+ unique int id: @commentblock ref,
+ int loc: @location ref);
+
+commentblock_binding(
+ int id: @commentblock ref,
+ int entity: @element ref,
+ int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */
+
+commentblock_child(
+ int id: @commentblock ref,
+ int commentline: @commentline ref,
+ int index: int ref);
+
+/* ASP.NET */
+
+case @asp_element.kind of
+ 0=@asp_close_tag
+| 1=@asp_code
+| 2=@asp_comment
+| 3=@asp_data_binding
+| 4=@asp_directive
+| 5=@asp_open_tag
+| 6=@asp_quoted_string
+| 7=@asp_text
+| 8=@asp_xml_directive;
+
+@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string;
+
+asp_elements(
+ unique int id: @asp_element,
+ int kind: int ref,
+ int loc: @location ref);
+
+asp_comment_server(unique int comment: @asp_comment ref);
+asp_code_inline(unique int code: @asp_code ref);
+asp_directive_attribute(
+ int directive: @asp_directive ref,
+ int index: int ref,
+ string name: string ref,
+ int value: @asp_quoted_string ref);
+asp_directive_name(
+ unique int directive: @asp_directive ref,
+ string name: string ref);
+asp_element_body(
+ unique int element: @asp_element ref,
+ string body: string ref);
+asp_tag_attribute(
+ int tag: @asp_open_tag ref,
+ int index: int ref,
+ string name: string ref,
+ int attribute: @asp_attribute ref);
+asp_tag_name(
+ unique int tag: @asp_open_tag ref,
+ string name: string ref);
+asp_tag_isempty(int tag: @asp_open_tag ref);
diff --git a/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/semmlecode.csharp.dbscheme b/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/semmlecode.csharp.dbscheme
new file mode 100644
index 000000000000..a2bda57dbc6e
--- /dev/null
+++ b/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/semmlecode.csharp.dbscheme
@@ -0,0 +1,1459 @@
+/* This is a dummy line to alter the dbscheme, so we can make a database upgrade
+ * without actually changing any of the dbscheme predicates. It contains a date
+ * to allow for such updates in the future as well.
+ *
+ * 2021-07-14
+ *
+ * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a
+ * previously seen state (matching a previously seen SHA), which would make the upgrade
+ * mechanism not work properly.
+ */
+
+/**
+ * An invocation of the compiler. Note that more than one file may be
+ * compiled per invocation. For example, this command compiles three
+ * source files:
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * The `id` simply identifies the invocation, while `cwd` is the working
+ * directory from which the compiler was invoked.
+ */
+compilations(
+ unique int id : @compilation,
+ string cwd : string ref
+);
+
+compilation_info(
+ int id : @compilation ref,
+ string info_key: string ref,
+ string info_value: string ref
+)
+
+/**
+ * The arguments that were passed to the extractor for a compiler
+ * invocation. If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then typically there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | --compiler
+ * 1 | *path to compiler*
+ * 2 | f1.cs
+ * 3 | f2.cs
+ * 4 | f3.cs
+ */
+#keyset[id, num]
+compilation_args(
+ int id : @compilation ref,
+ int num : int ref,
+ string arg : string ref
+);
+
+/**
+ * The expanded arguments that were passed to the extractor for a
+ * compiler invocation. This is similar to `compilation_args`, but
+ * for a `@someFile.rsp` argument, it includes the arguments from that
+ * file, rather than just taking the argument literally.
+ */
+#keyset[id, num]
+compilation_expanded_args(
+ int id : @compilation ref,
+ int num : int ref,
+ string arg : string ref
+);
+
+/**
+ * The source files that are compiled by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | f1.cs
+ * 1 | f2.cs
+ * 2 | f3.cs
+ */
+#keyset[id, num]
+compilation_compiling_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The references used by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | ref1.dll
+ * 1 | ref2.dll
+ * 2 | ref3.dll
+ */
+#keyset[id, num]
+compilation_referencing_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The time taken by the extractor for a compiler invocation.
+ *
+ * For each file `num`, there will be rows for
+ *
+ * kind | seconds
+ * ---- | ---
+ * 1 | CPU seconds used by the extractor frontend
+ * 2 | Elapsed seconds during the extractor frontend
+ * 3 | CPU seconds used by the extractor backend
+ * 4 | Elapsed seconds during the extractor backend
+ */
+#keyset[id, num, kind]
+compilation_time(
+ int id : @compilation ref,
+ int num : int ref,
+ /* kind:
+ 1 = frontend_cpu_seconds
+ 2 = frontend_elapsed_seconds
+ 3 = extractor_cpu_seconds
+ 4 = extractor_elapsed_seconds
+ */
+ int kind : int ref,
+ float seconds : float ref
+);
+
+/**
+ * An error or warning generated by the extractor.
+ * The diagnostic message `diagnostic` was generated during compiler
+ * invocation `compilation`, and is the `file_number_diagnostic_number`th
+ * message generated while extracting the `file_number`th file of that
+ * invocation.
+ */
+#keyset[compilation, file_number, file_number_diagnostic_number]
+diagnostic_for(
+ unique int diagnostic : @diagnostic ref,
+ int compilation : @compilation ref,
+ int file_number : int ref,
+ int file_number_diagnostic_number : int ref
+);
+
+diagnostics(
+ unique int id: @diagnostic,
+ int severity: int ref,
+ string error_tag: string ref,
+ string error_message: string ref,
+ string full_error_message: string ref,
+ int location: @location ref
+);
+
+extractor_messages(
+ unique int id: @extractor_message,
+ int severity: int ref,
+ string origin : string ref,
+ string text : string ref,
+ string entity : string ref,
+ int location: @location ref,
+ string stack_trace : string ref
+);
+
+/**
+ * If extraction was successful, then `cpu_seconds` and
+ * `elapsed_seconds` are the CPU time and elapsed time (respectively)
+ * that extraction took for compiler invocation `id`.
+ */
+compilation_finished(
+ unique int id : @compilation ref,
+ float cpu_seconds : float ref,
+ float elapsed_seconds : float ref
+);
+
+compilation_assembly(
+ unique int id : @compilation ref,
+ int assembly: @assembly ref
+)
+
+// Populated by the CSV extractor
+externalData(
+ int id: @externalDataElement,
+ string path: string ref,
+ int column: int ref,
+ string value: string ref);
+
+sourceLocationPrefix(
+ string prefix: string ref);
+
+/*
+ * C# dbscheme
+ */
+
+/** ELEMENTS **/
+
+@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration
+ | @using_directive | @type_parameter_constraints | @externalDataElement
+ | @xmllocatable | @asp_element | @namespace | @preprocessor_directive;
+
+@declaration = @callable | @generic | @assignable | @namespace;
+
+@named_element = @namespace | @declaration;
+
+@declaration_with_accessors = @property | @indexer | @event;
+
+@assignable = @variable | @assignable_with_accessors | @event;
+
+@assignable_with_accessors = @property | @indexer;
+
+@attributable = @assembly | @field | @parameter | @operator | @method | @constructor
+ | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors
+ | @local_function | @lambda_expr;
+
+/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/
+
+@location = @location_default | @assembly;
+
+locations_default(
+ unique int id: @location_default,
+ int file: @file ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+locations_mapped(
+ unique int id: @location_default ref,
+ int mapped_to: @location_default ref);
+
+@sourceline = @file | @callable | @xmllocatable;
+
+numlines(
+ int element_id: @sourceline ref,
+ int num_lines: int ref,
+ int num_code: int ref,
+ int num_comment: int ref);
+
+assemblies(
+ unique int id: @assembly,
+ int file: @file ref,
+ string fullname: string ref,
+ string name: string ref,
+ string version: string ref);
+
+files(
+ unique int id: @file,
+ string name: string ref);
+
+folders(
+ unique int id: @folder,
+ string name: string ref);
+
+@container = @folder | @file ;
+
+containerparent(
+ int parent: @container ref,
+ unique int child: @container ref);
+
+file_extraction_mode(
+ unique int file: @file ref,
+ int mode: int ref
+ /* 0 = normal, 1 = standalone extractor */
+ );
+
+/** NAMESPACES **/
+
+@type_container = @namespace | @type;
+
+namespaces(
+ unique int id: @namespace,
+ string name: string ref);
+
+namespace_declarations(
+ unique int id: @namespace_declaration,
+ int namespace_id: @namespace ref);
+
+namespace_declaration_location(
+ unique int id: @namespace_declaration ref,
+ int loc: @location ref);
+
+parent_namespace(
+ unique int child_id: @type_container ref,
+ int namespace_id: @namespace ref);
+
+@declaration_or_directive = @namespace_declaration | @type | @using_directive;
+
+parent_namespace_declaration(
+ int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes
+ int namespace_id: @namespace_declaration ref);
+
+@using_directive = @using_namespace_directive | @using_static_directive;
+
+using_global(
+ unique int id: @using_directive ref
+);
+
+using_namespace_directives(
+ unique int id: @using_namespace_directive,
+ int namespace_id: @namespace ref);
+
+using_static_directives(
+ unique int id: @using_static_directive,
+ int type_id: @type_or_ref ref);
+
+using_directive_location(
+ unique int id: @using_directive ref,
+ int loc: @location ref);
+
+@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning
+ | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if
+ | @directive_elif | @directive_else | @directive_endif;
+
+@conditional_directive = @directive_if | @directive_elif;
+@branch_directive = @directive_if | @directive_elif | @directive_else;
+
+directive_ifs(
+ unique int id: @directive_if,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref); /* 0: false, 1: true */
+
+directive_elifs(
+ unique int id: @directive_elif,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+directive_elses(
+ unique int id: @directive_else,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+#keyset[id, start]
+directive_endifs(
+ unique int id: @directive_endif,
+ unique int start: @directive_if ref);
+
+directive_define_symbols(
+ unique int id: @define_symbol_expr ref,
+ string name: string ref);
+
+directive_regions(
+ unique int id: @directive_region,
+ string name: string ref);
+
+#keyset[id, start]
+directive_endregions(
+ unique int id: @directive_endregion,
+ unique int start: @directive_region ref);
+
+directive_lines(
+ unique int id: @directive_line,
+ int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */
+
+directive_line_value(
+ unique int id: @directive_line ref,
+ int line: int ref);
+
+directive_line_file(
+ unique int id: @directive_line ref,
+ int file: @file ref);
+
+directive_line_offset(
+ unique int id: @directive_line ref,
+ int offset: int ref);
+
+directive_line_span(
+ unique int id: @directive_line ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+directive_nullables(
+ unique int id: @directive_nullable,
+ int setting: int ref, /* 0: disable, 1: enable, 2: restore */
+ int target: int ref); /* 0: none, 1: annotations, 2: warnings */
+
+directive_warnings(
+ unique int id: @directive_warning,
+ string message: string ref);
+
+directive_errors(
+ unique int id: @directive_error,
+ string message: string ref);
+
+directive_undefines(
+ unique int id: @directive_undefine,
+ string name: string ref);
+
+directive_defines(
+ unique int id: @directive_define,
+ string name: string ref);
+
+pragma_checksums(
+ unique int id: @pragma_checksum,
+ int file: @file ref,
+ string guid: string ref,
+ string bytes: string ref);
+
+pragma_warnings(
+ unique int id: @pragma_warning,
+ int kind: int ref /* 0 = disable, 1 = restore */);
+
+#keyset[id, index]
+pragma_warning_error_codes(
+ int id: @pragma_warning ref,
+ string errorCode: string ref,
+ int index: int ref);
+
+preprocessor_directive_location(
+ unique int id: @preprocessor_directive ref,
+ int loc: @location ref);
+
+preprocessor_directive_compilation(
+ int id: @preprocessor_directive ref,
+ int compilation: @compilation ref);
+
+preprocessor_directive_active(
+ unique int id: @preprocessor_directive ref,
+ int active: int ref); /* 0: false, 1: true */
+
+/** TYPES **/
+
+types(
+ unique int id: @type,
+ int kind: int ref,
+ string name: string ref);
+
+case @type.kind of
+ 1 = @bool_type
+| 2 = @char_type
+| 3 = @decimal_type
+| 4 = @sbyte_type
+| 5 = @short_type
+| 6 = @int_type
+| 7 = @long_type
+| 8 = @byte_type
+| 9 = @ushort_type
+| 10 = @uint_type
+| 11 = @ulong_type
+| 12 = @float_type
+| 13 = @double_type
+| 14 = @enum_type
+| 15 = @struct_type
+| 17 = @class_type
+| 19 = @interface_type
+| 20 = @delegate_type
+| 21 = @null_type
+| 22 = @type_parameter
+| 23 = @pointer_type
+| 24 = @nullable_type
+| 25 = @array_type
+| 26 = @void_type
+| 27 = @int_ptr_type
+| 28 = @uint_ptr_type
+| 29 = @dynamic_type
+| 30 = @arglist_type
+| 31 = @unknown_type
+| 32 = @tuple_type
+| 33 = @function_pointer_type
+| 34 = @inline_array_type
+ ;
+
+@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type;
+@integral_type = @signed_integral_type | @unsigned_integral_type;
+@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type;
+@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type;
+@floating_point_type = @float_type | @double_type;
+@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type
+ | @uint_ptr_type | @tuple_type | @void_type | @inline_array_type;
+@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type
+ | @dynamic_type;
+@value_or_ref_type = @value_type | @ref_type;
+
+typerefs(
+ unique int id: @typeref,
+ string name: string ref);
+
+typeref_type(
+ int id: @typeref ref,
+ unique int typeId: @type ref);
+
+@type_or_ref = @type | @typeref;
+
+array_element_type(
+ unique int array: @array_type ref,
+ int dimension: int ref,
+ int rank: int ref,
+ int element: @type_or_ref ref);
+
+nullable_underlying_type(
+ unique int nullable: @nullable_type ref,
+ int underlying: @type_or_ref ref);
+
+pointer_referent_type(
+ unique int pointer: @pointer_type ref,
+ int referent: @type_or_ref ref);
+
+enum_underlying_type(
+ unique int enum_id: @enum_type ref,
+ int underlying_type_id: @type_or_ref ref);
+
+delegate_return_type(
+ unique int delegate_id: @delegate_type ref,
+ int return_type_id: @type_or_ref ref);
+
+function_pointer_return_type(
+ unique int function_pointer_id: @function_pointer_type ref,
+ int return_type_id: @type_or_ref ref);
+
+extend(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+anonymous_types(
+ unique int id: @type ref);
+
+@interface_or_ref = @interface_type | @typeref;
+
+implement(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+type_location(
+ int id: @type ref,
+ int loc: @location ref);
+
+tuple_underlying_type(
+ unique int tuple: @tuple_type ref,
+ int struct: @type_or_ref ref);
+
+#keyset[tuple, index]
+tuple_element(
+ int tuple: @tuple_type ref,
+ int index: int ref,
+ unique int field: @field ref);
+
+attributes(
+ unique int id: @attribute,
+ int kind: int ref,
+ int type_id: @type_or_ref ref,
+ int target: @attributable ref);
+
+case @attribute.kind of
+ 0 = @attribute_default
+| 1 = @attribute_return
+| 2 = @attribute_assembly
+| 3 = @attribute_module
+;
+
+attribute_location(
+ int id: @attribute ref,
+ int loc: @location ref);
+
+@type_mention_parent = @element | @type_mention;
+
+type_mention(
+ unique int id: @type_mention,
+ int type_id: @type_or_ref ref,
+ int parent: @type_mention_parent ref);
+
+type_mention_location(
+ unique int id: @type_mention ref,
+ int loc: @location ref);
+
+@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type;
+
+/**
+ * A direct annotation on an entity, for example `string? x;`.
+ *
+ * Annotations:
+ * 2 = reftype is not annotated "!"
+ * 3 = reftype is annotated "?"
+ * 4 = readonly ref type / in parameter
+ * 5 = ref type parameter, return or local variable
+ * 6 = out parameter
+ *
+ * Note that the annotation depends on the element it annotates.
+ * @assignable: The annotation is on the type of the assignable, for example the variable type.
+ * @type_parameter: The annotation is on the reftype constraint
+ * @callable: The annotation is on the return type
+ * @array_type: The annotation is on the element type
+ */
+type_annotation(int id: @has_type_annotation ref, int annotation: int ref);
+
+nullability(unique int nullability: @nullability, int kind: int ref);
+
+case @nullability.kind of
+ 0 = @oblivious
+| 1 = @not_annotated
+| 2 = @annotated
+;
+
+#keyset[parent, index]
+nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref)
+
+type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref);
+
+/**
+ * The nullable flow state of an expression, as determined by Roslyn.
+ * 0 = none (default, not populated)
+ * 1 = not null
+ * 2 = maybe null
+ */
+expr_flowstate(unique int id: @expr ref, int state: int ref);
+
+/** GENERICS **/
+
+@generic = @type | @method | @local_function;
+
+type_parameters(
+ unique int id: @type_parameter ref,
+ int index: int ref,
+ int generic_id: @generic ref,
+ int variance: int ref /* none = 0, out = 1, in = 2 */);
+
+#keyset[constructed_id, index]
+type_arguments(
+ int id: @type_or_ref ref,
+ int index: int ref,
+ int constructed_id: @generic_or_ref ref);
+
+@generic_or_ref = @generic | @typeref;
+
+constructed_generic(
+ unique int constructed: @generic ref,
+ int generic: @generic_or_ref ref);
+
+type_parameter_constraints(
+ unique int id: @type_parameter_constraints,
+ int param_id: @type_parameter ref);
+
+type_parameter_constraints_location(
+ int id: @type_parameter_constraints ref,
+ int loc: @location ref);
+
+general_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int kind: int ref /* class = 1, struct = 2, new = 3 */);
+
+specific_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref);
+
+specific_type_parameter_nullability(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref,
+ int nullability: @nullability ref);
+
+/** FUNCTION POINTERS */
+
+function_pointer_calling_conventions(
+ int id: @function_pointer_type ref,
+ int kind: int ref);
+
+#keyset[id, index]
+has_unmanaged_calling_conventions(
+ int id: @function_pointer_type ref,
+ int index: int ref,
+ int conv_id: @type_or_ref ref);
+
+/** MODIFIERS */
+
+@modifiable = @modifiable_direct | @event_accessor;
+
+@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr;
+
+modifiers(
+ unique int id: @modifier,
+ string name: string ref);
+
+has_modifiers(
+ int id: @modifiable_direct ref,
+ int mod_id: @modifier ref);
+
+/** MEMBERS **/
+
+@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type;
+
+@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr;
+
+@virtualizable = @method | @property | @indexer | @event | @operator;
+
+exprorstmt_name(
+ unique int parent_id: @named_exprorstmt ref,
+ string name: string ref);
+
+nested_types(
+ unique int id: @type ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @type ref);
+
+properties(
+ unique int id: @property,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @property ref);
+
+property_location(
+ int id: @property ref,
+ int loc: @location ref);
+
+indexers(
+ unique int id: @indexer,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @indexer ref);
+
+indexer_location(
+ int id: @indexer ref,
+ int loc: @location ref);
+
+accessors(
+ unique int id: @accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_member_id: @member ref,
+ int unbound_id: @accessor ref);
+
+case @accessor.kind of
+ 1 = @getter
+| 2 = @setter
+ ;
+
+init_only_accessors(
+ unique int id: @accessor ref);
+
+accessor_location(
+ int id: @accessor ref,
+ int loc: @location ref);
+
+events(
+ unique int id: @event,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @event ref);
+
+event_location(
+ int id: @event ref,
+ int loc: @location ref);
+
+event_accessors(
+ unique int id: @event_accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_event_id: @event ref,
+ int unbound_id: @event_accessor ref);
+
+case @event_accessor.kind of
+ 1 = @add_event_accessor
+| 2 = @remove_event_accessor
+ ;
+
+event_accessor_location(
+ int id: @event_accessor ref,
+ int loc: @location ref);
+
+operators(
+ unique int id: @operator,
+ string name: string ref,
+ string symbol: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @operator ref);
+
+operator_location(
+ int id: @operator ref,
+ int loc: @location ref);
+
+constant_value(
+ int id: @variable ref,
+ string value: string ref);
+
+/** CALLABLES **/
+
+@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function;
+
+@callable_accessor = @accessor | @event_accessor;
+
+methods(
+ unique int id: @method,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @method ref);
+
+method_location(
+ int id: @method ref,
+ int loc: @location ref);
+
+constructors(
+ unique int id: @constructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @constructor ref);
+
+constructor_location(
+ int id: @constructor ref,
+ int loc: @location ref);
+
+destructors(
+ unique int id: @destructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @destructor ref);
+
+destructor_location(
+ int id: @destructor ref,
+ int loc: @location ref);
+
+overrides(
+ int id: @callable ref,
+ int base_id: @callable ref);
+
+explicitly_implements(
+ int id: @member ref,
+ int interface_id: @interface_or_ref ref);
+
+local_functions(
+ unique int id: @local_function,
+ string name: string ref,
+ int return_type: @type ref,
+ int unbound_id: @local_function ref);
+
+local_function_stmts(
+ unique int fn: @local_function_stmt ref,
+ int stmt: @local_function ref);
+
+/** VARIABLES **/
+
+@variable = @local_scope_variable | @field;
+
+@local_scope_variable = @local_variable | @parameter;
+
+fields(
+ unique int id: @field,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @field ref);
+
+case @field.kind of
+ 1 = @addressable_field
+| 2 = @constant
+ ;
+
+field_location(
+ int id: @field ref,
+ int loc: @location ref);
+
+localvars(
+ unique int id: @local_variable,
+ int kind: int ref,
+ string name: string ref,
+ int implicitly_typed: int ref /* 0 = no, 1 = yes */,
+ int type_id: @type_or_ref ref,
+ int parent_id: @local_var_decl_expr ref);
+
+case @local_variable.kind of
+ 1 = @addressable_local_variable
+| 2 = @local_constant
+| 3 = @local_variable_ref
+ ;
+
+localvar_location(
+ unique int id: @local_variable ref,
+ int loc: @location ref);
+
+@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type;
+
+#keyset[name, parent_id]
+#keyset[index, parent_id]
+params(
+ unique int id: @parameter,
+ string name: string ref,
+ int type_id: @type_or_ref ref,
+ int index: int ref,
+ int mode: int ref, /* value = 0, ref = 1, out = 2, params/array = 3, this = 4, in = 5, ref readonly = 6 */
+ int parent_id: @parameterizable ref,
+ int unbound_id: @parameter ref);
+
+param_location(
+ int id: @parameter ref,
+ int loc: @location ref);
+
+@has_scoped_annotation = @local_scope_variable
+
+scoped_annotation(
+ int id: @has_scoped_annotation ref,
+ int kind: int ref // scoped ref = 1, scoped value = 2
+ );
+
+/** STATEMENTS **/
+
+@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent;
+
+statements(
+ unique int id: @stmt,
+ int kind: int ref);
+
+#keyset[index, parent]
+stmt_parent(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_stmt_parent = @callable;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+stmt_parent_top_level(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @top_level_stmt_parent ref);
+
+case @stmt.kind of
+ 1 = @block_stmt
+| 2 = @expr_stmt
+| 3 = @if_stmt
+| 4 = @switch_stmt
+| 5 = @while_stmt
+| 6 = @do_stmt
+| 7 = @for_stmt
+| 8 = @foreach_stmt
+| 9 = @break_stmt
+| 10 = @continue_stmt
+| 11 = @goto_stmt
+| 12 = @goto_case_stmt
+| 13 = @goto_default_stmt
+| 14 = @throw_stmt
+| 15 = @return_stmt
+| 16 = @yield_stmt
+| 17 = @try_stmt
+| 18 = @checked_stmt
+| 19 = @unchecked_stmt
+| 20 = @lock_stmt
+| 21 = @using_block_stmt
+| 22 = @var_decl_stmt
+| 23 = @const_decl_stmt
+| 24 = @empty_stmt
+| 25 = @unsafe_stmt
+| 26 = @fixed_stmt
+| 27 = @label_stmt
+| 28 = @catch
+| 29 = @case_stmt
+| 30 = @local_function_stmt
+| 31 = @using_decl_stmt
+ ;
+
+@using_stmt = @using_block_stmt | @using_decl_stmt;
+
+@labeled_stmt = @label_stmt | @case;
+
+@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt;
+
+@cond_stmt = @if_stmt | @switch_stmt;
+
+@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt;
+
+@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt
+ | @yield_stmt;
+
+@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt;
+
+
+stmt_location(
+ unique int id: @stmt ref,
+ int loc: @location ref);
+
+catch_type(
+ unique int catch_id: @catch ref,
+ int type_id: @type_or_ref ref,
+ int kind: int ref /* explicit = 1, implicit = 2 */);
+
+foreach_stmt_info(
+ unique int id: @foreach_stmt ref,
+ int kind: int ref /* non-async = 1, async = 2 */);
+
+@foreach_symbol = @method | @property | @type_or_ref;
+
+#keyset[id, kind]
+foreach_stmt_desugar(
+ int id: @foreach_stmt ref,
+ int symbol: @foreach_symbol ref,
+ int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */);
+
+/** EXPRESSIONS **/
+
+expressions(
+ unique int id: @expr,
+ int kind: int ref,
+ int type_id: @type_or_ref ref);
+
+#keyset[index, parent]
+expr_parent(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif;
+
+@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+expr_parent_top_level(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @top_level_exprorstmt_parent ref);
+
+case @expr.kind of
+/* literal */
+ 1 = @bool_literal_expr
+| 2 = @char_literal_expr
+| 3 = @decimal_literal_expr
+| 4 = @int_literal_expr
+| 5 = @long_literal_expr
+| 6 = @uint_literal_expr
+| 7 = @ulong_literal_expr
+| 8 = @float_literal_expr
+| 9 = @double_literal_expr
+| 10 = @utf16_string_literal_expr
+| 11 = @null_literal_expr
+/* primary & unary */
+| 12 = @this_access_expr
+| 13 = @base_access_expr
+| 14 = @local_variable_access_expr
+| 15 = @parameter_access_expr
+| 16 = @field_access_expr
+| 17 = @property_access_expr
+| 18 = @method_access_expr
+| 19 = @event_access_expr
+| 20 = @indexer_access_expr
+| 21 = @array_access_expr
+| 22 = @type_access_expr
+| 23 = @typeof_expr
+| 24 = @method_invocation_expr
+| 25 = @delegate_invocation_expr
+| 26 = @operator_invocation_expr
+| 27 = @cast_expr
+| 28 = @object_creation_expr
+| 29 = @explicit_delegate_creation_expr
+| 30 = @implicit_delegate_creation_expr
+| 31 = @array_creation_expr
+| 32 = @default_expr
+| 33 = @plus_expr
+| 34 = @minus_expr
+| 35 = @bit_not_expr
+| 36 = @log_not_expr
+| 37 = @post_incr_expr
+| 38 = @post_decr_expr
+| 39 = @pre_incr_expr
+| 40 = @pre_decr_expr
+/* multiplicative */
+| 41 = @mul_expr
+| 42 = @div_expr
+| 43 = @rem_expr
+/* additive */
+| 44 = @add_expr
+| 45 = @sub_expr
+/* shift */
+| 46 = @lshift_expr
+| 47 = @rshift_expr
+/* relational */
+| 48 = @lt_expr
+| 49 = @gt_expr
+| 50 = @le_expr
+| 51 = @ge_expr
+/* equality */
+| 52 = @eq_expr
+| 53 = @ne_expr
+/* logical */
+| 54 = @bit_and_expr
+| 55 = @bit_xor_expr
+| 56 = @bit_or_expr
+| 57 = @log_and_expr
+| 58 = @log_or_expr
+/* type testing */
+| 59 = @is_expr
+| 60 = @as_expr
+/* null coalescing */
+| 61 = @null_coalescing_expr
+/* conditional */
+| 62 = @conditional_expr
+/* assignment */
+| 63 = @simple_assign_expr
+| 64 = @assign_add_expr
+| 65 = @assign_sub_expr
+| 66 = @assign_mul_expr
+| 67 = @assign_div_expr
+| 68 = @assign_rem_expr
+| 69 = @assign_and_expr
+| 70 = @assign_xor_expr
+| 71 = @assign_or_expr
+| 72 = @assign_lshift_expr
+| 73 = @assign_rshift_expr
+/* more */
+| 74 = @object_init_expr
+| 75 = @collection_init_expr
+| 76 = @array_init_expr
+| 77 = @checked_expr
+| 78 = @unchecked_expr
+| 79 = @constructor_init_expr
+| 80 = @add_event_expr
+| 81 = @remove_event_expr
+| 82 = @par_expr
+| 83 = @local_var_decl_expr
+| 84 = @lambda_expr
+| 85 = @anonymous_method_expr
+| 86 = @namespace_expr
+/* dynamic */
+| 92 = @dynamic_element_access_expr
+| 93 = @dynamic_member_access_expr
+/* unsafe */
+| 100 = @pointer_indirection_expr
+| 101 = @address_of_expr
+| 102 = @sizeof_expr
+/* async */
+| 103 = @await_expr
+/* C# 6.0 */
+| 104 = @nameof_expr
+| 105 = @interpolated_string_expr
+| 106 = @unknown_expr
+/* C# 7.0 */
+| 107 = @throw_expr
+| 108 = @tuple_expr
+| 109 = @local_function_invocation_expr
+| 110 = @ref_expr
+| 111 = @discard_expr
+/* C# 8.0 */
+| 112 = @range_expr
+| 113 = @index_expr
+| 114 = @switch_expr
+| 115 = @recursive_pattern_expr
+| 116 = @property_pattern_expr
+| 117 = @positional_pattern_expr
+| 118 = @switch_case_expr
+| 119 = @assign_coalesce_expr
+| 120 = @suppress_nullable_warning_expr
+| 121 = @namespace_access_expr
+/* C# 9.0 */
+| 122 = @lt_pattern_expr
+| 123 = @gt_pattern_expr
+| 124 = @le_pattern_expr
+| 125 = @ge_pattern_expr
+| 126 = @not_pattern_expr
+| 127 = @and_pattern_expr
+| 128 = @or_pattern_expr
+| 129 = @function_pointer_invocation_expr
+| 130 = @with_expr
+/* C# 11.0 */
+| 131 = @list_pattern_expr
+| 132 = @slice_pattern_expr
+| 133 = @urshift_expr
+| 134 = @assign_urshift_expr
+| 135 = @utf8_string_literal_expr
+/* C# 12.0 */
+| 136 = @collection_expr
+| 137 = @spread_element_expr
+/* Preprocessor */
+| 999 = @define_symbol_expr
+;
+
+@switch = @switch_stmt | @switch_expr;
+@case = @case_stmt | @switch_case_expr;
+@pattern_match = @case | @is_expr;
+@unary_pattern_expr = @not_pattern_expr;
+@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr;
+@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr;
+
+@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr;
+@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr;
+@string_literal_expr = @utf16_string_literal_expr | @utf8_string_literal_expr;
+@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr
+ | @string_literal_expr | @null_literal_expr;
+
+@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr;
+@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr;
+@assign_event_expr = @add_event_expr | @remove_event_expr;
+
+@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr
+ | @assign_rem_expr
+@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr
+ | @assign_lshift_expr | @assign_rshift_expr | @assign_urshift_expr;
+
+@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr
+ | @method_access_expr | @type_access_expr | @dynamic_member_access_expr;
+@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr;
+@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr;
+
+@local_variable_access = @local_variable_access_expr | @local_var_decl_expr;
+@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access;
+@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr;
+
+@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr
+ | @event_access_expr | @dynamic_member_access_expr;
+
+@objectorcollection_init_expr = @object_init_expr | @collection_init_expr;
+
+@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr;
+
+@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
+@incr_op_expr = @pre_incr_expr | @post_incr_expr;
+@decr_op_expr = @pre_decr_expr | @post_decr_expr;
+@mut_op_expr = @incr_op_expr | @decr_op_expr;
+@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr;
+@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr;
+
+@ternary_log_op_expr = @conditional_expr;
+@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr;
+@un_log_op_expr = @log_not_expr;
+@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr;
+
+@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
+ | @rshift_expr | @urshift_expr;
+@un_bit_op_expr = @bit_not_expr;
+@bit_expr = @un_bit_op_expr | @bin_bit_op_expr;
+
+@equality_op_expr = @eq_expr | @ne_expr;
+@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr;
+@comp_expr = @equality_op_expr | @rel_op_expr;
+
+@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op;
+
+@ternary_op = @ternary_log_op_expr;
+@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr;
+@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr
+ | @pointer_indirection_expr | @address_of_expr;
+
+@anonymous_function_expr = @lambda_expr | @anonymous_method_expr;
+
+@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr
+ | @delegate_invocation_expr | @object_creation_expr | @call_access_expr
+ | @local_function_invocation_expr | @function_pointer_invocation_expr;
+
+@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr;
+
+@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr
+ | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr;
+
+@throw_element = @throw_expr | @throw_stmt;
+
+@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr;
+
+implicitly_typed_array_creation(
+ unique int id: @array_creation_expr ref);
+
+explicitly_sized_array_creation(
+ unique int id: @array_creation_expr ref);
+
+stackalloc_array_creation(
+ unique int id: @array_creation_expr ref);
+
+implicitly_typed_object_creation(
+ unique int id: @implicitly_typeable_object_creation_expr ref);
+
+mutator_invocation_mode(
+ unique int id: @operator_invocation_expr ref,
+ int mode: int ref /* prefix = 1, postfix = 2*/);
+
+expr_value(
+ unique int id: @expr ref,
+ string value: string ref);
+
+expr_call(
+ unique int caller_id: @expr ref,
+ int target_id: @callable ref);
+
+expr_access(
+ unique int accesser_id: @access_expr ref,
+ int target_id: @accessible ref);
+
+@accessible = @method | @assignable | @local_function | @namespace;
+
+expr_location(
+ unique int id: @expr ref,
+ int loc: @location ref);
+
+dynamic_member_name(
+ unique int id: @late_bindable_expr ref,
+ string name: string ref);
+
+@qualifiable_expr = @member_access_expr
+ | @method_invocation_expr
+ | @element_access_expr;
+
+conditional_access(
+ unique int id: @qualifiable_expr ref);
+
+expr_argument(
+ unique int id: @expr ref,
+ int mode: int ref);
+ /* mode is the same as params: value = 0, ref = 1, out = 2 */
+
+expr_argument_name(
+ unique int id: @expr ref,
+ string name: string ref);
+
+lambda_expr_return_type(
+ unique int id: @lambda_expr ref,
+ int type_id: @type_or_ref ref);
+
+/* Compiler generated */
+
+compiler_generated(unique int id: @element ref);
+
+/** CONTROL/DATA FLOW **/
+
+@control_flow_element = @stmt | @expr;
+
+/* XML Files */
+
+xmlEncoding (
+ unique int id: @file ref,
+ string encoding: string ref);
+
+xmlDTDs(
+ unique int id: @xmldtd,
+ string root: string ref,
+ string publicId: string ref,
+ string systemId: string ref,
+ int fileid: @file ref);
+
+xmlElements(
+ unique int id: @xmlelement,
+ string name: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlAttrs(
+ unique int id: @xmlattribute,
+ int elementid: @xmlelement ref,
+ string name: string ref,
+ string value: string ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlNs(
+ int id: @xmlnamespace,
+ string prefixName: string ref,
+ string URI: string ref,
+ int fileid: @file ref);
+
+xmlHasNs(
+ int elementId: @xmlnamespaceable ref,
+ int nsId: @xmlnamespace ref,
+ int fileid: @file ref);
+
+xmlComments(
+ unique int id: @xmlcomment,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int fileid: @file ref);
+
+xmlChars(
+ unique int id: @xmlcharacters,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int isCDATA: int ref,
+ int fileid: @file ref);
+
+@xmlparent = @file | @xmlelement;
+@xmlnamespaceable = @xmlelement | @xmlattribute;
+
+xmllocations(
+ int xmlElement: @xmllocatable ref,
+ int location: @location_default ref);
+
+@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
+
+/* Comments */
+
+commentline(
+ unique int id: @commentline,
+ int kind: int ref,
+ string text: string ref,
+ string rawtext: string ref);
+
+case @commentline.kind of
+ 0 = @singlelinecomment
+| 1 = @xmldoccomment
+| 2 = @multilinecomment;
+
+commentline_location(
+ unique int id: @commentline ref,
+ int loc: @location ref);
+
+commentblock(
+ unique int id : @commentblock);
+
+commentblock_location(
+ unique int id: @commentblock ref,
+ int loc: @location ref);
+
+commentblock_binding(
+ int id: @commentblock ref,
+ int entity: @element ref,
+ int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */
+
+commentblock_child(
+ int id: @commentblock ref,
+ int commentline: @commentline ref,
+ int index: int ref);
+
+/* ASP.NET */
+
+case @asp_element.kind of
+ 0=@asp_close_tag
+| 1=@asp_code
+| 2=@asp_comment
+| 3=@asp_data_binding
+| 4=@asp_directive
+| 5=@asp_open_tag
+| 6=@asp_quoted_string
+| 7=@asp_text
+| 8=@asp_xml_directive;
+
+@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string;
+
+asp_elements(
+ unique int id: @asp_element,
+ int kind: int ref,
+ int loc: @location ref);
+
+asp_comment_server(unique int comment: @asp_comment ref);
+asp_code_inline(unique int code: @asp_code ref);
+asp_directive_attribute(
+ int directive: @asp_directive ref,
+ int index: int ref,
+ string name: string ref,
+ int value: @asp_quoted_string ref);
+asp_directive_name(
+ unique int directive: @asp_directive ref,
+ string name: string ref);
+asp_element_body(
+ unique int element: @asp_element ref,
+ string body: string ref);
+asp_tag_attribute(
+ int tag: @asp_open_tag ref,
+ int index: int ref,
+ string name: string ref,
+ int attribute: @asp_attribute ref);
+asp_tag_name(
+ unique int tag: @asp_open_tag ref,
+ string name: string ref);
+asp_tag_isempty(int tag: @asp_open_tag ref);
diff --git a/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/upgrade.properties b/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/upgrade.properties
new file mode 100644
index 000000000000..9e9a659b10a3
--- /dev/null
+++ b/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/upgrade.properties
@@ -0,0 +1,3 @@
+description: Remove `interpolated_string_insert_expr` kind.
+compatibility: partial
+expressions.rel: run expressions.qlo
diff --git a/csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/old.dbscheme b/csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/old.dbscheme
new file mode 100644
index 000000000000..a2bda57dbc6e
--- /dev/null
+++ b/csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/old.dbscheme
@@ -0,0 +1,1459 @@
+/* This is a dummy line to alter the dbscheme, so we can make a database upgrade
+ * without actually changing any of the dbscheme predicates. It contains a date
+ * to allow for such updates in the future as well.
+ *
+ * 2021-07-14
+ *
+ * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a
+ * previously seen state (matching a previously seen SHA), which would make the upgrade
+ * mechanism not work properly.
+ */
+
+/**
+ * An invocation of the compiler. Note that more than one file may be
+ * compiled per invocation. For example, this command compiles three
+ * source files:
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * The `id` simply identifies the invocation, while `cwd` is the working
+ * directory from which the compiler was invoked.
+ */
+compilations(
+ unique int id : @compilation,
+ string cwd : string ref
+);
+
+compilation_info(
+ int id : @compilation ref,
+ string info_key: string ref,
+ string info_value: string ref
+)
+
+/**
+ * The arguments that were passed to the extractor for a compiler
+ * invocation. If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then typically there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | --compiler
+ * 1 | *path to compiler*
+ * 2 | f1.cs
+ * 3 | f2.cs
+ * 4 | f3.cs
+ */
+#keyset[id, num]
+compilation_args(
+ int id : @compilation ref,
+ int num : int ref,
+ string arg : string ref
+);
+
+/**
+ * The expanded arguments that were passed to the extractor for a
+ * compiler invocation. This is similar to `compilation_args`, but
+ * for a `@someFile.rsp` argument, it includes the arguments from that
+ * file, rather than just taking the argument literally.
+ */
+#keyset[id, num]
+compilation_expanded_args(
+ int id : @compilation ref,
+ int num : int ref,
+ string arg : string ref
+);
+
+/**
+ * The source files that are compiled by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | f1.cs
+ * 1 | f2.cs
+ * 2 | f3.cs
+ */
+#keyset[id, num]
+compilation_compiling_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The references used by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | ref1.dll
+ * 1 | ref2.dll
+ * 2 | ref3.dll
+ */
+#keyset[id, num]
+compilation_referencing_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The time taken by the extractor for a compiler invocation.
+ *
+ * For each file `num`, there will be rows for
+ *
+ * kind | seconds
+ * ---- | ---
+ * 1 | CPU seconds used by the extractor frontend
+ * 2 | Elapsed seconds during the extractor frontend
+ * 3 | CPU seconds used by the extractor backend
+ * 4 | Elapsed seconds during the extractor backend
+ */
+#keyset[id, num, kind]
+compilation_time(
+ int id : @compilation ref,
+ int num : int ref,
+ /* kind:
+ 1 = frontend_cpu_seconds
+ 2 = frontend_elapsed_seconds
+ 3 = extractor_cpu_seconds
+ 4 = extractor_elapsed_seconds
+ */
+ int kind : int ref,
+ float seconds : float ref
+);
+
+/**
+ * An error or warning generated by the extractor.
+ * The diagnostic message `diagnostic` was generated during compiler
+ * invocation `compilation`, and is the `file_number_diagnostic_number`th
+ * message generated while extracting the `file_number`th file of that
+ * invocation.
+ */
+#keyset[compilation, file_number, file_number_diagnostic_number]
+diagnostic_for(
+ unique int diagnostic : @diagnostic ref,
+ int compilation : @compilation ref,
+ int file_number : int ref,
+ int file_number_diagnostic_number : int ref
+);
+
+diagnostics(
+ unique int id: @diagnostic,
+ int severity: int ref,
+ string error_tag: string ref,
+ string error_message: string ref,
+ string full_error_message: string ref,
+ int location: @location ref
+);
+
+extractor_messages(
+ unique int id: @extractor_message,
+ int severity: int ref,
+ string origin : string ref,
+ string text : string ref,
+ string entity : string ref,
+ int location: @location ref,
+ string stack_trace : string ref
+);
+
+/**
+ * If extraction was successful, then `cpu_seconds` and
+ * `elapsed_seconds` are the CPU time and elapsed time (respectively)
+ * that extraction took for compiler invocation `id`.
+ */
+compilation_finished(
+ unique int id : @compilation ref,
+ float cpu_seconds : float ref,
+ float elapsed_seconds : float ref
+);
+
+compilation_assembly(
+ unique int id : @compilation ref,
+ int assembly: @assembly ref
+)
+
+// Populated by the CSV extractor
+externalData(
+ int id: @externalDataElement,
+ string path: string ref,
+ int column: int ref,
+ string value: string ref);
+
+sourceLocationPrefix(
+ string prefix: string ref);
+
+/*
+ * C# dbscheme
+ */
+
+/** ELEMENTS **/
+
+@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration
+ | @using_directive | @type_parameter_constraints | @externalDataElement
+ | @xmllocatable | @asp_element | @namespace | @preprocessor_directive;
+
+@declaration = @callable | @generic | @assignable | @namespace;
+
+@named_element = @namespace | @declaration;
+
+@declaration_with_accessors = @property | @indexer | @event;
+
+@assignable = @variable | @assignable_with_accessors | @event;
+
+@assignable_with_accessors = @property | @indexer;
+
+@attributable = @assembly | @field | @parameter | @operator | @method | @constructor
+ | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors
+ | @local_function | @lambda_expr;
+
+/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/
+
+@location = @location_default | @assembly;
+
+locations_default(
+ unique int id: @location_default,
+ int file: @file ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+locations_mapped(
+ unique int id: @location_default ref,
+ int mapped_to: @location_default ref);
+
+@sourceline = @file | @callable | @xmllocatable;
+
+numlines(
+ int element_id: @sourceline ref,
+ int num_lines: int ref,
+ int num_code: int ref,
+ int num_comment: int ref);
+
+assemblies(
+ unique int id: @assembly,
+ int file: @file ref,
+ string fullname: string ref,
+ string name: string ref,
+ string version: string ref);
+
+files(
+ unique int id: @file,
+ string name: string ref);
+
+folders(
+ unique int id: @folder,
+ string name: string ref);
+
+@container = @folder | @file ;
+
+containerparent(
+ int parent: @container ref,
+ unique int child: @container ref);
+
+file_extraction_mode(
+ unique int file: @file ref,
+ int mode: int ref
+ /* 0 = normal, 1 = standalone extractor */
+ );
+
+/** NAMESPACES **/
+
+@type_container = @namespace | @type;
+
+namespaces(
+ unique int id: @namespace,
+ string name: string ref);
+
+namespace_declarations(
+ unique int id: @namespace_declaration,
+ int namespace_id: @namespace ref);
+
+namespace_declaration_location(
+ unique int id: @namespace_declaration ref,
+ int loc: @location ref);
+
+parent_namespace(
+ unique int child_id: @type_container ref,
+ int namespace_id: @namespace ref);
+
+@declaration_or_directive = @namespace_declaration | @type | @using_directive;
+
+parent_namespace_declaration(
+ int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes
+ int namespace_id: @namespace_declaration ref);
+
+@using_directive = @using_namespace_directive | @using_static_directive;
+
+using_global(
+ unique int id: @using_directive ref
+);
+
+using_namespace_directives(
+ unique int id: @using_namespace_directive,
+ int namespace_id: @namespace ref);
+
+using_static_directives(
+ unique int id: @using_static_directive,
+ int type_id: @type_or_ref ref);
+
+using_directive_location(
+ unique int id: @using_directive ref,
+ int loc: @location ref);
+
+@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning
+ | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if
+ | @directive_elif | @directive_else | @directive_endif;
+
+@conditional_directive = @directive_if | @directive_elif;
+@branch_directive = @directive_if | @directive_elif | @directive_else;
+
+directive_ifs(
+ unique int id: @directive_if,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref); /* 0: false, 1: true */
+
+directive_elifs(
+ unique int id: @directive_elif,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+directive_elses(
+ unique int id: @directive_else,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+#keyset[id, start]
+directive_endifs(
+ unique int id: @directive_endif,
+ unique int start: @directive_if ref);
+
+directive_define_symbols(
+ unique int id: @define_symbol_expr ref,
+ string name: string ref);
+
+directive_regions(
+ unique int id: @directive_region,
+ string name: string ref);
+
+#keyset[id, start]
+directive_endregions(
+ unique int id: @directive_endregion,
+ unique int start: @directive_region ref);
+
+directive_lines(
+ unique int id: @directive_line,
+ int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */
+
+directive_line_value(
+ unique int id: @directive_line ref,
+ int line: int ref);
+
+directive_line_file(
+ unique int id: @directive_line ref,
+ int file: @file ref);
+
+directive_line_offset(
+ unique int id: @directive_line ref,
+ int offset: int ref);
+
+directive_line_span(
+ unique int id: @directive_line ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+directive_nullables(
+ unique int id: @directive_nullable,
+ int setting: int ref, /* 0: disable, 1: enable, 2: restore */
+ int target: int ref); /* 0: none, 1: annotations, 2: warnings */
+
+directive_warnings(
+ unique int id: @directive_warning,
+ string message: string ref);
+
+directive_errors(
+ unique int id: @directive_error,
+ string message: string ref);
+
+directive_undefines(
+ unique int id: @directive_undefine,
+ string name: string ref);
+
+directive_defines(
+ unique int id: @directive_define,
+ string name: string ref);
+
+pragma_checksums(
+ unique int id: @pragma_checksum,
+ int file: @file ref,
+ string guid: string ref,
+ string bytes: string ref);
+
+pragma_warnings(
+ unique int id: @pragma_warning,
+ int kind: int ref /* 0 = disable, 1 = restore */);
+
+#keyset[id, index]
+pragma_warning_error_codes(
+ int id: @pragma_warning ref,
+ string errorCode: string ref,
+ int index: int ref);
+
+preprocessor_directive_location(
+ unique int id: @preprocessor_directive ref,
+ int loc: @location ref);
+
+preprocessor_directive_compilation(
+ int id: @preprocessor_directive ref,
+ int compilation: @compilation ref);
+
+preprocessor_directive_active(
+ unique int id: @preprocessor_directive ref,
+ int active: int ref); /* 0: false, 1: true */
+
+/** TYPES **/
+
+types(
+ unique int id: @type,
+ int kind: int ref,
+ string name: string ref);
+
+case @type.kind of
+ 1 = @bool_type
+| 2 = @char_type
+| 3 = @decimal_type
+| 4 = @sbyte_type
+| 5 = @short_type
+| 6 = @int_type
+| 7 = @long_type
+| 8 = @byte_type
+| 9 = @ushort_type
+| 10 = @uint_type
+| 11 = @ulong_type
+| 12 = @float_type
+| 13 = @double_type
+| 14 = @enum_type
+| 15 = @struct_type
+| 17 = @class_type
+| 19 = @interface_type
+| 20 = @delegate_type
+| 21 = @null_type
+| 22 = @type_parameter
+| 23 = @pointer_type
+| 24 = @nullable_type
+| 25 = @array_type
+| 26 = @void_type
+| 27 = @int_ptr_type
+| 28 = @uint_ptr_type
+| 29 = @dynamic_type
+| 30 = @arglist_type
+| 31 = @unknown_type
+| 32 = @tuple_type
+| 33 = @function_pointer_type
+| 34 = @inline_array_type
+ ;
+
+@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type;
+@integral_type = @signed_integral_type | @unsigned_integral_type;
+@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type;
+@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type;
+@floating_point_type = @float_type | @double_type;
+@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type
+ | @uint_ptr_type | @tuple_type | @void_type | @inline_array_type;
+@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type
+ | @dynamic_type;
+@value_or_ref_type = @value_type | @ref_type;
+
+typerefs(
+ unique int id: @typeref,
+ string name: string ref);
+
+typeref_type(
+ int id: @typeref ref,
+ unique int typeId: @type ref);
+
+@type_or_ref = @type | @typeref;
+
+array_element_type(
+ unique int array: @array_type ref,
+ int dimension: int ref,
+ int rank: int ref,
+ int element: @type_or_ref ref);
+
+nullable_underlying_type(
+ unique int nullable: @nullable_type ref,
+ int underlying: @type_or_ref ref);
+
+pointer_referent_type(
+ unique int pointer: @pointer_type ref,
+ int referent: @type_or_ref ref);
+
+enum_underlying_type(
+ unique int enum_id: @enum_type ref,
+ int underlying_type_id: @type_or_ref ref);
+
+delegate_return_type(
+ unique int delegate_id: @delegate_type ref,
+ int return_type_id: @type_or_ref ref);
+
+function_pointer_return_type(
+ unique int function_pointer_id: @function_pointer_type ref,
+ int return_type_id: @type_or_ref ref);
+
+extend(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+anonymous_types(
+ unique int id: @type ref);
+
+@interface_or_ref = @interface_type | @typeref;
+
+implement(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+type_location(
+ int id: @type ref,
+ int loc: @location ref);
+
+tuple_underlying_type(
+ unique int tuple: @tuple_type ref,
+ int struct: @type_or_ref ref);
+
+#keyset[tuple, index]
+tuple_element(
+ int tuple: @tuple_type ref,
+ int index: int ref,
+ unique int field: @field ref);
+
+attributes(
+ unique int id: @attribute,
+ int kind: int ref,
+ int type_id: @type_or_ref ref,
+ int target: @attributable ref);
+
+case @attribute.kind of
+ 0 = @attribute_default
+| 1 = @attribute_return
+| 2 = @attribute_assembly
+| 3 = @attribute_module
+;
+
+attribute_location(
+ int id: @attribute ref,
+ int loc: @location ref);
+
+@type_mention_parent = @element | @type_mention;
+
+type_mention(
+ unique int id: @type_mention,
+ int type_id: @type_or_ref ref,
+ int parent: @type_mention_parent ref);
+
+type_mention_location(
+ unique int id: @type_mention ref,
+ int loc: @location ref);
+
+@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type;
+
+/**
+ * A direct annotation on an entity, for example `string? x;`.
+ *
+ * Annotations:
+ * 2 = reftype is not annotated "!"
+ * 3 = reftype is annotated "?"
+ * 4 = readonly ref type / in parameter
+ * 5 = ref type parameter, return or local variable
+ * 6 = out parameter
+ *
+ * Note that the annotation depends on the element it annotates.
+ * @assignable: The annotation is on the type of the assignable, for example the variable type.
+ * @type_parameter: The annotation is on the reftype constraint
+ * @callable: The annotation is on the return type
+ * @array_type: The annotation is on the element type
+ */
+type_annotation(int id: @has_type_annotation ref, int annotation: int ref);
+
+nullability(unique int nullability: @nullability, int kind: int ref);
+
+case @nullability.kind of
+ 0 = @oblivious
+| 1 = @not_annotated
+| 2 = @annotated
+;
+
+#keyset[parent, index]
+nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref)
+
+type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref);
+
+/**
+ * The nullable flow state of an expression, as determined by Roslyn.
+ * 0 = none (default, not populated)
+ * 1 = not null
+ * 2 = maybe null
+ */
+expr_flowstate(unique int id: @expr ref, int state: int ref);
+
+/** GENERICS **/
+
+@generic = @type | @method | @local_function;
+
+type_parameters(
+ unique int id: @type_parameter ref,
+ int index: int ref,
+ int generic_id: @generic ref,
+ int variance: int ref /* none = 0, out = 1, in = 2 */);
+
+#keyset[constructed_id, index]
+type_arguments(
+ int id: @type_or_ref ref,
+ int index: int ref,
+ int constructed_id: @generic_or_ref ref);
+
+@generic_or_ref = @generic | @typeref;
+
+constructed_generic(
+ unique int constructed: @generic ref,
+ int generic: @generic_or_ref ref);
+
+type_parameter_constraints(
+ unique int id: @type_parameter_constraints,
+ int param_id: @type_parameter ref);
+
+type_parameter_constraints_location(
+ int id: @type_parameter_constraints ref,
+ int loc: @location ref);
+
+general_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int kind: int ref /* class = 1, struct = 2, new = 3 */);
+
+specific_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref);
+
+specific_type_parameter_nullability(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref,
+ int nullability: @nullability ref);
+
+/** FUNCTION POINTERS */
+
+function_pointer_calling_conventions(
+ int id: @function_pointer_type ref,
+ int kind: int ref);
+
+#keyset[id, index]
+has_unmanaged_calling_conventions(
+ int id: @function_pointer_type ref,
+ int index: int ref,
+ int conv_id: @type_or_ref ref);
+
+/** MODIFIERS */
+
+@modifiable = @modifiable_direct | @event_accessor;
+
+@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr;
+
+modifiers(
+ unique int id: @modifier,
+ string name: string ref);
+
+has_modifiers(
+ int id: @modifiable_direct ref,
+ int mod_id: @modifier ref);
+
+/** MEMBERS **/
+
+@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type;
+
+@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr;
+
+@virtualizable = @method | @property | @indexer | @event | @operator;
+
+exprorstmt_name(
+ unique int parent_id: @named_exprorstmt ref,
+ string name: string ref);
+
+nested_types(
+ unique int id: @type ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @type ref);
+
+properties(
+ unique int id: @property,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @property ref);
+
+property_location(
+ int id: @property ref,
+ int loc: @location ref);
+
+indexers(
+ unique int id: @indexer,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @indexer ref);
+
+indexer_location(
+ int id: @indexer ref,
+ int loc: @location ref);
+
+accessors(
+ unique int id: @accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_member_id: @member ref,
+ int unbound_id: @accessor ref);
+
+case @accessor.kind of
+ 1 = @getter
+| 2 = @setter
+ ;
+
+init_only_accessors(
+ unique int id: @accessor ref);
+
+accessor_location(
+ int id: @accessor ref,
+ int loc: @location ref);
+
+events(
+ unique int id: @event,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @event ref);
+
+event_location(
+ int id: @event ref,
+ int loc: @location ref);
+
+event_accessors(
+ unique int id: @event_accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_event_id: @event ref,
+ int unbound_id: @event_accessor ref);
+
+case @event_accessor.kind of
+ 1 = @add_event_accessor
+| 2 = @remove_event_accessor
+ ;
+
+event_accessor_location(
+ int id: @event_accessor ref,
+ int loc: @location ref);
+
+operators(
+ unique int id: @operator,
+ string name: string ref,
+ string symbol: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @operator ref);
+
+operator_location(
+ int id: @operator ref,
+ int loc: @location ref);
+
+constant_value(
+ int id: @variable ref,
+ string value: string ref);
+
+/** CALLABLES **/
+
+@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function;
+
+@callable_accessor = @accessor | @event_accessor;
+
+methods(
+ unique int id: @method,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @method ref);
+
+method_location(
+ int id: @method ref,
+ int loc: @location ref);
+
+constructors(
+ unique int id: @constructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @constructor ref);
+
+constructor_location(
+ int id: @constructor ref,
+ int loc: @location ref);
+
+destructors(
+ unique int id: @destructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @destructor ref);
+
+destructor_location(
+ int id: @destructor ref,
+ int loc: @location ref);
+
+overrides(
+ int id: @callable ref,
+ int base_id: @callable ref);
+
+explicitly_implements(
+ int id: @member ref,
+ int interface_id: @interface_or_ref ref);
+
+local_functions(
+ unique int id: @local_function,
+ string name: string ref,
+ int return_type: @type ref,
+ int unbound_id: @local_function ref);
+
+local_function_stmts(
+ unique int fn: @local_function_stmt ref,
+ int stmt: @local_function ref);
+
+/** VARIABLES **/
+
+@variable = @local_scope_variable | @field;
+
+@local_scope_variable = @local_variable | @parameter;
+
+fields(
+ unique int id: @field,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @field ref);
+
+case @field.kind of
+ 1 = @addressable_field
+| 2 = @constant
+ ;
+
+field_location(
+ int id: @field ref,
+ int loc: @location ref);
+
+localvars(
+ unique int id: @local_variable,
+ int kind: int ref,
+ string name: string ref,
+ int implicitly_typed: int ref /* 0 = no, 1 = yes */,
+ int type_id: @type_or_ref ref,
+ int parent_id: @local_var_decl_expr ref);
+
+case @local_variable.kind of
+ 1 = @addressable_local_variable
+| 2 = @local_constant
+| 3 = @local_variable_ref
+ ;
+
+localvar_location(
+ unique int id: @local_variable ref,
+ int loc: @location ref);
+
+@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type;
+
+#keyset[name, parent_id]
+#keyset[index, parent_id]
+params(
+ unique int id: @parameter,
+ string name: string ref,
+ int type_id: @type_or_ref ref,
+ int index: int ref,
+ int mode: int ref, /* value = 0, ref = 1, out = 2, params/array = 3, this = 4, in = 5, ref readonly = 6 */
+ int parent_id: @parameterizable ref,
+ int unbound_id: @parameter ref);
+
+param_location(
+ int id: @parameter ref,
+ int loc: @location ref);
+
+@has_scoped_annotation = @local_scope_variable
+
+scoped_annotation(
+ int id: @has_scoped_annotation ref,
+ int kind: int ref // scoped ref = 1, scoped value = 2
+ );
+
+/** STATEMENTS **/
+
+@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent;
+
+statements(
+ unique int id: @stmt,
+ int kind: int ref);
+
+#keyset[index, parent]
+stmt_parent(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_stmt_parent = @callable;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+stmt_parent_top_level(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @top_level_stmt_parent ref);
+
+case @stmt.kind of
+ 1 = @block_stmt
+| 2 = @expr_stmt
+| 3 = @if_stmt
+| 4 = @switch_stmt
+| 5 = @while_stmt
+| 6 = @do_stmt
+| 7 = @for_stmt
+| 8 = @foreach_stmt
+| 9 = @break_stmt
+| 10 = @continue_stmt
+| 11 = @goto_stmt
+| 12 = @goto_case_stmt
+| 13 = @goto_default_stmt
+| 14 = @throw_stmt
+| 15 = @return_stmt
+| 16 = @yield_stmt
+| 17 = @try_stmt
+| 18 = @checked_stmt
+| 19 = @unchecked_stmt
+| 20 = @lock_stmt
+| 21 = @using_block_stmt
+| 22 = @var_decl_stmt
+| 23 = @const_decl_stmt
+| 24 = @empty_stmt
+| 25 = @unsafe_stmt
+| 26 = @fixed_stmt
+| 27 = @label_stmt
+| 28 = @catch
+| 29 = @case_stmt
+| 30 = @local_function_stmt
+| 31 = @using_decl_stmt
+ ;
+
+@using_stmt = @using_block_stmt | @using_decl_stmt;
+
+@labeled_stmt = @label_stmt | @case;
+
+@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt;
+
+@cond_stmt = @if_stmt | @switch_stmt;
+
+@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt;
+
+@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt
+ | @yield_stmt;
+
+@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt;
+
+
+stmt_location(
+ unique int id: @stmt ref,
+ int loc: @location ref);
+
+catch_type(
+ unique int catch_id: @catch ref,
+ int type_id: @type_or_ref ref,
+ int kind: int ref /* explicit = 1, implicit = 2 */);
+
+foreach_stmt_info(
+ unique int id: @foreach_stmt ref,
+ int kind: int ref /* non-async = 1, async = 2 */);
+
+@foreach_symbol = @method | @property | @type_or_ref;
+
+#keyset[id, kind]
+foreach_stmt_desugar(
+ int id: @foreach_stmt ref,
+ int symbol: @foreach_symbol ref,
+ int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */);
+
+/** EXPRESSIONS **/
+
+expressions(
+ unique int id: @expr,
+ int kind: int ref,
+ int type_id: @type_or_ref ref);
+
+#keyset[index, parent]
+expr_parent(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif;
+
+@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+expr_parent_top_level(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @top_level_exprorstmt_parent ref);
+
+case @expr.kind of
+/* literal */
+ 1 = @bool_literal_expr
+| 2 = @char_literal_expr
+| 3 = @decimal_literal_expr
+| 4 = @int_literal_expr
+| 5 = @long_literal_expr
+| 6 = @uint_literal_expr
+| 7 = @ulong_literal_expr
+| 8 = @float_literal_expr
+| 9 = @double_literal_expr
+| 10 = @utf16_string_literal_expr
+| 11 = @null_literal_expr
+/* primary & unary */
+| 12 = @this_access_expr
+| 13 = @base_access_expr
+| 14 = @local_variable_access_expr
+| 15 = @parameter_access_expr
+| 16 = @field_access_expr
+| 17 = @property_access_expr
+| 18 = @method_access_expr
+| 19 = @event_access_expr
+| 20 = @indexer_access_expr
+| 21 = @array_access_expr
+| 22 = @type_access_expr
+| 23 = @typeof_expr
+| 24 = @method_invocation_expr
+| 25 = @delegate_invocation_expr
+| 26 = @operator_invocation_expr
+| 27 = @cast_expr
+| 28 = @object_creation_expr
+| 29 = @explicit_delegate_creation_expr
+| 30 = @implicit_delegate_creation_expr
+| 31 = @array_creation_expr
+| 32 = @default_expr
+| 33 = @plus_expr
+| 34 = @minus_expr
+| 35 = @bit_not_expr
+| 36 = @log_not_expr
+| 37 = @post_incr_expr
+| 38 = @post_decr_expr
+| 39 = @pre_incr_expr
+| 40 = @pre_decr_expr
+/* multiplicative */
+| 41 = @mul_expr
+| 42 = @div_expr
+| 43 = @rem_expr
+/* additive */
+| 44 = @add_expr
+| 45 = @sub_expr
+/* shift */
+| 46 = @lshift_expr
+| 47 = @rshift_expr
+/* relational */
+| 48 = @lt_expr
+| 49 = @gt_expr
+| 50 = @le_expr
+| 51 = @ge_expr
+/* equality */
+| 52 = @eq_expr
+| 53 = @ne_expr
+/* logical */
+| 54 = @bit_and_expr
+| 55 = @bit_xor_expr
+| 56 = @bit_or_expr
+| 57 = @log_and_expr
+| 58 = @log_or_expr
+/* type testing */
+| 59 = @is_expr
+| 60 = @as_expr
+/* null coalescing */
+| 61 = @null_coalescing_expr
+/* conditional */
+| 62 = @conditional_expr
+/* assignment */
+| 63 = @simple_assign_expr
+| 64 = @assign_add_expr
+| 65 = @assign_sub_expr
+| 66 = @assign_mul_expr
+| 67 = @assign_div_expr
+| 68 = @assign_rem_expr
+| 69 = @assign_and_expr
+| 70 = @assign_xor_expr
+| 71 = @assign_or_expr
+| 72 = @assign_lshift_expr
+| 73 = @assign_rshift_expr
+/* more */
+| 74 = @object_init_expr
+| 75 = @collection_init_expr
+| 76 = @array_init_expr
+| 77 = @checked_expr
+| 78 = @unchecked_expr
+| 79 = @constructor_init_expr
+| 80 = @add_event_expr
+| 81 = @remove_event_expr
+| 82 = @par_expr
+| 83 = @local_var_decl_expr
+| 84 = @lambda_expr
+| 85 = @anonymous_method_expr
+| 86 = @namespace_expr
+/* dynamic */
+| 92 = @dynamic_element_access_expr
+| 93 = @dynamic_member_access_expr
+/* unsafe */
+| 100 = @pointer_indirection_expr
+| 101 = @address_of_expr
+| 102 = @sizeof_expr
+/* async */
+| 103 = @await_expr
+/* C# 6.0 */
+| 104 = @nameof_expr
+| 105 = @interpolated_string_expr
+| 106 = @unknown_expr
+/* C# 7.0 */
+| 107 = @throw_expr
+| 108 = @tuple_expr
+| 109 = @local_function_invocation_expr
+| 110 = @ref_expr
+| 111 = @discard_expr
+/* C# 8.0 */
+| 112 = @range_expr
+| 113 = @index_expr
+| 114 = @switch_expr
+| 115 = @recursive_pattern_expr
+| 116 = @property_pattern_expr
+| 117 = @positional_pattern_expr
+| 118 = @switch_case_expr
+| 119 = @assign_coalesce_expr
+| 120 = @suppress_nullable_warning_expr
+| 121 = @namespace_access_expr
+/* C# 9.0 */
+| 122 = @lt_pattern_expr
+| 123 = @gt_pattern_expr
+| 124 = @le_pattern_expr
+| 125 = @ge_pattern_expr
+| 126 = @not_pattern_expr
+| 127 = @and_pattern_expr
+| 128 = @or_pattern_expr
+| 129 = @function_pointer_invocation_expr
+| 130 = @with_expr
+/* C# 11.0 */
+| 131 = @list_pattern_expr
+| 132 = @slice_pattern_expr
+| 133 = @urshift_expr
+| 134 = @assign_urshift_expr
+| 135 = @utf8_string_literal_expr
+/* C# 12.0 */
+| 136 = @collection_expr
+| 137 = @spread_element_expr
+/* Preprocessor */
+| 999 = @define_symbol_expr
+;
+
+@switch = @switch_stmt | @switch_expr;
+@case = @case_stmt | @switch_case_expr;
+@pattern_match = @case | @is_expr;
+@unary_pattern_expr = @not_pattern_expr;
+@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr;
+@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr;
+
+@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr;
+@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr;
+@string_literal_expr = @utf16_string_literal_expr | @utf8_string_literal_expr;
+@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr
+ | @string_literal_expr | @null_literal_expr;
+
+@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr;
+@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr;
+@assign_event_expr = @add_event_expr | @remove_event_expr;
+
+@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr
+ | @assign_rem_expr
+@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr
+ | @assign_lshift_expr | @assign_rshift_expr | @assign_urshift_expr;
+
+@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr
+ | @method_access_expr | @type_access_expr | @dynamic_member_access_expr;
+@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr;
+@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr;
+
+@local_variable_access = @local_variable_access_expr | @local_var_decl_expr;
+@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access;
+@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr;
+
+@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr
+ | @event_access_expr | @dynamic_member_access_expr;
+
+@objectorcollection_init_expr = @object_init_expr | @collection_init_expr;
+
+@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr;
+
+@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
+@incr_op_expr = @pre_incr_expr | @post_incr_expr;
+@decr_op_expr = @pre_decr_expr | @post_decr_expr;
+@mut_op_expr = @incr_op_expr | @decr_op_expr;
+@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr;
+@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr;
+
+@ternary_log_op_expr = @conditional_expr;
+@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr;
+@un_log_op_expr = @log_not_expr;
+@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr;
+
+@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
+ | @rshift_expr | @urshift_expr;
+@un_bit_op_expr = @bit_not_expr;
+@bit_expr = @un_bit_op_expr | @bin_bit_op_expr;
+
+@equality_op_expr = @eq_expr | @ne_expr;
+@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr;
+@comp_expr = @equality_op_expr | @rel_op_expr;
+
+@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op;
+
+@ternary_op = @ternary_log_op_expr;
+@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr;
+@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr
+ | @pointer_indirection_expr | @address_of_expr;
+
+@anonymous_function_expr = @lambda_expr | @anonymous_method_expr;
+
+@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr
+ | @delegate_invocation_expr | @object_creation_expr | @call_access_expr
+ | @local_function_invocation_expr | @function_pointer_invocation_expr;
+
+@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr;
+
+@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr
+ | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr;
+
+@throw_element = @throw_expr | @throw_stmt;
+
+@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr;
+
+implicitly_typed_array_creation(
+ unique int id: @array_creation_expr ref);
+
+explicitly_sized_array_creation(
+ unique int id: @array_creation_expr ref);
+
+stackalloc_array_creation(
+ unique int id: @array_creation_expr ref);
+
+implicitly_typed_object_creation(
+ unique int id: @implicitly_typeable_object_creation_expr ref);
+
+mutator_invocation_mode(
+ unique int id: @operator_invocation_expr ref,
+ int mode: int ref /* prefix = 1, postfix = 2*/);
+
+expr_value(
+ unique int id: @expr ref,
+ string value: string ref);
+
+expr_call(
+ unique int caller_id: @expr ref,
+ int target_id: @callable ref);
+
+expr_access(
+ unique int accesser_id: @access_expr ref,
+ int target_id: @accessible ref);
+
+@accessible = @method | @assignable | @local_function | @namespace;
+
+expr_location(
+ unique int id: @expr ref,
+ int loc: @location ref);
+
+dynamic_member_name(
+ unique int id: @late_bindable_expr ref,
+ string name: string ref);
+
+@qualifiable_expr = @member_access_expr
+ | @method_invocation_expr
+ | @element_access_expr;
+
+conditional_access(
+ unique int id: @qualifiable_expr ref);
+
+expr_argument(
+ unique int id: @expr ref,
+ int mode: int ref);
+ /* mode is the same as params: value = 0, ref = 1, out = 2 */
+
+expr_argument_name(
+ unique int id: @expr ref,
+ string name: string ref);
+
+lambda_expr_return_type(
+ unique int id: @lambda_expr ref,
+ int type_id: @type_or_ref ref);
+
+/* Compiler generated */
+
+compiler_generated(unique int id: @element ref);
+
+/** CONTROL/DATA FLOW **/
+
+@control_flow_element = @stmt | @expr;
+
+/* XML Files */
+
+xmlEncoding (
+ unique int id: @file ref,
+ string encoding: string ref);
+
+xmlDTDs(
+ unique int id: @xmldtd,
+ string root: string ref,
+ string publicId: string ref,
+ string systemId: string ref,
+ int fileid: @file ref);
+
+xmlElements(
+ unique int id: @xmlelement,
+ string name: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlAttrs(
+ unique int id: @xmlattribute,
+ int elementid: @xmlelement ref,
+ string name: string ref,
+ string value: string ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlNs(
+ int id: @xmlnamespace,
+ string prefixName: string ref,
+ string URI: string ref,
+ int fileid: @file ref);
+
+xmlHasNs(
+ int elementId: @xmlnamespaceable ref,
+ int nsId: @xmlnamespace ref,
+ int fileid: @file ref);
+
+xmlComments(
+ unique int id: @xmlcomment,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int fileid: @file ref);
+
+xmlChars(
+ unique int id: @xmlcharacters,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int isCDATA: int ref,
+ int fileid: @file ref);
+
+@xmlparent = @file | @xmlelement;
+@xmlnamespaceable = @xmlelement | @xmlattribute;
+
+xmllocations(
+ int xmlElement: @xmllocatable ref,
+ int location: @location_default ref);
+
+@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
+
+/* Comments */
+
+commentline(
+ unique int id: @commentline,
+ int kind: int ref,
+ string text: string ref,
+ string rawtext: string ref);
+
+case @commentline.kind of
+ 0 = @singlelinecomment
+| 1 = @xmldoccomment
+| 2 = @multilinecomment;
+
+commentline_location(
+ unique int id: @commentline ref,
+ int loc: @location ref);
+
+commentblock(
+ unique int id : @commentblock);
+
+commentblock_location(
+ unique int id: @commentblock ref,
+ int loc: @location ref);
+
+commentblock_binding(
+ int id: @commentblock ref,
+ int entity: @element ref,
+ int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */
+
+commentblock_child(
+ int id: @commentblock ref,
+ int commentline: @commentline ref,
+ int index: int ref);
+
+/* ASP.NET */
+
+case @asp_element.kind of
+ 0=@asp_close_tag
+| 1=@asp_code
+| 2=@asp_comment
+| 3=@asp_data_binding
+| 4=@asp_directive
+| 5=@asp_open_tag
+| 6=@asp_quoted_string
+| 7=@asp_text
+| 8=@asp_xml_directive;
+
+@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string;
+
+asp_elements(
+ unique int id: @asp_element,
+ int kind: int ref,
+ int loc: @location ref);
+
+asp_comment_server(unique int comment: @asp_comment ref);
+asp_code_inline(unique int code: @asp_code ref);
+asp_directive_attribute(
+ int directive: @asp_directive ref,
+ int index: int ref,
+ string name: string ref,
+ int value: @asp_quoted_string ref);
+asp_directive_name(
+ unique int directive: @asp_directive ref,
+ string name: string ref);
+asp_element_body(
+ unique int element: @asp_element ref,
+ string body: string ref);
+asp_tag_attribute(
+ int tag: @asp_open_tag ref,
+ int index: int ref,
+ string name: string ref,
+ int attribute: @asp_attribute ref);
+asp_tag_name(
+ unique int tag: @asp_open_tag ref,
+ string name: string ref);
+asp_tag_isempty(int tag: @asp_open_tag ref);
diff --git a/csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/semmlecode.csharp.dbscheme b/csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/semmlecode.csharp.dbscheme
new file mode 100644
index 000000000000..66044cfa5bbf
--- /dev/null
+++ b/csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/semmlecode.csharp.dbscheme
@@ -0,0 +1,1460 @@
+/* This is a dummy line to alter the dbscheme, so we can make a database upgrade
+ * without actually changing any of the dbscheme predicates. It contains a date
+ * to allow for such updates in the future as well.
+ *
+ * 2021-07-14
+ *
+ * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a
+ * previously seen state (matching a previously seen SHA), which would make the upgrade
+ * mechanism not work properly.
+ */
+
+/**
+ * An invocation of the compiler. Note that more than one file may be
+ * compiled per invocation. For example, this command compiles three
+ * source files:
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * The `id` simply identifies the invocation, while `cwd` is the working
+ * directory from which the compiler was invoked.
+ */
+compilations(
+ unique int id : @compilation,
+ string cwd : string ref
+);
+
+compilation_info(
+ int id : @compilation ref,
+ string info_key: string ref,
+ string info_value: string ref
+)
+
+/**
+ * The arguments that were passed to the extractor for a compiler
+ * invocation. If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then typically there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | --compiler
+ * 1 | *path to compiler*
+ * 2 | f1.cs
+ * 3 | f2.cs
+ * 4 | f3.cs
+ */
+#keyset[id, num]
+compilation_args(
+ int id : @compilation ref,
+ int num : int ref,
+ string arg : string ref
+);
+
+/**
+ * The expanded arguments that were passed to the extractor for a
+ * compiler invocation. This is similar to `compilation_args`, but
+ * for a `@someFile.rsp` argument, it includes the arguments from that
+ * file, rather than just taking the argument literally.
+ */
+#keyset[id, num]
+compilation_expanded_args(
+ int id : @compilation ref,
+ int num : int ref,
+ string arg : string ref
+);
+
+/**
+ * The source files that are compiled by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | f1.cs
+ * 1 | f2.cs
+ * 2 | f3.cs
+ */
+#keyset[id, num]
+compilation_compiling_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The references used by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | ref1.dll
+ * 1 | ref2.dll
+ * 2 | ref3.dll
+ */
+#keyset[id, num]
+compilation_referencing_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The time taken by the extractor for a compiler invocation.
+ *
+ * For each file `num`, there will be rows for
+ *
+ * kind | seconds
+ * ---- | ---
+ * 1 | CPU seconds used by the extractor frontend
+ * 2 | Elapsed seconds during the extractor frontend
+ * 3 | CPU seconds used by the extractor backend
+ * 4 | Elapsed seconds during the extractor backend
+ */
+#keyset[id, num, kind]
+compilation_time(
+ int id : @compilation ref,
+ int num : int ref,
+ /* kind:
+ 1 = frontend_cpu_seconds
+ 2 = frontend_elapsed_seconds
+ 3 = extractor_cpu_seconds
+ 4 = extractor_elapsed_seconds
+ */
+ int kind : int ref,
+ float seconds : float ref
+);
+
+/**
+ * An error or warning generated by the extractor.
+ * The diagnostic message `diagnostic` was generated during compiler
+ * invocation `compilation`, and is the `file_number_diagnostic_number`th
+ * message generated while extracting the `file_number`th file of that
+ * invocation.
+ */
+#keyset[compilation, file_number, file_number_diagnostic_number]
+diagnostic_for(
+ unique int diagnostic : @diagnostic ref,
+ int compilation : @compilation ref,
+ int file_number : int ref,
+ int file_number_diagnostic_number : int ref
+);
+
+diagnostics(
+ unique int id: @diagnostic,
+ int severity: int ref,
+ string error_tag: string ref,
+ string error_message: string ref,
+ string full_error_message: string ref,
+ int location: @location ref
+);
+
+extractor_messages(
+ unique int id: @extractor_message,
+ int severity: int ref,
+ string origin : string ref,
+ string text : string ref,
+ string entity : string ref,
+ int location: @location ref,
+ string stack_trace : string ref
+);
+
+/**
+ * If extraction was successful, then `cpu_seconds` and
+ * `elapsed_seconds` are the CPU time and elapsed time (respectively)
+ * that extraction took for compiler invocation `id`.
+ */
+compilation_finished(
+ unique int id : @compilation ref,
+ float cpu_seconds : float ref,
+ float elapsed_seconds : float ref
+);
+
+compilation_assembly(
+ unique int id : @compilation ref,
+ int assembly: @assembly ref
+)
+
+// Populated by the CSV extractor
+externalData(
+ int id: @externalDataElement,
+ string path: string ref,
+ int column: int ref,
+ string value: string ref);
+
+sourceLocationPrefix(
+ string prefix: string ref);
+
+/*
+ * C# dbscheme
+ */
+
+/** ELEMENTS **/
+
+@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration
+ | @using_directive | @type_parameter_constraints | @externalDataElement
+ | @xmllocatable | @asp_element | @namespace | @preprocessor_directive;
+
+@declaration = @callable | @generic | @assignable | @namespace;
+
+@named_element = @namespace | @declaration;
+
+@declaration_with_accessors = @property | @indexer | @event;
+
+@assignable = @variable | @assignable_with_accessors | @event;
+
+@assignable_with_accessors = @property | @indexer;
+
+@attributable = @assembly | @field | @parameter | @operator | @method | @constructor
+ | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors
+ | @local_function | @lambda_expr;
+
+/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/
+
+@location = @location_default | @assembly;
+
+locations_default(
+ unique int id: @location_default,
+ int file: @file ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+locations_mapped(
+ unique int id: @location_default ref,
+ int mapped_to: @location_default ref);
+
+@sourceline = @file | @callable | @xmllocatable;
+
+numlines(
+ int element_id: @sourceline ref,
+ int num_lines: int ref,
+ int num_code: int ref,
+ int num_comment: int ref);
+
+assemblies(
+ unique int id: @assembly,
+ int file: @file ref,
+ string fullname: string ref,
+ string name: string ref,
+ string version: string ref);
+
+files(
+ unique int id: @file,
+ string name: string ref);
+
+folders(
+ unique int id: @folder,
+ string name: string ref);
+
+@container = @folder | @file ;
+
+containerparent(
+ int parent: @container ref,
+ unique int child: @container ref);
+
+file_extraction_mode(
+ unique int file: @file ref,
+ int mode: int ref
+ /* 0 = normal, 1 = standalone extractor */
+ );
+
+/** NAMESPACES **/
+
+@type_container = @namespace | @type;
+
+namespaces(
+ unique int id: @namespace,
+ string name: string ref);
+
+namespace_declarations(
+ unique int id: @namespace_declaration,
+ int namespace_id: @namespace ref);
+
+namespace_declaration_location(
+ unique int id: @namespace_declaration ref,
+ int loc: @location ref);
+
+parent_namespace(
+ unique int child_id: @type_container ref,
+ int namespace_id: @namespace ref);
+
+@declaration_or_directive = @namespace_declaration | @type | @using_directive;
+
+parent_namespace_declaration(
+ int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes
+ int namespace_id: @namespace_declaration ref);
+
+@using_directive = @using_namespace_directive | @using_static_directive;
+
+using_global(
+ unique int id: @using_directive ref
+);
+
+using_namespace_directives(
+ unique int id: @using_namespace_directive,
+ int namespace_id: @namespace ref);
+
+using_static_directives(
+ unique int id: @using_static_directive,
+ int type_id: @type_or_ref ref);
+
+using_directive_location(
+ unique int id: @using_directive ref,
+ int loc: @location ref);
+
+@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning
+ | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if
+ | @directive_elif | @directive_else | @directive_endif;
+
+@conditional_directive = @directive_if | @directive_elif;
+@branch_directive = @directive_if | @directive_elif | @directive_else;
+
+directive_ifs(
+ unique int id: @directive_if,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref); /* 0: false, 1: true */
+
+directive_elifs(
+ unique int id: @directive_elif,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+directive_elses(
+ unique int id: @directive_else,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+#keyset[id, start]
+directive_endifs(
+ unique int id: @directive_endif,
+ unique int start: @directive_if ref);
+
+directive_define_symbols(
+ unique int id: @define_symbol_expr ref,
+ string name: string ref);
+
+directive_regions(
+ unique int id: @directive_region,
+ string name: string ref);
+
+#keyset[id, start]
+directive_endregions(
+ unique int id: @directive_endregion,
+ unique int start: @directive_region ref);
+
+directive_lines(
+ unique int id: @directive_line,
+ int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */
+
+directive_line_value(
+ unique int id: @directive_line ref,
+ int line: int ref);
+
+directive_line_file(
+ unique int id: @directive_line ref,
+ int file: @file ref);
+
+directive_line_offset(
+ unique int id: @directive_line ref,
+ int offset: int ref);
+
+directive_line_span(
+ unique int id: @directive_line ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+directive_nullables(
+ unique int id: @directive_nullable,
+ int setting: int ref, /* 0: disable, 1: enable, 2: restore */
+ int target: int ref); /* 0: none, 1: annotations, 2: warnings */
+
+directive_warnings(
+ unique int id: @directive_warning,
+ string message: string ref);
+
+directive_errors(
+ unique int id: @directive_error,
+ string message: string ref);
+
+directive_undefines(
+ unique int id: @directive_undefine,
+ string name: string ref);
+
+directive_defines(
+ unique int id: @directive_define,
+ string name: string ref);
+
+pragma_checksums(
+ unique int id: @pragma_checksum,
+ int file: @file ref,
+ string guid: string ref,
+ string bytes: string ref);
+
+pragma_warnings(
+ unique int id: @pragma_warning,
+ int kind: int ref /* 0 = disable, 1 = restore */);
+
+#keyset[id, index]
+pragma_warning_error_codes(
+ int id: @pragma_warning ref,
+ string errorCode: string ref,
+ int index: int ref);
+
+preprocessor_directive_location(
+ unique int id: @preprocessor_directive ref,
+ int loc: @location ref);
+
+preprocessor_directive_compilation(
+ int id: @preprocessor_directive ref,
+ int compilation: @compilation ref);
+
+preprocessor_directive_active(
+ unique int id: @preprocessor_directive ref,
+ int active: int ref); /* 0: false, 1: true */
+
+/** TYPES **/
+
+types(
+ unique int id: @type,
+ int kind: int ref,
+ string name: string ref);
+
+case @type.kind of
+ 1 = @bool_type
+| 2 = @char_type
+| 3 = @decimal_type
+| 4 = @sbyte_type
+| 5 = @short_type
+| 6 = @int_type
+| 7 = @long_type
+| 8 = @byte_type
+| 9 = @ushort_type
+| 10 = @uint_type
+| 11 = @ulong_type
+| 12 = @float_type
+| 13 = @double_type
+| 14 = @enum_type
+| 15 = @struct_type
+| 17 = @class_type
+| 19 = @interface_type
+| 20 = @delegate_type
+| 21 = @null_type
+| 22 = @type_parameter
+| 23 = @pointer_type
+| 24 = @nullable_type
+| 25 = @array_type
+| 26 = @void_type
+| 27 = @int_ptr_type
+| 28 = @uint_ptr_type
+| 29 = @dynamic_type
+| 30 = @arglist_type
+| 31 = @unknown_type
+| 32 = @tuple_type
+| 33 = @function_pointer_type
+| 34 = @inline_array_type
+ ;
+
+@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type;
+@integral_type = @signed_integral_type | @unsigned_integral_type;
+@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type;
+@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type;
+@floating_point_type = @float_type | @double_type;
+@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type
+ | @uint_ptr_type | @tuple_type | @void_type | @inline_array_type;
+@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type
+ | @dynamic_type;
+@value_or_ref_type = @value_type | @ref_type;
+
+typerefs(
+ unique int id: @typeref,
+ string name: string ref);
+
+typeref_type(
+ int id: @typeref ref,
+ unique int typeId: @type ref);
+
+@type_or_ref = @type | @typeref;
+
+array_element_type(
+ unique int array: @array_type ref,
+ int dimension: int ref,
+ int rank: int ref,
+ int element: @type_or_ref ref);
+
+nullable_underlying_type(
+ unique int nullable: @nullable_type ref,
+ int underlying: @type_or_ref ref);
+
+pointer_referent_type(
+ unique int pointer: @pointer_type ref,
+ int referent: @type_or_ref ref);
+
+enum_underlying_type(
+ unique int enum_id: @enum_type ref,
+ int underlying_type_id: @type_or_ref ref);
+
+delegate_return_type(
+ unique int delegate_id: @delegate_type ref,
+ int return_type_id: @type_or_ref ref);
+
+function_pointer_return_type(
+ unique int function_pointer_id: @function_pointer_type ref,
+ int return_type_id: @type_or_ref ref);
+
+extend(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+anonymous_types(
+ unique int id: @type ref);
+
+@interface_or_ref = @interface_type | @typeref;
+
+implement(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+type_location(
+ int id: @type ref,
+ int loc: @location ref);
+
+tuple_underlying_type(
+ unique int tuple: @tuple_type ref,
+ int struct: @type_or_ref ref);
+
+#keyset[tuple, index]
+tuple_element(
+ int tuple: @tuple_type ref,
+ int index: int ref,
+ unique int field: @field ref);
+
+attributes(
+ unique int id: @attribute,
+ int kind: int ref,
+ int type_id: @type_or_ref ref,
+ int target: @attributable ref);
+
+case @attribute.kind of
+ 0 = @attribute_default
+| 1 = @attribute_return
+| 2 = @attribute_assembly
+| 3 = @attribute_module
+;
+
+attribute_location(
+ int id: @attribute ref,
+ int loc: @location ref);
+
+@type_mention_parent = @element | @type_mention;
+
+type_mention(
+ unique int id: @type_mention,
+ int type_id: @type_or_ref ref,
+ int parent: @type_mention_parent ref);
+
+type_mention_location(
+ unique int id: @type_mention ref,
+ int loc: @location ref);
+
+@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type;
+
+/**
+ * A direct annotation on an entity, for example `string? x;`.
+ *
+ * Annotations:
+ * 2 = reftype is not annotated "!"
+ * 3 = reftype is annotated "?"
+ * 4 = readonly ref type / in parameter
+ * 5 = ref type parameter, return or local variable
+ * 6 = out parameter
+ *
+ * Note that the annotation depends on the element it annotates.
+ * @assignable: The annotation is on the type of the assignable, for example the variable type.
+ * @type_parameter: The annotation is on the reftype constraint
+ * @callable: The annotation is on the return type
+ * @array_type: The annotation is on the element type
+ */
+type_annotation(int id: @has_type_annotation ref, int annotation: int ref);
+
+nullability(unique int nullability: @nullability, int kind: int ref);
+
+case @nullability.kind of
+ 0 = @oblivious
+| 1 = @not_annotated
+| 2 = @annotated
+;
+
+#keyset[parent, index]
+nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref)
+
+type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref);
+
+/**
+ * The nullable flow state of an expression, as determined by Roslyn.
+ * 0 = none (default, not populated)
+ * 1 = not null
+ * 2 = maybe null
+ */
+expr_flowstate(unique int id: @expr ref, int state: int ref);
+
+/** GENERICS **/
+
+@generic = @type | @method | @local_function;
+
+type_parameters(
+ unique int id: @type_parameter ref,
+ int index: int ref,
+ int generic_id: @generic ref,
+ int variance: int ref /* none = 0, out = 1, in = 2 */);
+
+#keyset[constructed_id, index]
+type_arguments(
+ int id: @type_or_ref ref,
+ int index: int ref,
+ int constructed_id: @generic_or_ref ref);
+
+@generic_or_ref = @generic | @typeref;
+
+constructed_generic(
+ unique int constructed: @generic ref,
+ int generic: @generic_or_ref ref);
+
+type_parameter_constraints(
+ unique int id: @type_parameter_constraints,
+ int param_id: @type_parameter ref);
+
+type_parameter_constraints_location(
+ int id: @type_parameter_constraints ref,
+ int loc: @location ref);
+
+general_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int kind: int ref /* class = 1, struct = 2, new = 3 */);
+
+specific_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref);
+
+specific_type_parameter_nullability(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref,
+ int nullability: @nullability ref);
+
+/** FUNCTION POINTERS */
+
+function_pointer_calling_conventions(
+ int id: @function_pointer_type ref,
+ int kind: int ref);
+
+#keyset[id, index]
+has_unmanaged_calling_conventions(
+ int id: @function_pointer_type ref,
+ int index: int ref,
+ int conv_id: @type_or_ref ref);
+
+/** MODIFIERS */
+
+@modifiable = @modifiable_direct | @event_accessor;
+
+@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr;
+
+modifiers(
+ unique int id: @modifier,
+ string name: string ref);
+
+has_modifiers(
+ int id: @modifiable_direct ref,
+ int mod_id: @modifier ref);
+
+/** MEMBERS **/
+
+@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type;
+
+@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr;
+
+@virtualizable = @method | @property | @indexer | @event | @operator;
+
+exprorstmt_name(
+ unique int parent_id: @named_exprorstmt ref,
+ string name: string ref);
+
+nested_types(
+ unique int id: @type ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @type ref);
+
+properties(
+ unique int id: @property,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @property ref);
+
+property_location(
+ int id: @property ref,
+ int loc: @location ref);
+
+indexers(
+ unique int id: @indexer,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @indexer ref);
+
+indexer_location(
+ int id: @indexer ref,
+ int loc: @location ref);
+
+accessors(
+ unique int id: @accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_member_id: @member ref,
+ int unbound_id: @accessor ref);
+
+case @accessor.kind of
+ 1 = @getter
+| 2 = @setter
+ ;
+
+init_only_accessors(
+ unique int id: @accessor ref);
+
+accessor_location(
+ int id: @accessor ref,
+ int loc: @location ref);
+
+events(
+ unique int id: @event,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @event ref);
+
+event_location(
+ int id: @event ref,
+ int loc: @location ref);
+
+event_accessors(
+ unique int id: @event_accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_event_id: @event ref,
+ int unbound_id: @event_accessor ref);
+
+case @event_accessor.kind of
+ 1 = @add_event_accessor
+| 2 = @remove_event_accessor
+ ;
+
+event_accessor_location(
+ int id: @event_accessor ref,
+ int loc: @location ref);
+
+operators(
+ unique int id: @operator,
+ string name: string ref,
+ string symbol: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @operator ref);
+
+operator_location(
+ int id: @operator ref,
+ int loc: @location ref);
+
+constant_value(
+ int id: @variable ref,
+ string value: string ref);
+
+/** CALLABLES **/
+
+@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function;
+
+@callable_accessor = @accessor | @event_accessor;
+
+methods(
+ unique int id: @method,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @method ref);
+
+method_location(
+ int id: @method ref,
+ int loc: @location ref);
+
+constructors(
+ unique int id: @constructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @constructor ref);
+
+constructor_location(
+ int id: @constructor ref,
+ int loc: @location ref);
+
+destructors(
+ unique int id: @destructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @destructor ref);
+
+destructor_location(
+ int id: @destructor ref,
+ int loc: @location ref);
+
+overrides(
+ int id: @callable ref,
+ int base_id: @callable ref);
+
+explicitly_implements(
+ int id: @member ref,
+ int interface_id: @interface_or_ref ref);
+
+local_functions(
+ unique int id: @local_function,
+ string name: string ref,
+ int return_type: @type ref,
+ int unbound_id: @local_function ref);
+
+local_function_stmts(
+ unique int fn: @local_function_stmt ref,
+ int stmt: @local_function ref);
+
+/** VARIABLES **/
+
+@variable = @local_scope_variable | @field;
+
+@local_scope_variable = @local_variable | @parameter;
+
+fields(
+ unique int id: @field,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @field ref);
+
+case @field.kind of
+ 1 = @addressable_field
+| 2 = @constant
+ ;
+
+field_location(
+ int id: @field ref,
+ int loc: @location ref);
+
+localvars(
+ unique int id: @local_variable,
+ int kind: int ref,
+ string name: string ref,
+ int implicitly_typed: int ref /* 0 = no, 1 = yes */,
+ int type_id: @type_or_ref ref,
+ int parent_id: @local_var_decl_expr ref);
+
+case @local_variable.kind of
+ 1 = @addressable_local_variable
+| 2 = @local_constant
+| 3 = @local_variable_ref
+ ;
+
+localvar_location(
+ unique int id: @local_variable ref,
+ int loc: @location ref);
+
+@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type;
+
+#keyset[name, parent_id]
+#keyset[index, parent_id]
+params(
+ unique int id: @parameter,
+ string name: string ref,
+ int type_id: @type_or_ref ref,
+ int index: int ref,
+ int mode: int ref, /* value = 0, ref = 1, out = 2, params/array = 3, this = 4, in = 5, ref readonly = 6 */
+ int parent_id: @parameterizable ref,
+ int unbound_id: @parameter ref);
+
+param_location(
+ int id: @parameter ref,
+ int loc: @location ref);
+
+@has_scoped_annotation = @local_scope_variable
+
+scoped_annotation(
+ int id: @has_scoped_annotation ref,
+ int kind: int ref // scoped ref = 1, scoped value = 2
+ );
+
+/** STATEMENTS **/
+
+@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent;
+
+statements(
+ unique int id: @stmt,
+ int kind: int ref);
+
+#keyset[index, parent]
+stmt_parent(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_stmt_parent = @callable;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+stmt_parent_top_level(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @top_level_stmt_parent ref);
+
+case @stmt.kind of
+ 1 = @block_stmt
+| 2 = @expr_stmt
+| 3 = @if_stmt
+| 4 = @switch_stmt
+| 5 = @while_stmt
+| 6 = @do_stmt
+| 7 = @for_stmt
+| 8 = @foreach_stmt
+| 9 = @break_stmt
+| 10 = @continue_stmt
+| 11 = @goto_stmt
+| 12 = @goto_case_stmt
+| 13 = @goto_default_stmt
+| 14 = @throw_stmt
+| 15 = @return_stmt
+| 16 = @yield_stmt
+| 17 = @try_stmt
+| 18 = @checked_stmt
+| 19 = @unchecked_stmt
+| 20 = @lock_stmt
+| 21 = @using_block_stmt
+| 22 = @var_decl_stmt
+| 23 = @const_decl_stmt
+| 24 = @empty_stmt
+| 25 = @unsafe_stmt
+| 26 = @fixed_stmt
+| 27 = @label_stmt
+| 28 = @catch
+| 29 = @case_stmt
+| 30 = @local_function_stmt
+| 31 = @using_decl_stmt
+ ;
+
+@using_stmt = @using_block_stmt | @using_decl_stmt;
+
+@labeled_stmt = @label_stmt | @case;
+
+@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt;
+
+@cond_stmt = @if_stmt | @switch_stmt;
+
+@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt;
+
+@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt
+ | @yield_stmt;
+
+@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt;
+
+
+stmt_location(
+ unique int id: @stmt ref,
+ int loc: @location ref);
+
+catch_type(
+ unique int catch_id: @catch ref,
+ int type_id: @type_or_ref ref,
+ int kind: int ref /* explicit = 1, implicit = 2 */);
+
+foreach_stmt_info(
+ unique int id: @foreach_stmt ref,
+ int kind: int ref /* non-async = 1, async = 2 */);
+
+@foreach_symbol = @method | @property | @type_or_ref;
+
+#keyset[id, kind]
+foreach_stmt_desugar(
+ int id: @foreach_stmt ref,
+ int symbol: @foreach_symbol ref,
+ int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */);
+
+/** EXPRESSIONS **/
+
+expressions(
+ unique int id: @expr,
+ int kind: int ref,
+ int type_id: @type_or_ref ref);
+
+#keyset[index, parent]
+expr_parent(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif;
+
+@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+expr_parent_top_level(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @top_level_exprorstmt_parent ref);
+
+case @expr.kind of
+/* literal */
+ 1 = @bool_literal_expr
+| 2 = @char_literal_expr
+| 3 = @decimal_literal_expr
+| 4 = @int_literal_expr
+| 5 = @long_literal_expr
+| 6 = @uint_literal_expr
+| 7 = @ulong_literal_expr
+| 8 = @float_literal_expr
+| 9 = @double_literal_expr
+| 10 = @utf16_string_literal_expr
+| 11 = @null_literal_expr
+/* primary & unary */
+| 12 = @this_access_expr
+| 13 = @base_access_expr
+| 14 = @local_variable_access_expr
+| 15 = @parameter_access_expr
+| 16 = @field_access_expr
+| 17 = @property_access_expr
+| 18 = @method_access_expr
+| 19 = @event_access_expr
+| 20 = @indexer_access_expr
+| 21 = @array_access_expr
+| 22 = @type_access_expr
+| 23 = @typeof_expr
+| 24 = @method_invocation_expr
+| 25 = @delegate_invocation_expr
+| 26 = @operator_invocation_expr
+| 27 = @cast_expr
+| 28 = @object_creation_expr
+| 29 = @explicit_delegate_creation_expr
+| 30 = @implicit_delegate_creation_expr
+| 31 = @array_creation_expr
+| 32 = @default_expr
+| 33 = @plus_expr
+| 34 = @minus_expr
+| 35 = @bit_not_expr
+| 36 = @log_not_expr
+| 37 = @post_incr_expr
+| 38 = @post_decr_expr
+| 39 = @pre_incr_expr
+| 40 = @pre_decr_expr
+/* multiplicative */
+| 41 = @mul_expr
+| 42 = @div_expr
+| 43 = @rem_expr
+/* additive */
+| 44 = @add_expr
+| 45 = @sub_expr
+/* shift */
+| 46 = @lshift_expr
+| 47 = @rshift_expr
+/* relational */
+| 48 = @lt_expr
+| 49 = @gt_expr
+| 50 = @le_expr
+| 51 = @ge_expr
+/* equality */
+| 52 = @eq_expr
+| 53 = @ne_expr
+/* logical */
+| 54 = @bit_and_expr
+| 55 = @bit_xor_expr
+| 56 = @bit_or_expr
+| 57 = @log_and_expr
+| 58 = @log_or_expr
+/* type testing */
+| 59 = @is_expr
+| 60 = @as_expr
+/* null coalescing */
+| 61 = @null_coalescing_expr
+/* conditional */
+| 62 = @conditional_expr
+/* assignment */
+| 63 = @simple_assign_expr
+| 64 = @assign_add_expr
+| 65 = @assign_sub_expr
+| 66 = @assign_mul_expr
+| 67 = @assign_div_expr
+| 68 = @assign_rem_expr
+| 69 = @assign_and_expr
+| 70 = @assign_xor_expr
+| 71 = @assign_or_expr
+| 72 = @assign_lshift_expr
+| 73 = @assign_rshift_expr
+/* more */
+| 74 = @object_init_expr
+| 75 = @collection_init_expr
+| 76 = @array_init_expr
+| 77 = @checked_expr
+| 78 = @unchecked_expr
+| 79 = @constructor_init_expr
+| 80 = @add_event_expr
+| 81 = @remove_event_expr
+| 82 = @par_expr
+| 83 = @local_var_decl_expr
+| 84 = @lambda_expr
+| 85 = @anonymous_method_expr
+| 86 = @namespace_expr
+/* dynamic */
+| 92 = @dynamic_element_access_expr
+| 93 = @dynamic_member_access_expr
+/* unsafe */
+| 100 = @pointer_indirection_expr
+| 101 = @address_of_expr
+| 102 = @sizeof_expr
+/* async */
+| 103 = @await_expr
+/* C# 6.0 */
+| 104 = @nameof_expr
+| 105 = @interpolated_string_expr
+| 106 = @unknown_expr
+/* C# 7.0 */
+| 107 = @throw_expr
+| 108 = @tuple_expr
+| 109 = @local_function_invocation_expr
+| 110 = @ref_expr
+| 111 = @discard_expr
+/* C# 8.0 */
+| 112 = @range_expr
+| 113 = @index_expr
+| 114 = @switch_expr
+| 115 = @recursive_pattern_expr
+| 116 = @property_pattern_expr
+| 117 = @positional_pattern_expr
+| 118 = @switch_case_expr
+| 119 = @assign_coalesce_expr
+| 120 = @suppress_nullable_warning_expr
+| 121 = @namespace_access_expr
+/* C# 9.0 */
+| 122 = @lt_pattern_expr
+| 123 = @gt_pattern_expr
+| 124 = @le_pattern_expr
+| 125 = @ge_pattern_expr
+| 126 = @not_pattern_expr
+| 127 = @and_pattern_expr
+| 128 = @or_pattern_expr
+| 129 = @function_pointer_invocation_expr
+| 130 = @with_expr
+/* C# 11.0 */
+| 131 = @list_pattern_expr
+| 132 = @slice_pattern_expr
+| 133 = @urshift_expr
+| 134 = @assign_urshift_expr
+| 135 = @utf8_string_literal_expr
+/* C# 12.0 */
+| 136 = @collection_expr
+| 137 = @spread_element_expr
+| 138 = @interpolated_string_insert_expr
+/* Preprocessor */
+| 999 = @define_symbol_expr
+;
+
+@switch = @switch_stmt | @switch_expr;
+@case = @case_stmt | @switch_case_expr;
+@pattern_match = @case | @is_expr;
+@unary_pattern_expr = @not_pattern_expr;
+@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr;
+@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr;
+
+@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr;
+@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr;
+@string_literal_expr = @utf16_string_literal_expr | @utf8_string_literal_expr;
+@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr
+ | @string_literal_expr | @null_literal_expr;
+
+@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr;
+@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr;
+@assign_event_expr = @add_event_expr | @remove_event_expr;
+
+@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr
+ | @assign_rem_expr
+@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr
+ | @assign_lshift_expr | @assign_rshift_expr | @assign_urshift_expr;
+
+@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr
+ | @method_access_expr | @type_access_expr | @dynamic_member_access_expr;
+@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr;
+@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr;
+
+@local_variable_access = @local_variable_access_expr | @local_var_decl_expr;
+@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access;
+@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr;
+
+@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr
+ | @event_access_expr | @dynamic_member_access_expr;
+
+@objectorcollection_init_expr = @object_init_expr | @collection_init_expr;
+
+@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr;
+
+@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
+@incr_op_expr = @pre_incr_expr | @post_incr_expr;
+@decr_op_expr = @pre_decr_expr | @post_decr_expr;
+@mut_op_expr = @incr_op_expr | @decr_op_expr;
+@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr;
+@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr;
+
+@ternary_log_op_expr = @conditional_expr;
+@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr;
+@un_log_op_expr = @log_not_expr;
+@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr;
+
+@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
+ | @rshift_expr | @urshift_expr;
+@un_bit_op_expr = @bit_not_expr;
+@bit_expr = @un_bit_op_expr | @bin_bit_op_expr;
+
+@equality_op_expr = @eq_expr | @ne_expr;
+@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr;
+@comp_expr = @equality_op_expr | @rel_op_expr;
+
+@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op;
+
+@ternary_op = @ternary_log_op_expr;
+@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr;
+@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr
+ | @pointer_indirection_expr | @address_of_expr;
+
+@anonymous_function_expr = @lambda_expr | @anonymous_method_expr;
+
+@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr
+ | @delegate_invocation_expr | @object_creation_expr | @call_access_expr
+ | @local_function_invocation_expr | @function_pointer_invocation_expr;
+
+@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr;
+
+@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr
+ | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr;
+
+@throw_element = @throw_expr | @throw_stmt;
+
+@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr;
+
+implicitly_typed_array_creation(
+ unique int id: @array_creation_expr ref);
+
+explicitly_sized_array_creation(
+ unique int id: @array_creation_expr ref);
+
+stackalloc_array_creation(
+ unique int id: @array_creation_expr ref);
+
+implicitly_typed_object_creation(
+ unique int id: @implicitly_typeable_object_creation_expr ref);
+
+mutator_invocation_mode(
+ unique int id: @operator_invocation_expr ref,
+ int mode: int ref /* prefix = 1, postfix = 2*/);
+
+expr_value(
+ unique int id: @expr ref,
+ string value: string ref);
+
+expr_call(
+ unique int caller_id: @expr ref,
+ int target_id: @callable ref);
+
+expr_access(
+ unique int accesser_id: @access_expr ref,
+ int target_id: @accessible ref);
+
+@accessible = @method | @assignable | @local_function | @namespace;
+
+expr_location(
+ unique int id: @expr ref,
+ int loc: @location ref);
+
+dynamic_member_name(
+ unique int id: @late_bindable_expr ref,
+ string name: string ref);
+
+@qualifiable_expr = @member_access_expr
+ | @method_invocation_expr
+ | @element_access_expr;
+
+conditional_access(
+ unique int id: @qualifiable_expr ref);
+
+expr_argument(
+ unique int id: @expr ref,
+ int mode: int ref);
+ /* mode is the same as params: value = 0, ref = 1, out = 2 */
+
+expr_argument_name(
+ unique int id: @expr ref,
+ string name: string ref);
+
+lambda_expr_return_type(
+ unique int id: @lambda_expr ref,
+ int type_id: @type_or_ref ref);
+
+/* Compiler generated */
+
+compiler_generated(unique int id: @element ref);
+
+/** CONTROL/DATA FLOW **/
+
+@control_flow_element = @stmt | @expr;
+
+/* XML Files */
+
+xmlEncoding (
+ unique int id: @file ref,
+ string encoding: string ref);
+
+xmlDTDs(
+ unique int id: @xmldtd,
+ string root: string ref,
+ string publicId: string ref,
+ string systemId: string ref,
+ int fileid: @file ref);
+
+xmlElements(
+ unique int id: @xmlelement,
+ string name: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlAttrs(
+ unique int id: @xmlattribute,
+ int elementid: @xmlelement ref,
+ string name: string ref,
+ string value: string ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlNs(
+ int id: @xmlnamespace,
+ string prefixName: string ref,
+ string URI: string ref,
+ int fileid: @file ref);
+
+xmlHasNs(
+ int elementId: @xmlnamespaceable ref,
+ int nsId: @xmlnamespace ref,
+ int fileid: @file ref);
+
+xmlComments(
+ unique int id: @xmlcomment,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int fileid: @file ref);
+
+xmlChars(
+ unique int id: @xmlcharacters,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int isCDATA: int ref,
+ int fileid: @file ref);
+
+@xmlparent = @file | @xmlelement;
+@xmlnamespaceable = @xmlelement | @xmlattribute;
+
+xmllocations(
+ int xmlElement: @xmllocatable ref,
+ int location: @location_default ref);
+
+@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
+
+/* Comments */
+
+commentline(
+ unique int id: @commentline,
+ int kind: int ref,
+ string text: string ref,
+ string rawtext: string ref);
+
+case @commentline.kind of
+ 0 = @singlelinecomment
+| 1 = @xmldoccomment
+| 2 = @multilinecomment;
+
+commentline_location(
+ unique int id: @commentline ref,
+ int loc: @location ref);
+
+commentblock(
+ unique int id : @commentblock);
+
+commentblock_location(
+ unique int id: @commentblock ref,
+ int loc: @location ref);
+
+commentblock_binding(
+ int id: @commentblock ref,
+ int entity: @element ref,
+ int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */
+
+commentblock_child(
+ int id: @commentblock ref,
+ int commentline: @commentline ref,
+ int index: int ref);
+
+/* ASP.NET */
+
+case @asp_element.kind of
+ 0=@asp_close_tag
+| 1=@asp_code
+| 2=@asp_comment
+| 3=@asp_data_binding
+| 4=@asp_directive
+| 5=@asp_open_tag
+| 6=@asp_quoted_string
+| 7=@asp_text
+| 8=@asp_xml_directive;
+
+@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string;
+
+asp_elements(
+ unique int id: @asp_element,
+ int kind: int ref,
+ int loc: @location ref);
+
+asp_comment_server(unique int comment: @asp_comment ref);
+asp_code_inline(unique int code: @asp_code ref);
+asp_directive_attribute(
+ int directive: @asp_directive ref,
+ int index: int ref,
+ string name: string ref,
+ int value: @asp_quoted_string ref);
+asp_directive_name(
+ unique int directive: @asp_directive ref,
+ string name: string ref);
+asp_element_body(
+ unique int element: @asp_element ref,
+ string body: string ref);
+asp_tag_attribute(
+ int tag: @asp_open_tag ref,
+ int index: int ref,
+ string name: string ref,
+ int attribute: @asp_attribute ref);
+asp_tag_name(
+ unique int tag: @asp_open_tag ref,
+ string name: string ref);
+asp_tag_isempty(int tag: @asp_open_tag ref);
diff --git a/csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/upgrade.properties b/csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/upgrade.properties
new file mode 100644
index 000000000000..1989c9c8847b
--- /dev/null
+++ b/csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/upgrade.properties
@@ -0,0 +1,2 @@
+description: Add `interpolated_string_insert_expr` kind.
+compatibility: partial
From f582054ca4425b0013fa285d40126ce10bda8307 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 24 Mar 2025 09:17:56 +0000
Subject: [PATCH 031/409] Rust: Refactor the tests that have multiple control
flow paths.
---
.../CWE-825/AccessInvalidPointer.expected | 142 +++++++++---------
.../security/CWE-825/deallocation.rs | 97 ++++++++----
.../query-tests/security/CWE-825/lifetime.rs | 99 ++++++++----
.../test/query-tests/security/CWE-825/main.rs | 45 +++---
4 files changed, 225 insertions(+), 158 deletions(-)
diff --git a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
index 0067fcc17daa..919bd2245199 100644
--- a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
+++ b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
@@ -1,45 +1,44 @@
#select
-| deallocation.rs:23:13:23:14 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:23:13:23:14 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
-| deallocation.rs:25:12:25:31 | ...::read::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:25:12:25:31 | ...::read::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
-| deallocation.rs:33:5:33:6 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:33:5:33:6 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
-| deallocation.rs:35:4:35:24 | ...::write::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:35:4:35:24 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
-| deallocation.rs:57:14:57:15 | m2 | deallocation.rs:54:23:54:24 | m2 | deallocation.rs:57:14:57:15 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:54:23:54:24 | m2 | invalid |
-| deallocation.rs:58:14:58:15 | m2 | deallocation.rs:54:23:54:24 | m2 | deallocation.rs:58:14:58:15 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:54:23:54:24 | m2 | invalid |
-| deallocation.rs:63:6:63:7 | m2 | deallocation.rs:54:23:54:24 | m2 | deallocation.rs:63:6:63:7 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:54:23:54:24 | m2 | invalid |
-| deallocation.rs:64:6:64:7 | m2 | deallocation.rs:54:23:54:24 | m2 | deallocation.rs:64:6:64:7 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:54:23:54:24 | m2 | invalid |
-| deallocation.rs:66:4:66:30 | ...::write::<...> | deallocation.rs:54:23:54:24 | m2 | deallocation.rs:66:4:66:30 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:54:23:54:24 | m2 | invalid |
-| deallocation.rs:84:13:84:18 | my_ptr | deallocation.rs:81:14:81:19 | my_ptr | deallocation.rs:84:13:84:18 | my_ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:81:14:81:19 | my_ptr | invalid |
-| deallocation.rs:99:14:99:15 | p1 | deallocation.rs:92:23:92:40 | ...::dangling | deallocation.rs:99:14:99:15 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:92:23:92:40 | ...::dangling | invalid |
-| deallocation.rs:100:14:100:15 | p2 | deallocation.rs:93:21:93:42 | ...::dangling_mut | deallocation.rs:100:14:100:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:93:21:93:42 | ...::dangling_mut | invalid |
-| deallocation.rs:101:14:101:15 | p3 | deallocation.rs:94:23:94:36 | ...::null | deallocation.rs:101:14:101:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:94:23:94:36 | ...::null | invalid |
-| deallocation.rs:148:14:148:15 | p1 | deallocation.rs:145:27:145:28 | p1 | deallocation.rs:148:14:148:15 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:145:27:145:28 | p1 | invalid |
-| deallocation.rs:179:18:179:20 | ptr | deallocation.rs:173:27:173:29 | ptr | deallocation.rs:179:18:179:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:173:27:173:29 | ptr | invalid |
+| deallocation.rs:26:15:26:16 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:26:15:26:16 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
+| deallocation.rs:33:14:33:33 | ...::read::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:33:14:33:33 | ...::read::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
+| deallocation.rs:40:6:40:7 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:40:6:40:7 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
+| deallocation.rs:45:5:45:25 | ...::write::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:45:5:45:25 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
+| deallocation.rs:72:16:72:17 | m2 | deallocation.rs:66:23:66:24 | m2 | deallocation.rs:72:16:72:17 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:66:23:66:24 | m2 | invalid |
+| deallocation.rs:77:16:77:17 | m2 | deallocation.rs:66:23:66:24 | m2 | deallocation.rs:77:16:77:17 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:66:23:66:24 | m2 | invalid |
+| deallocation.rs:82:7:82:8 | m2 | deallocation.rs:66:23:66:24 | m2 | deallocation.rs:82:7:82:8 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:66:23:66:24 | m2 | invalid |
+| deallocation.rs:86:7:86:8 | m2 | deallocation.rs:66:23:66:24 | m2 | deallocation.rs:86:7:86:8 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:66:23:66:24 | m2 | invalid |
+| deallocation.rs:91:5:91:31 | ...::write::<...> | deallocation.rs:66:23:66:24 | m2 | deallocation.rs:91:5:91:31 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:66:23:66:24 | m2 | invalid |
+| deallocation.rs:111:13:111:18 | my_ptr | deallocation.rs:108:14:108:19 | my_ptr | deallocation.rs:111:13:111:18 | my_ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:108:14:108:19 | my_ptr | invalid |
+| deallocation.rs:126:14:126:15 | p1 | deallocation.rs:119:23:119:40 | ...::dangling | deallocation.rs:126:14:126:15 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:119:23:119:40 | ...::dangling | invalid |
+| deallocation.rs:127:14:127:15 | p2 | deallocation.rs:120:21:120:42 | ...::dangling_mut | deallocation.rs:127:14:127:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:120:21:120:42 | ...::dangling_mut | invalid |
+| deallocation.rs:128:14:128:15 | p3 | deallocation.rs:121:23:121:36 | ...::null | deallocation.rs:128:14:128:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:121:23:121:36 | ...::null | invalid |
+| deallocation.rs:176:15:176:16 | p1 | deallocation.rs:172:27:172:28 | p1 | deallocation.rs:176:15:176:16 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:172:27:172:28 | p1 | invalid |
+| deallocation.rs:210:18:210:20 | ptr | deallocation.rs:204:27:204:29 | ptr | deallocation.rs:210:18:210:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:204:27:204:29 | ptr | invalid |
edges
-| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:23:13:23:14 | m1 | provenance | |
-| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:25:33:25:34 | m1 | provenance | |
-| deallocation.rs:25:33:25:34 | m1 | deallocation.rs:25:12:25:31 | ...::read::<...> | provenance | MaD:1 Sink:MaD:1 |
-| deallocation.rs:25:33:25:34 | m1 | deallocation.rs:33:5:33:6 | m1 | provenance | |
-| deallocation.rs:25:33:25:34 | m1 | deallocation.rs:33:5:33:6 | m1 | provenance | |
-| deallocation.rs:33:5:33:6 | m1 | deallocation.rs:35:26:35:27 | m1 | provenance | |
-| deallocation.rs:35:26:35:27 | m1 | deallocation.rs:35:4:35:24 | ...::write::<...> | provenance | MaD:2 Sink:MaD:2 |
-| deallocation.rs:54:23:54:24 | m2 | deallocation.rs:57:14:57:15 | m2 | provenance | |
-| deallocation.rs:54:23:54:24 | m2 | deallocation.rs:58:14:58:15 | m2 | provenance | |
-| deallocation.rs:54:23:54:24 | m2 | deallocation.rs:63:6:63:7 | m2 | provenance | |
-| deallocation.rs:54:23:54:24 | m2 | deallocation.rs:64:6:64:7 | m2 | provenance | |
-| deallocation.rs:54:23:54:24 | m2 | deallocation.rs:66:32:66:33 | m2 | provenance | |
-| deallocation.rs:66:32:66:33 | m2 | deallocation.rs:66:4:66:30 | ...::write::<...> | provenance | MaD:2 Sink:MaD:2 |
-| deallocation.rs:81:14:81:19 | my_ptr | deallocation.rs:84:13:84:18 | my_ptr | provenance | |
-| deallocation.rs:92:6:92:7 | p1 | deallocation.rs:99:14:99:15 | p1 | provenance | |
-| deallocation.rs:92:23:92:40 | ...::dangling | deallocation.rs:92:23:92:42 | ...::dangling(...) | provenance | Src:MaD:3 MaD:3 |
-| deallocation.rs:92:23:92:42 | ...::dangling(...) | deallocation.rs:92:6:92:7 | p1 | provenance | |
-| deallocation.rs:93:6:93:7 | p2 | deallocation.rs:100:14:100:15 | p2 | provenance | |
-| deallocation.rs:93:21:93:42 | ...::dangling_mut | deallocation.rs:93:21:93:44 | ...::dangling_mut(...) | provenance | Src:MaD:4 MaD:4 |
-| deallocation.rs:93:21:93:44 | ...::dangling_mut(...) | deallocation.rs:93:6:93:7 | p2 | provenance | |
-| deallocation.rs:94:6:94:7 | p3 | deallocation.rs:101:14:101:15 | p3 | provenance | |
-| deallocation.rs:94:23:94:36 | ...::null | deallocation.rs:94:23:94:38 | ...::null(...) | provenance | Src:MaD:5 MaD:5 |
-| deallocation.rs:94:23:94:38 | ...::null(...) | deallocation.rs:94:6:94:7 | p3 | provenance | |
-| deallocation.rs:145:27:145:28 | p1 | deallocation.rs:148:14:148:15 | p1 | provenance | |
-| deallocation.rs:173:27:173:29 | ptr | deallocation.rs:179:18:179:20 | ptr | provenance | |
+| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:26:15:26:16 | m1 | provenance | |
+| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:33:35:33:36 | m1 | provenance | |
+| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:40:6:40:7 | m1 | provenance | |
+| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:45:27:45:28 | m1 | provenance | |
+| deallocation.rs:33:35:33:36 | m1 | deallocation.rs:33:14:33:33 | ...::read::<...> | provenance | MaD:1 Sink:MaD:1 |
+| deallocation.rs:45:27:45:28 | m1 | deallocation.rs:45:5:45:25 | ...::write::<...> | provenance | MaD:2 Sink:MaD:2 |
+| deallocation.rs:66:23:66:24 | m2 | deallocation.rs:72:16:72:17 | m2 | provenance | |
+| deallocation.rs:66:23:66:24 | m2 | deallocation.rs:77:16:77:17 | m2 | provenance | |
+| deallocation.rs:66:23:66:24 | m2 | deallocation.rs:82:7:82:8 | m2 | provenance | |
+| deallocation.rs:66:23:66:24 | m2 | deallocation.rs:86:7:86:8 | m2 | provenance | |
+| deallocation.rs:66:23:66:24 | m2 | deallocation.rs:91:33:91:34 | m2 | provenance | |
+| deallocation.rs:91:33:91:34 | m2 | deallocation.rs:91:5:91:31 | ...::write::<...> | provenance | MaD:2 Sink:MaD:2 |
+| deallocation.rs:108:14:108:19 | my_ptr | deallocation.rs:111:13:111:18 | my_ptr | provenance | |
+| deallocation.rs:119:6:119:7 | p1 | deallocation.rs:126:14:126:15 | p1 | provenance | |
+| deallocation.rs:119:23:119:40 | ...::dangling | deallocation.rs:119:23:119:42 | ...::dangling(...) | provenance | Src:MaD:3 MaD:3 |
+| deallocation.rs:119:23:119:42 | ...::dangling(...) | deallocation.rs:119:6:119:7 | p1 | provenance | |
+| deallocation.rs:120:6:120:7 | p2 | deallocation.rs:127:14:127:15 | p2 | provenance | |
+| deallocation.rs:120:21:120:42 | ...::dangling_mut | deallocation.rs:120:21:120:44 | ...::dangling_mut(...) | provenance | Src:MaD:4 MaD:4 |
+| deallocation.rs:120:21:120:44 | ...::dangling_mut(...) | deallocation.rs:120:6:120:7 | p2 | provenance | |
+| deallocation.rs:121:6:121:7 | p3 | deallocation.rs:128:14:128:15 | p3 | provenance | |
+| deallocation.rs:121:23:121:36 | ...::null | deallocation.rs:121:23:121:38 | ...::null(...) | provenance | Src:MaD:5 MaD:5 |
+| deallocation.rs:121:23:121:38 | ...::null(...) | deallocation.rs:121:6:121:7 | p3 | provenance | |
+| deallocation.rs:172:27:172:28 | p1 | deallocation.rs:176:15:176:16 | p1 | provenance | |
+| deallocation.rs:204:27:204:29 | ptr | deallocation.rs:210:18:210:20 | ptr | provenance | |
models
| 1 | Sink: lang:core; crate::ptr::read; pointer-access; Argument[0] |
| 2 | Sink: lang:core; crate::ptr::write; pointer-access; Argument[0] |
@@ -48,36 +47,35 @@ models
| 5 | Source: lang:core; crate::ptr::null; pointer-invalidate; ReturnValue |
nodes
| deallocation.rs:20:23:20:24 | m1 | semmle.label | m1 |
-| deallocation.rs:23:13:23:14 | m1 | semmle.label | m1 |
-| deallocation.rs:25:12:25:31 | ...::read::<...> | semmle.label | ...::read::<...> |
-| deallocation.rs:25:33:25:34 | m1 | semmle.label | m1 |
-| deallocation.rs:33:5:33:6 | m1 | semmle.label | m1 |
-| deallocation.rs:33:5:33:6 | m1 | semmle.label | m1 |
-| deallocation.rs:35:4:35:24 | ...::write::<...> | semmle.label | ...::write::<...> |
-| deallocation.rs:35:26:35:27 | m1 | semmle.label | m1 |
-| deallocation.rs:54:23:54:24 | m2 | semmle.label | m2 |
-| deallocation.rs:57:14:57:15 | m2 | semmle.label | m2 |
-| deallocation.rs:58:14:58:15 | m2 | semmle.label | m2 |
-| deallocation.rs:63:6:63:7 | m2 | semmle.label | m2 |
-| deallocation.rs:64:6:64:7 | m2 | semmle.label | m2 |
-| deallocation.rs:66:4:66:30 | ...::write::<...> | semmle.label | ...::write::<...> |
-| deallocation.rs:66:32:66:33 | m2 | semmle.label | m2 |
-| deallocation.rs:81:14:81:19 | my_ptr | semmle.label | my_ptr |
-| deallocation.rs:84:13:84:18 | my_ptr | semmle.label | my_ptr |
-| deallocation.rs:92:6:92:7 | p1 | semmle.label | p1 |
-| deallocation.rs:92:23:92:40 | ...::dangling | semmle.label | ...::dangling |
-| deallocation.rs:92:23:92:42 | ...::dangling(...) | semmle.label | ...::dangling(...) |
-| deallocation.rs:93:6:93:7 | p2 | semmle.label | p2 |
-| deallocation.rs:93:21:93:42 | ...::dangling_mut | semmle.label | ...::dangling_mut |
-| deallocation.rs:93:21:93:44 | ...::dangling_mut(...) | semmle.label | ...::dangling_mut(...) |
-| deallocation.rs:94:6:94:7 | p3 | semmle.label | p3 |
-| deallocation.rs:94:23:94:36 | ...::null | semmle.label | ...::null |
-| deallocation.rs:94:23:94:38 | ...::null(...) | semmle.label | ...::null(...) |
-| deallocation.rs:99:14:99:15 | p1 | semmle.label | p1 |
-| deallocation.rs:100:14:100:15 | p2 | semmle.label | p2 |
-| deallocation.rs:101:14:101:15 | p3 | semmle.label | p3 |
-| deallocation.rs:145:27:145:28 | p1 | semmle.label | p1 |
-| deallocation.rs:148:14:148:15 | p1 | semmle.label | p1 |
-| deallocation.rs:173:27:173:29 | ptr | semmle.label | ptr |
-| deallocation.rs:179:18:179:20 | ptr | semmle.label | ptr |
+| deallocation.rs:26:15:26:16 | m1 | semmle.label | m1 |
+| deallocation.rs:33:14:33:33 | ...::read::<...> | semmle.label | ...::read::<...> |
+| deallocation.rs:33:35:33:36 | m1 | semmle.label | m1 |
+| deallocation.rs:40:6:40:7 | m1 | semmle.label | m1 |
+| deallocation.rs:45:5:45:25 | ...::write::<...> | semmle.label | ...::write::<...> |
+| deallocation.rs:45:27:45:28 | m1 | semmle.label | m1 |
+| deallocation.rs:66:23:66:24 | m2 | semmle.label | m2 |
+| deallocation.rs:72:16:72:17 | m2 | semmle.label | m2 |
+| deallocation.rs:77:16:77:17 | m2 | semmle.label | m2 |
+| deallocation.rs:82:7:82:8 | m2 | semmle.label | m2 |
+| deallocation.rs:86:7:86:8 | m2 | semmle.label | m2 |
+| deallocation.rs:91:5:91:31 | ...::write::<...> | semmle.label | ...::write::<...> |
+| deallocation.rs:91:33:91:34 | m2 | semmle.label | m2 |
+| deallocation.rs:108:14:108:19 | my_ptr | semmle.label | my_ptr |
+| deallocation.rs:111:13:111:18 | my_ptr | semmle.label | my_ptr |
+| deallocation.rs:119:6:119:7 | p1 | semmle.label | p1 |
+| deallocation.rs:119:23:119:40 | ...::dangling | semmle.label | ...::dangling |
+| deallocation.rs:119:23:119:42 | ...::dangling(...) | semmle.label | ...::dangling(...) |
+| deallocation.rs:120:6:120:7 | p2 | semmle.label | p2 |
+| deallocation.rs:120:21:120:42 | ...::dangling_mut | semmle.label | ...::dangling_mut |
+| deallocation.rs:120:21:120:44 | ...::dangling_mut(...) | semmle.label | ...::dangling_mut(...) |
+| deallocation.rs:121:6:121:7 | p3 | semmle.label | p3 |
+| deallocation.rs:121:23:121:36 | ...::null | semmle.label | ...::null |
+| deallocation.rs:121:23:121:38 | ...::null(...) | semmle.label | ...::null(...) |
+| deallocation.rs:126:14:126:15 | p1 | semmle.label | p1 |
+| deallocation.rs:127:14:127:15 | p2 | semmle.label | p2 |
+| deallocation.rs:128:14:128:15 | p3 | semmle.label | p3 |
+| deallocation.rs:172:27:172:28 | p1 | semmle.label | p1 |
+| deallocation.rs:176:15:176:16 | p1 | semmle.label | p1 |
+| deallocation.rs:204:27:204:29 | ptr | semmle.label | ptr |
+| deallocation.rs:210:18:210:20 | ptr | semmle.label | ptr |
subpaths
diff --git a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
index 30677ddc07cc..738abe774035 100644
--- a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
@@ -1,7 +1,7 @@
// --- std::alloc ---
-pub fn test_alloc(do_dangerous_writes: bool) {
+pub fn test_alloc(mode: i32) {
let layout = std::alloc::Layout::new::();
unsafe {
let m1 = std::alloc::alloc(layout); // *mut u8
@@ -20,25 +20,37 @@ pub fn test_alloc(do_dangerous_writes: bool) {
std::alloc::dealloc(m1, layout); // $ Source=dealloc
// (m1, m2 are now dangling)
- let v5 = *m1; // $ Alert[rust/access-invalid-pointer]=dealloc
- let v6 = *m2; // $ MISSING: Alert
- let v7 = std::ptr::read::(m1); // $ Alert[rust/access-invalid-pointer]=dealloc
- let v8 = std::ptr::read::(m2); // $ MISSING: Alert
- println!(" v5 = {v5} (!)"); // corrupt in practice
- println!(" v6 = {v6} (!)"); // corrupt in practice
- println!(" v7 = {v7} (!)"); // corrupt in practice
- println!(" v8 = {v8} (!)"); // corrupt in practice
-
- if do_dangerous_writes {
- *m1 = 2; // $ Alert[rust/access-invalid-pointer]=dealloc
- *m2 = 3; // $ MISSING: Alert
- std::ptr::write::(m1, 4); // $ Alert[rust/access-invalid-pointer]=dealloc
- std::ptr::write::(m2, 5); // $ MISSING: Alert
+ match mode {
+ 0 => {
+ // reads
+ let v5 = *m1; // $ Alert[rust/access-invalid-pointer]=dealloc
+ let v6 = *m2; // $ MISSING: Alert
+ println!(" v5 = {v5} (!)"); // corrupt in practice
+ println!(" v6 = {v6} (!)"); // corrupt in practice
+ },
+ 100 => {
+ // more reads
+ let v7 = std::ptr::read::(m1); // $ Alert[rust/access-invalid-pointer]=dealloc
+ let v8 = std::ptr::read::(m2); // $ MISSING: Alert
+ println!(" v7 = {v7} (!)"); // corrupt in practice
+ println!(" v8 = {v8} (!)"); // corrupt in practice
+ },
+ 101 => {
+ // writes
+ *m1 = 2; // $ Alert[rust/access-invalid-pointer]=dealloc
+ *m2 = 3; // $ MISSING: Alert
+ },
+ 102 => {
+ // more writes
+ std::ptr::write::(m1, 4); // $ Alert[rust/access-invalid-pointer]=dealloc
+ std::ptr::write::(m2, 5); // $ MISSING: Alert
+ },
+ _ => {}
}
}
}
-pub fn test_alloc_array(do_dangerous_writes: bool) {
+pub fn test_alloc_array(mode: i32) {
let layout = std::alloc::Layout::new::<[u8; 10]>();
unsafe {
let m1 = std::alloc::alloc(layout);
@@ -54,16 +66,31 @@ pub fn test_alloc_array(do_dangerous_writes: bool) {
std::alloc::dealloc(m2 as *mut u8, layout); // $ Source=dealloc_array
// m1, m2 are now dangling
- let v3 = (*m2)[0]; // $ Alert[rust/access-invalid-pointer]=dealloc_array
- let v4 = (*m2)[1]; // $ Alert[rust/access-invalid-pointer]=dealloc_array
- println!(" v3 = {v3} (!)"); // corrupt in practice
- println!(" v4 = {v4} (!)"); // corrupt in practice
-
- if do_dangerous_writes {
- (*m2)[0] = 3; // $ Alert[rust/access-invalid-pointer]=dealloc_array
- (*m2)[1] = 4; // $ Alert[rust/access-invalid-pointer]=dealloc_array
- std::ptr::write::(m1, 5); // $ MISSING: Alert
- std::ptr::write::<[u8; 10]>(m2, [6; 10]); // $ Alert[rust/access-invalid-pointer]=dealloc_array
+ match mode {
+ 0 => {
+ // read
+ let v3 = (*m2)[0]; // $ Alert[rust/access-invalid-pointer]=dealloc_array
+ println!(" v3 = {v3} (!)"); // corrupt in practice
+ },
+ 110 => {
+ // another read
+ let v4 = (*m2)[1]; // $ Alert[rust/access-invalid-pointer]=dealloc_array
+ println!(" v4 = {v4} (!)"); // corrupt in practice
+ },
+ 111 => {
+ // write
+ (*m2)[0] = 3; // $ Alert[rust/access-invalid-pointer]=dealloc_array
+ },
+ 112 => {
+ // another write
+ (*m2)[1] = 4; // $ Alert[rust/access-invalid-pointer]=dealloc_array
+ },
+ 113 => {
+ // more writes
+ std::ptr::write::(m1, 5); // $ MISSING: Alert
+ std::ptr::write::<[u8; 10]>(m2, [6; 10]); // $ Alert[rust/access-invalid-pointer]=dealloc_array
+ },
+ _ => {}
}
}
}
@@ -88,12 +115,12 @@ pub fn test_libc() {
// --- std::ptr ---
-pub fn test_ptr_invalid(do_dangerous_accesses: bool) {
+pub fn test_ptr_invalid(mode: i32) {
let p1: *const i64 = std::ptr::dangling(); // $ Source=dangling
let p2: *mut i64 = std::ptr::dangling_mut(); // $ Source=dangling_mut
let p3: *const i64 = std::ptr::null(); // $ Source=null
- if do_dangerous_accesses {
+ if mode == 120 {
unsafe {
// (a segmentation fault occurs in the code below)
let v1 = *p1; // $ Alert[rust/access-invalid-pointer]=dangling
@@ -129,7 +156,7 @@ pub fn test_drop() {
}
}
-pub fn test_ptr_drop() {
+pub fn test_ptr_drop(mode: i32) {
let layout = std::alloc::Layout::new::>();
unsafe {
let p1 = std::alloc::alloc(layout) as *mut Vec; // *mut i64
@@ -145,10 +172,14 @@ pub fn test_ptr_drop() {
std::ptr::drop_in_place(p1); // $ Source=drop_in_place
// explicitly destructs the pointed-to `m2`
- let v3 = (*p1)[0]; // $ Alert[rust/access-invalid-pointer]=drop_in_place
- let v4 = (*p2)[0]; // $ MISSING: Alert
- println!(" v3 = {v3} (!)"); // corrupt in practice
- println!(" v4 = {v4} (!)"); // corrupt in practice
+ if mode == 1 {
+ let v3 = (*p1)[0]; // $ Alert[rust/access-invalid-pointer]=drop_in_place
+ println!(" v3 = {v3} (!)"); // corrupt in practice
+ }
+ if mode == 130 {
+ let v4 = (*p2)[0]; // $ MISSING: Alert
+ println!(" v4 = {v4} (!)"); // corrupt in practice
+ }
}
}
diff --git a/rust/ql/test/query-tests/security/CWE-825/lifetime.rs b/rust/ql/test/query-tests/security/CWE-825/lifetime.rs
index 49b0678b0359..d7fd8204993a 100644
--- a/rust/ql/test/query-tests/security/CWE-825/lifetime.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/lifetime.rs
@@ -88,7 +88,7 @@ pub fn test_local_dangling() {
// --- local in scope ---
-fn use_pointers(p1: *const i64, p2: *mut i64) {
+fn use_pointers(p1: *const i64, p2: *mut i64, mode: i32) {
let p3: *const i64;
let my_local1 = 1;
p3 = &my_local1;
@@ -96,21 +96,27 @@ fn use_pointers(p1: *const i64, p2: *mut i64) {
use_the_stack();
unsafe {
- let v1 = *p1; // GOOD
- let v2 = *p2; // GOOD
- let v3 = *p3; // GOOD
- *p2 = 2; // GOOD
- println!(" v1 = {v1}");
- println!(" v2 = {v2}");
- println!(" v3 = {v3}");
+ if (mode == 0) {
+ // reads
+ let v1 = *p1; // GOOD
+ let v2 = *p2; // GOOD
+ let v3 = *p3; // GOOD
+ println!(" v1 = {v1}");
+ println!(" v2 = {v2}");
+ println!(" v3 = {v3}");
+ }
+ if (mode == 200) {
+ // writes
+ *p2 = 2; // GOOD
+ }
}
}
-pub fn test_local_in_scope() {
+pub fn test_local_in_scope(mode: i32) {
let my_local3: i64 = 3;
let mut my_local_mut4: i64 = 4;
- use_pointers(&my_local3, &mut my_local_mut4);
+ use_pointers(&my_local3, &mut my_local_mut4, mode);
}
// --- static lifetime ---
@@ -129,18 +135,24 @@ fn get_static_mut() -> *mut i64 {
}
}
-pub fn test_static() {
+pub fn test_static(mode: i32) {
let p1 = get_const();
let p2 = get_static_mut();
use_the_stack();
unsafe {
- let v1 = *p1; // GOOD
- let v2 = *p2; // GOOD
- *p2 = 3; // GOOD
- println!(" v1 = {v1}");
- println!(" v2 = {v2}");
+ if (mode == 0) {
+ // reads
+ let v1 = *p1; // GOOD
+ let v2 = *p2; // GOOD
+ println!(" v1 = {v1}");
+ println!(" v2 = {v2}");
+ }
+ if (mode == 210) {
+ // writes
+ *p2 = 3; // GOOD
+ }
}
}
@@ -299,7 +311,7 @@ impl Drop for MyPair {
}
}
-pub fn test_ptr_to_struct() {
+pub fn test_ptr_to_struct(mode: i32) {
let p1: *mut MyPair;
let p2: *const i64;
let p3: *mut i64;
@@ -312,33 +324,54 @@ pub fn test_ptr_to_struct() {
unsafe {
let v1 = (*p1).a; // GOOD
+ println!(" v1 = {v1}");
+
let v2 = (*p1).b; // GOOD
+ println!(" v2 = {v2}");
+
let v3 = *p2; // GOOD
let v4 = *p3; // GOOD
- (*p1).a = 3; // GOOD
- (*p1).b = 4; // GOOD
- *p3 = 5; // GOOD
- println!(" v1 = {v1}");
- println!(" v2 = {v2}");
println!(" v3 = {v3}");
println!(" v4 = {v4}");
+
+ (*p1).a = 3; // GOOD
+ *p3 = 4; // GOOD
+ (*p1).b = 5; // GOOD
}
}; // my_pair goes out of scope, thus p1, p2, p3 are dangling
use_the_stack();
unsafe {
- let v5 = (*p1).a; // $ MISSING: Alert
- let v6 = (*p1).b; // $ MISSING: Alert
- let v7 = *p2; // $ MISSING: Alert
- let v8 = *p3; // $ MISSING: Alert
- (*p1).a = 6; // $ MISSING: Alert
- (*p1).b = 7; // $ MISSING: Alert
- *p3 = 8; // $ MISSING: Alert
- println!(" v5 = {v5} (!)"); // dropped in practice
- println!(" v6 = {v6} (!)"); // dropped in practice
- println!(" v7 = {v7} (!)"); // dropped in practice
- println!(" v8 = {v8} (!)"); // dropped in practice
+ match mode {
+ 0 => {
+ // read
+ let v5 = (*p1).a; // $ MISSING: Alert
+ println!(" v5 = {v5} (!)"); // dropped in practice
+ },
+ 220 => {
+ // another read
+ let v6 = (*p1).b; // $ MISSING: Alert
+ println!(" v6 = {v6} (!)"); // dropped in practice
+ },
+ 221 => {
+ // more reads
+ let v7 = *p2; // $ MISSING: Alert
+ let v8 = *p3; // $ MISSING: Alert
+ println!(" v7 = {v7} (!)"); // dropped in practice
+ println!(" v8 = {v8} (!)"); // dropped in practice
+ },
+ 222 => {
+ // writes
+ (*p1).a = 6; // $ MISSING: Alert
+ *p3 = 7; // $ MISSING: Alert
+ },
+ 223 => {
+ // another write
+ (*p1).b = 8; // $ MISSING: Alert
+ },
+ _ => {}
+ }
}
}
diff --git a/rust/ql/test/query-tests/security/CWE-825/main.rs b/rust/ql/test/query-tests/security/CWE-825/main.rs
index 9a3dfcd2889c..0b3fc423de12 100644
--- a/rust/ql/test/query-tests/security/CWE-825/main.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/main.rs
@@ -31,7 +31,7 @@ pub fn test_boxes_into() {
}
}
-pub fn test_boxes_1(do_dangerous_writes: bool) {
+pub fn test_boxes_1(mode: i32) {
let p1: *const i64;
let p2: *const i64;
let p3: *mut i64;
@@ -50,27 +50,28 @@ pub fn test_boxes_1(do_dangerous_writes: bool) {
let v1 = *p1; // GOOD
let v2 = *p2; // GOOD
let v3 = *p3; // GOOD
- *p3 = 4;
-
println!(" v1 = {v1}");
println!(" v2 = {v2}");
println!(" v3 = {v3}");
+ *p3 = 4;
}
} // (b2, b3 go out of scope, thus p2, p3 are dangling)
unsafe {
- let v4 = *p1; // GOOD
- let v5 = *p2; // $ MISSING: Alert
- let v6 = *p3; // $ MISSING: Alert
-
- if do_dangerous_writes {
+ if mode == 0 {
+ // reads
+ let v4 = *p1; // GOOD
+ let v5 = *p2; // $ MISSING: Alert
+ let v6 = *p3; // $ MISSING: Alert
+ println!(" v4 = {v4}");
+ println!(" v5 = {v5} (!)"); // corrupt in practice
+ println!(" v6 = {v6} (!)"); // corrupt in practice
+ }
+ if mode == 10 {
+ // write
*p3 = 5; // $ MISSING: Alert
use_the_heap(); // "malloc: Heap corruption detected"
}
-
- println!(" v4 = {v4}");
- println!(" v5 = {v5} (!)"); // corrupt in practice
- println!(" v6 = {v6} (!)"); // corrupt in practice
}
}
@@ -94,11 +95,15 @@ pub fn test_boxes_2() {
// --- main ---
fn main() {
+ let mode = std::env::args().nth(1).unwrap_or("0".to_string()).parse::().unwrap_or(0);
+ // mode = which test cases to explore (0 should be safe; some will crash / segfault).
+ println!("mode = {mode}");
+
println!("test_boxes_into:");
test_boxes_into();
println!("test_boxes_1:");
- test_boxes_1(false);
+ test_boxes_1(mode);
println!("test_boxes_2:");
test_boxes_2();
@@ -106,22 +111,22 @@ fn main() {
// ---
println!("test_alloc:");
- test_alloc(false);
+ test_alloc(mode);
println!("test_alloc_array:");
- test_alloc_array(false);
+ test_alloc_array(mode);
println!("test_libc:");
test_libc();
println!("test_ptr_invalid:");
- test_ptr_invalid(false);
+ test_ptr_invalid(mode);
println!("test_drop:");
test_drop();
println!("test_ptr_drop:");
- test_ptr_drop();
+ test_ptr_drop(mode);
println!("test_qhelp_tests:");
test_qhelp_tests();
@@ -135,10 +140,10 @@ fn main() {
test_local_dangling();
println!("test_local_in_scope:");
- test_local_in_scope();
+ test_local_in_scope(mode);
println!("test_static:");
- test_static();
+ test_static(mode);
println!("test_call_contexts:");
test_call_contexts();
@@ -153,7 +158,7 @@ fn main() {
test_enum();
println!("test_ptr_to_struct:");
- test_ptr_to_struct();
+ test_ptr_to_struct(mode);
println!("test_ptr_from_ref:");
test_ptr_from_ref();
From b7044bdcde3f7445148a1bc1953f1de9f92dc1e7 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 24 Mar 2025 11:21:02 +0000
Subject: [PATCH 032/409] Rust: Add a test of repeat sinks.
---
.../CWE-825/AccessInvalidPointer.expected | 138 +++++++++---------
.../security/CWE-825/deallocation.rs | 4 +
2 files changed, 76 insertions(+), 66 deletions(-)
diff --git a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
index 919bd2245199..910252a4aca0 100644
--- a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
+++ b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
@@ -1,44 +1,48 @@
#select
| deallocation.rs:26:15:26:16 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:26:15:26:16 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
-| deallocation.rs:33:14:33:33 | ...::read::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:33:14:33:33 | ...::read::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
-| deallocation.rs:40:6:40:7 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:40:6:40:7 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
-| deallocation.rs:45:5:45:25 | ...::write::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:45:5:45:25 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
-| deallocation.rs:72:16:72:17 | m2 | deallocation.rs:66:23:66:24 | m2 | deallocation.rs:72:16:72:17 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:66:23:66:24 | m2 | invalid |
-| deallocation.rs:77:16:77:17 | m2 | deallocation.rs:66:23:66:24 | m2 | deallocation.rs:77:16:77:17 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:66:23:66:24 | m2 | invalid |
-| deallocation.rs:82:7:82:8 | m2 | deallocation.rs:66:23:66:24 | m2 | deallocation.rs:82:7:82:8 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:66:23:66:24 | m2 | invalid |
-| deallocation.rs:86:7:86:8 | m2 | deallocation.rs:66:23:66:24 | m2 | deallocation.rs:86:7:86:8 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:66:23:66:24 | m2 | invalid |
-| deallocation.rs:91:5:91:31 | ...::write::<...> | deallocation.rs:66:23:66:24 | m2 | deallocation.rs:91:5:91:31 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:66:23:66:24 | m2 | invalid |
-| deallocation.rs:111:13:111:18 | my_ptr | deallocation.rs:108:14:108:19 | my_ptr | deallocation.rs:111:13:111:18 | my_ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:108:14:108:19 | my_ptr | invalid |
-| deallocation.rs:126:14:126:15 | p1 | deallocation.rs:119:23:119:40 | ...::dangling | deallocation.rs:126:14:126:15 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:119:23:119:40 | ...::dangling | invalid |
-| deallocation.rs:127:14:127:15 | p2 | deallocation.rs:120:21:120:42 | ...::dangling_mut | deallocation.rs:127:14:127:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:120:21:120:42 | ...::dangling_mut | invalid |
-| deallocation.rs:128:14:128:15 | p3 | deallocation.rs:121:23:121:36 | ...::null | deallocation.rs:128:14:128:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:121:23:121:36 | ...::null | invalid |
-| deallocation.rs:176:15:176:16 | p1 | deallocation.rs:172:27:172:28 | p1 | deallocation.rs:176:15:176:16 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:172:27:172:28 | p1 | invalid |
-| deallocation.rs:210:18:210:20 | ptr | deallocation.rs:204:27:204:29 | ptr | deallocation.rs:210:18:210:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:204:27:204:29 | ptr | invalid |
+| deallocation.rs:32:16:32:17 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:32:16:32:17 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
+| deallocation.rs:33:16:33:17 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:33:16:33:17 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
+| deallocation.rs:37:14:37:33 | ...::read::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:37:14:37:33 | ...::read::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
+| deallocation.rs:44:6:44:7 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:44:6:44:7 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
+| deallocation.rs:49:5:49:25 | ...::write::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:49:5:49:25 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
+| deallocation.rs:76:16:76:17 | m2 | deallocation.rs:70:23:70:24 | m2 | deallocation.rs:76:16:76:17 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:70:23:70:24 | m2 | invalid |
+| deallocation.rs:81:16:81:17 | m2 | deallocation.rs:70:23:70:24 | m2 | deallocation.rs:81:16:81:17 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:70:23:70:24 | m2 | invalid |
+| deallocation.rs:86:7:86:8 | m2 | deallocation.rs:70:23:70:24 | m2 | deallocation.rs:86:7:86:8 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:70:23:70:24 | m2 | invalid |
+| deallocation.rs:90:7:90:8 | m2 | deallocation.rs:70:23:70:24 | m2 | deallocation.rs:90:7:90:8 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:70:23:70:24 | m2 | invalid |
+| deallocation.rs:95:5:95:31 | ...::write::<...> | deallocation.rs:70:23:70:24 | m2 | deallocation.rs:95:5:95:31 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:70:23:70:24 | m2 | invalid |
+| deallocation.rs:115:13:115:18 | my_ptr | deallocation.rs:112:14:112:19 | my_ptr | deallocation.rs:115:13:115:18 | my_ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:112:14:112:19 | my_ptr | invalid |
+| deallocation.rs:130:14:130:15 | p1 | deallocation.rs:123:23:123:40 | ...::dangling | deallocation.rs:130:14:130:15 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:123:23:123:40 | ...::dangling | invalid |
+| deallocation.rs:131:14:131:15 | p2 | deallocation.rs:124:21:124:42 | ...::dangling_mut | deallocation.rs:131:14:131:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:124:21:124:42 | ...::dangling_mut | invalid |
+| deallocation.rs:132:14:132:15 | p3 | deallocation.rs:125:23:125:36 | ...::null | deallocation.rs:132:14:132:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:125:23:125:36 | ...::null | invalid |
+| deallocation.rs:180:15:180:16 | p1 | deallocation.rs:176:27:176:28 | p1 | deallocation.rs:180:15:180:16 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:176:27:176:28 | p1 | invalid |
+| deallocation.rs:214:18:214:20 | ptr | deallocation.rs:208:27:208:29 | ptr | deallocation.rs:214:18:214:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:208:27:208:29 | ptr | invalid |
edges
| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:26:15:26:16 | m1 | provenance | |
-| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:33:35:33:36 | m1 | provenance | |
-| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:40:6:40:7 | m1 | provenance | |
-| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:45:27:45:28 | m1 | provenance | |
-| deallocation.rs:33:35:33:36 | m1 | deallocation.rs:33:14:33:33 | ...::read::<...> | provenance | MaD:1 Sink:MaD:1 |
-| deallocation.rs:45:27:45:28 | m1 | deallocation.rs:45:5:45:25 | ...::write::<...> | provenance | MaD:2 Sink:MaD:2 |
-| deallocation.rs:66:23:66:24 | m2 | deallocation.rs:72:16:72:17 | m2 | provenance | |
-| deallocation.rs:66:23:66:24 | m2 | deallocation.rs:77:16:77:17 | m2 | provenance | |
-| deallocation.rs:66:23:66:24 | m2 | deallocation.rs:82:7:82:8 | m2 | provenance | |
-| deallocation.rs:66:23:66:24 | m2 | deallocation.rs:86:7:86:8 | m2 | provenance | |
-| deallocation.rs:66:23:66:24 | m2 | deallocation.rs:91:33:91:34 | m2 | provenance | |
-| deallocation.rs:91:33:91:34 | m2 | deallocation.rs:91:5:91:31 | ...::write::<...> | provenance | MaD:2 Sink:MaD:2 |
-| deallocation.rs:108:14:108:19 | my_ptr | deallocation.rs:111:13:111:18 | my_ptr | provenance | |
-| deallocation.rs:119:6:119:7 | p1 | deallocation.rs:126:14:126:15 | p1 | provenance | |
-| deallocation.rs:119:23:119:40 | ...::dangling | deallocation.rs:119:23:119:42 | ...::dangling(...) | provenance | Src:MaD:3 MaD:3 |
-| deallocation.rs:119:23:119:42 | ...::dangling(...) | deallocation.rs:119:6:119:7 | p1 | provenance | |
-| deallocation.rs:120:6:120:7 | p2 | deallocation.rs:127:14:127:15 | p2 | provenance | |
-| deallocation.rs:120:21:120:42 | ...::dangling_mut | deallocation.rs:120:21:120:44 | ...::dangling_mut(...) | provenance | Src:MaD:4 MaD:4 |
-| deallocation.rs:120:21:120:44 | ...::dangling_mut(...) | deallocation.rs:120:6:120:7 | p2 | provenance | |
-| deallocation.rs:121:6:121:7 | p3 | deallocation.rs:128:14:128:15 | p3 | provenance | |
-| deallocation.rs:121:23:121:36 | ...::null | deallocation.rs:121:23:121:38 | ...::null(...) | provenance | Src:MaD:5 MaD:5 |
-| deallocation.rs:121:23:121:38 | ...::null(...) | deallocation.rs:121:6:121:7 | p3 | provenance | |
-| deallocation.rs:172:27:172:28 | p1 | deallocation.rs:176:15:176:16 | p1 | provenance | |
-| deallocation.rs:204:27:204:29 | ptr | deallocation.rs:210:18:210:20 | ptr | provenance | |
+| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:32:16:32:17 | m1 | provenance | |
+| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:33:16:33:17 | m1 | provenance | |
+| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:37:35:37:36 | m1 | provenance | |
+| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:44:6:44:7 | m1 | provenance | |
+| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:49:27:49:28 | m1 | provenance | |
+| deallocation.rs:37:35:37:36 | m1 | deallocation.rs:37:14:37:33 | ...::read::<...> | provenance | MaD:1 Sink:MaD:1 |
+| deallocation.rs:49:27:49:28 | m1 | deallocation.rs:49:5:49:25 | ...::write::<...> | provenance | MaD:2 Sink:MaD:2 |
+| deallocation.rs:70:23:70:24 | m2 | deallocation.rs:76:16:76:17 | m2 | provenance | |
+| deallocation.rs:70:23:70:24 | m2 | deallocation.rs:81:16:81:17 | m2 | provenance | |
+| deallocation.rs:70:23:70:24 | m2 | deallocation.rs:86:7:86:8 | m2 | provenance | |
+| deallocation.rs:70:23:70:24 | m2 | deallocation.rs:90:7:90:8 | m2 | provenance | |
+| deallocation.rs:70:23:70:24 | m2 | deallocation.rs:95:33:95:34 | m2 | provenance | |
+| deallocation.rs:95:33:95:34 | m2 | deallocation.rs:95:5:95:31 | ...::write::<...> | provenance | MaD:2 Sink:MaD:2 |
+| deallocation.rs:112:14:112:19 | my_ptr | deallocation.rs:115:13:115:18 | my_ptr | provenance | |
+| deallocation.rs:123:6:123:7 | p1 | deallocation.rs:130:14:130:15 | p1 | provenance | |
+| deallocation.rs:123:23:123:40 | ...::dangling | deallocation.rs:123:23:123:42 | ...::dangling(...) | provenance | Src:MaD:3 MaD:3 |
+| deallocation.rs:123:23:123:42 | ...::dangling(...) | deallocation.rs:123:6:123:7 | p1 | provenance | |
+| deallocation.rs:124:6:124:7 | p2 | deallocation.rs:131:14:131:15 | p2 | provenance | |
+| deallocation.rs:124:21:124:42 | ...::dangling_mut | deallocation.rs:124:21:124:44 | ...::dangling_mut(...) | provenance | Src:MaD:4 MaD:4 |
+| deallocation.rs:124:21:124:44 | ...::dangling_mut(...) | deallocation.rs:124:6:124:7 | p2 | provenance | |
+| deallocation.rs:125:6:125:7 | p3 | deallocation.rs:132:14:132:15 | p3 | provenance | |
+| deallocation.rs:125:23:125:36 | ...::null | deallocation.rs:125:23:125:38 | ...::null(...) | provenance | Src:MaD:5 MaD:5 |
+| deallocation.rs:125:23:125:38 | ...::null(...) | deallocation.rs:125:6:125:7 | p3 | provenance | |
+| deallocation.rs:176:27:176:28 | p1 | deallocation.rs:180:15:180:16 | p1 | provenance | |
+| deallocation.rs:208:27:208:29 | ptr | deallocation.rs:214:18:214:20 | ptr | provenance | |
models
| 1 | Sink: lang:core; crate::ptr::read; pointer-access; Argument[0] |
| 2 | Sink: lang:core; crate::ptr::write; pointer-access; Argument[0] |
@@ -48,34 +52,36 @@ models
nodes
| deallocation.rs:20:23:20:24 | m1 | semmle.label | m1 |
| deallocation.rs:26:15:26:16 | m1 | semmle.label | m1 |
-| deallocation.rs:33:14:33:33 | ...::read::<...> | semmle.label | ...::read::<...> |
-| deallocation.rs:33:35:33:36 | m1 | semmle.label | m1 |
-| deallocation.rs:40:6:40:7 | m1 | semmle.label | m1 |
-| deallocation.rs:45:5:45:25 | ...::write::<...> | semmle.label | ...::write::<...> |
-| deallocation.rs:45:27:45:28 | m1 | semmle.label | m1 |
-| deallocation.rs:66:23:66:24 | m2 | semmle.label | m2 |
-| deallocation.rs:72:16:72:17 | m2 | semmle.label | m2 |
-| deallocation.rs:77:16:77:17 | m2 | semmle.label | m2 |
-| deallocation.rs:82:7:82:8 | m2 | semmle.label | m2 |
+| deallocation.rs:32:16:32:17 | m1 | semmle.label | m1 |
+| deallocation.rs:33:16:33:17 | m1 | semmle.label | m1 |
+| deallocation.rs:37:14:37:33 | ...::read::<...> | semmle.label | ...::read::<...> |
+| deallocation.rs:37:35:37:36 | m1 | semmle.label | m1 |
+| deallocation.rs:44:6:44:7 | m1 | semmle.label | m1 |
+| deallocation.rs:49:5:49:25 | ...::write::<...> | semmle.label | ...::write::<...> |
+| deallocation.rs:49:27:49:28 | m1 | semmle.label | m1 |
+| deallocation.rs:70:23:70:24 | m2 | semmle.label | m2 |
+| deallocation.rs:76:16:76:17 | m2 | semmle.label | m2 |
+| deallocation.rs:81:16:81:17 | m2 | semmle.label | m2 |
| deallocation.rs:86:7:86:8 | m2 | semmle.label | m2 |
-| deallocation.rs:91:5:91:31 | ...::write::<...> | semmle.label | ...::write::<...> |
-| deallocation.rs:91:33:91:34 | m2 | semmle.label | m2 |
-| deallocation.rs:108:14:108:19 | my_ptr | semmle.label | my_ptr |
-| deallocation.rs:111:13:111:18 | my_ptr | semmle.label | my_ptr |
-| deallocation.rs:119:6:119:7 | p1 | semmle.label | p1 |
-| deallocation.rs:119:23:119:40 | ...::dangling | semmle.label | ...::dangling |
-| deallocation.rs:119:23:119:42 | ...::dangling(...) | semmle.label | ...::dangling(...) |
-| deallocation.rs:120:6:120:7 | p2 | semmle.label | p2 |
-| deallocation.rs:120:21:120:42 | ...::dangling_mut | semmle.label | ...::dangling_mut |
-| deallocation.rs:120:21:120:44 | ...::dangling_mut(...) | semmle.label | ...::dangling_mut(...) |
-| deallocation.rs:121:6:121:7 | p3 | semmle.label | p3 |
-| deallocation.rs:121:23:121:36 | ...::null | semmle.label | ...::null |
-| deallocation.rs:121:23:121:38 | ...::null(...) | semmle.label | ...::null(...) |
-| deallocation.rs:126:14:126:15 | p1 | semmle.label | p1 |
-| deallocation.rs:127:14:127:15 | p2 | semmle.label | p2 |
-| deallocation.rs:128:14:128:15 | p3 | semmle.label | p3 |
-| deallocation.rs:172:27:172:28 | p1 | semmle.label | p1 |
-| deallocation.rs:176:15:176:16 | p1 | semmle.label | p1 |
-| deallocation.rs:204:27:204:29 | ptr | semmle.label | ptr |
-| deallocation.rs:210:18:210:20 | ptr | semmle.label | ptr |
+| deallocation.rs:90:7:90:8 | m2 | semmle.label | m2 |
+| deallocation.rs:95:5:95:31 | ...::write::<...> | semmle.label | ...::write::<...> |
+| deallocation.rs:95:33:95:34 | m2 | semmle.label | m2 |
+| deallocation.rs:112:14:112:19 | my_ptr | semmle.label | my_ptr |
+| deallocation.rs:115:13:115:18 | my_ptr | semmle.label | my_ptr |
+| deallocation.rs:123:6:123:7 | p1 | semmle.label | p1 |
+| deallocation.rs:123:23:123:40 | ...::dangling | semmle.label | ...::dangling |
+| deallocation.rs:123:23:123:42 | ...::dangling(...) | semmle.label | ...::dangling(...) |
+| deallocation.rs:124:6:124:7 | p2 | semmle.label | p2 |
+| deallocation.rs:124:21:124:42 | ...::dangling_mut | semmle.label | ...::dangling_mut |
+| deallocation.rs:124:21:124:44 | ...::dangling_mut(...) | semmle.label | ...::dangling_mut(...) |
+| deallocation.rs:125:6:125:7 | p3 | semmle.label | p3 |
+| deallocation.rs:125:23:125:36 | ...::null | semmle.label | ...::null |
+| deallocation.rs:125:23:125:38 | ...::null(...) | semmle.label | ...::null(...) |
+| deallocation.rs:130:14:130:15 | p1 | semmle.label | p1 |
+| deallocation.rs:131:14:131:15 | p2 | semmle.label | p2 |
+| deallocation.rs:132:14:132:15 | p3 | semmle.label | p3 |
+| deallocation.rs:176:27:176:28 | p1 | semmle.label | p1 |
+| deallocation.rs:180:15:180:16 | p1 | semmle.label | p1 |
+| deallocation.rs:208:27:208:29 | ptr | semmle.label | ptr |
+| deallocation.rs:214:18:214:20 | ptr | semmle.label | ptr |
subpaths
diff --git a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
index 738abe774035..a1e3676b8601 100644
--- a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
@@ -27,6 +27,10 @@ pub fn test_alloc(mode: i32) {
let v6 = *m2; // $ MISSING: Alert
println!(" v5 = {v5} (!)"); // corrupt in practice
println!(" v6 = {v6} (!)"); // corrupt in practice
+
+ // test repeat reads (we don't want lots of very similar results for the same dealloc)
+ let v5b = *m1; // $ Alert[rust/access-invalid-pointer]=dealloc
+ let v5c = *m1; // $ Alert[rust/access-invalid-pointer]=dealloc
},
100 => {
// more reads
From e4cadf09ce49753261f0854336438a17705618c8 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 24 Mar 2025 11:01:47 +0000
Subject: [PATCH 033/409] Rust: Don't report excessive results for the same
source.
---
.../ql/src/queries/security/CWE-825/AccessInvalidPointer.ql | 5 +++++
.../security/CWE-825/AccessInvalidPointer.expected | 6 ------
rust/ql/test/query-tests/security/CWE-825/deallocation.rs | 4 ++--
3 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
index cb474d0bb0fb..15d13dcc4790 100644
--- a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
+++ b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
@@ -26,6 +26,11 @@ module AccessInvalidPointerConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node node) { node instanceof AccessInvalidPointer::Sink }
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof AccessInvalidPointer::Barrier }
+
+ predicate isBarrierOut(DataFlow::Node node) {
+ // make sinks barriers so that we only report the closest instance
+ isSink(node)
+ }
}
module AccessInvalidPointerFlow = DataFlow::Global;
diff --git a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
index 910252a4aca0..abab63199175 100644
--- a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
+++ b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
@@ -1,7 +1,5 @@
#select
| deallocation.rs:26:15:26:16 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:26:15:26:16 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
-| deallocation.rs:32:16:32:17 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:32:16:32:17 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
-| deallocation.rs:33:16:33:17 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:33:16:33:17 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
| deallocation.rs:37:14:37:33 | ...::read::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:37:14:37:33 | ...::read::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
| deallocation.rs:44:6:44:7 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:44:6:44:7 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
| deallocation.rs:49:5:49:25 | ...::write::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:49:5:49:25 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
@@ -18,8 +16,6 @@
| deallocation.rs:214:18:214:20 | ptr | deallocation.rs:208:27:208:29 | ptr | deallocation.rs:214:18:214:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:208:27:208:29 | ptr | invalid |
edges
| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:26:15:26:16 | m1 | provenance | |
-| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:32:16:32:17 | m1 | provenance | |
-| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:33:16:33:17 | m1 | provenance | |
| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:37:35:37:36 | m1 | provenance | |
| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:44:6:44:7 | m1 | provenance | |
| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:49:27:49:28 | m1 | provenance | |
@@ -52,8 +48,6 @@ models
nodes
| deallocation.rs:20:23:20:24 | m1 | semmle.label | m1 |
| deallocation.rs:26:15:26:16 | m1 | semmle.label | m1 |
-| deallocation.rs:32:16:32:17 | m1 | semmle.label | m1 |
-| deallocation.rs:33:16:33:17 | m1 | semmle.label | m1 |
| deallocation.rs:37:14:37:33 | ...::read::<...> | semmle.label | ...::read::<...> |
| deallocation.rs:37:35:37:36 | m1 | semmle.label | m1 |
| deallocation.rs:44:6:44:7 | m1 | semmle.label | m1 |
diff --git a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
index a1e3676b8601..77f687b5ae28 100644
--- a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
@@ -29,8 +29,8 @@ pub fn test_alloc(mode: i32) {
println!(" v6 = {v6} (!)"); // corrupt in practice
// test repeat reads (we don't want lots of very similar results for the same dealloc)
- let v5b = *m1; // $ Alert[rust/access-invalid-pointer]=dealloc
- let v5c = *m1; // $ Alert[rust/access-invalid-pointer]=dealloc
+ let v5b = *m1;
+ let v5c = *m1;
},
100 => {
// more reads
From 363128f4ecfa63084c4a7be819fc52e78fc015b4 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 24 Mar 2025 12:21:51 +0000
Subject: [PATCH 034/409] Apply suggestions from code review
Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com>
---
.../src/queries/security/CWE-825/AccessInvalidPointer.qhelp | 6 +++---
.../ql/src/queries/security/CWE-825/AccessInvalidPointer.ql | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp
index 2981564b9eec..2aa2b8abef8d 100644
--- a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp
+++ b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp
@@ -5,7 +5,7 @@
-Dereferencing an invalid or dangling pointer is undefined behavior. Memory may be corrupted
+Dereferencing an invalid or dangling pointer may cause undefined behavior. Memory may be corrupted
causing the program to crash or behave incorrectly, in some cases exposing the program to
potential attacks.
@@ -17,7 +17,7 @@ potential attacks.
When dereferencing a pointer in unsafe code, take care that the pointer is valid and
points to the intended data. Code may need to be rearranged or additional checks added to ensure
safety in all circumstances. If possible, rewrite the code using safe Rust types to avoid this
-class of problems altogether.
+kind of problems altogether.
@@ -32,7 +32,7 @@ undefined behavior:
-In this case undefined behavior can be avoided by rearranging the code so that the dereference
+In this case, undefined behavior can be avoided by rearranging the code so that the dereferencing
comes before the call to std::ptr::drop_in_place:
diff --git a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
index 15d13dcc4790..1d84fffe1ee0 100644
--- a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
+++ b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.ql
@@ -1,6 +1,6 @@
/**
* @name Access of invalid pointer
- * @description Dereferencing an invalid or dangling pointer is undefined behavior and may cause memory corruption.
+ * @description Dereferencing an invalid or dangling pointer causes undefined behavior and may result in memory corruption.
* @kind path-problem
* @problem.severity error
* @security-severity 7.5
From 82068a262d1463fcbb912419727a323780b6ec6c Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 24 Mar 2025 12:23:48 +0000
Subject: [PATCH 035/409] Rust: Further rephrasing.
---
rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp
index 2aa2b8abef8d..1c6a0452c53b 100644
--- a/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp
+++ b/rust/ql/src/queries/security/CWE-825/AccessInvalidPointer.qhelp
@@ -17,7 +17,7 @@ potential attacks.
When dereferencing a pointer in unsafe code, take care that the pointer is valid and
points to the intended data. Code may need to be rearranged or additional checks added to ensure
safety in all circumstances. If possible, rewrite the code using safe Rust types to avoid this
-kind of problems altogether.
+kind of problem altogether.
From 29a23a3d20deddbceb7c85db87ac42260c9b928a Mon Sep 17 00:00:00 2001
From: Marco Gario
Date: Wed, 26 Mar 2025 13:28:34 +0100
Subject: [PATCH 036/409] Update UseOfKnownVulnerableAction.ql
Name should not end in a `.`
---
actions/ql/src/Security/CWE-1395/UseOfKnownVulnerableAction.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actions/ql/src/Security/CWE-1395/UseOfKnownVulnerableAction.ql b/actions/ql/src/Security/CWE-1395/UseOfKnownVulnerableAction.ql
index 497a3b9feb9b..05603dae68bb 100644
--- a/actions/ql/src/Security/CWE-1395/UseOfKnownVulnerableAction.ql
+++ b/actions/ql/src/Security/CWE-1395/UseOfKnownVulnerableAction.ql
@@ -1,5 +1,5 @@
/**
- * @name Use of a known vulnerable action.
+ * @name Use of a known vulnerable action
* @description The workflow is using an action with known vulnerabilities.
* @kind problem
* @problem.severity error
From b1737858fa07cdcde9513bac72f738fee9a81dbf Mon Sep 17 00:00:00 2001
From: Marco Gario
Date: Wed, 26 Mar 2025 12:49:48 +0000
Subject: [PATCH 037/409] UntrustedCheckout: Try and differentiate between two
versions of the rule
---
actions/ql/src/Security/CWE-829/UntrustedCheckoutCritical.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actions/ql/src/Security/CWE-829/UntrustedCheckoutCritical.ql b/actions/ql/src/Security/CWE-829/UntrustedCheckoutCritical.ql
index c1d3729701d1..b004b26c603b 100644
--- a/actions/ql/src/Security/CWE-829/UntrustedCheckoutCritical.ql
+++ b/actions/ql/src/Security/CWE-829/UntrustedCheckoutCritical.ql
@@ -1,5 +1,5 @@
/**
- * @name Checkout of untrusted code in trusted context
+ * @name Checkout of untrusted code in trusted context with poisonable step
* @description Privileged workflows have read/write access to the base repository and access to secrets.
* By explicitly checking out and running the build script from a fork the untrusted code is running in an environment
* that is able to push to the base repository and to access secrets.
From 288fcb60928710b975adaa61a034968955b60e2c Mon Sep 17 00:00:00 2001
From: Marco Gario
Date: Wed, 26 Mar 2025 15:53:20 +0100
Subject: [PATCH 038/409] Update CWE-829 description for clarity
---
actions/ql/src/Security/CWE-829/UntrustedCheckoutCritical.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actions/ql/src/Security/CWE-829/UntrustedCheckoutCritical.ql b/actions/ql/src/Security/CWE-829/UntrustedCheckoutCritical.ql
index b004b26c603b..90feab533a47 100644
--- a/actions/ql/src/Security/CWE-829/UntrustedCheckoutCritical.ql
+++ b/actions/ql/src/Security/CWE-829/UntrustedCheckoutCritical.ql
@@ -1,5 +1,5 @@
/**
- * @name Checkout of untrusted code in trusted context with poisonable step
+ * @name Checkout of untrusted code in priviledged context
* @description Privileged workflows have read/write access to the base repository and access to secrets.
* By explicitly checking out and running the build script from a fork the untrusted code is running in an environment
* that is able to push to the base repository and to access secrets.
From 0a04191a6173d403c5ea6fc6bcad5a97a27ca77d Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 26 Mar 2025 15:06:03 +0000
Subject: [PATCH 039/409] Rust: Effect of merging main (duplicate results).
---
.../CWE-825/AccessInvalidPointer.expected | 35 +++++++++++++++----
1 file changed, 29 insertions(+), 6 deletions(-)
diff --git a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
index abab63199175..78c94169f195 100644
--- a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
+++ b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
@@ -1,7 +1,11 @@
#select
+| deallocation.rs:26:15:26:16 | m1 | deallocation.rs:20:3:20:21 | ...::dealloc | deallocation.rs:26:15:26:16 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:3:20:21 | ...::dealloc | invalid |
| deallocation.rs:26:15:26:16 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:26:15:26:16 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
+| deallocation.rs:37:14:37:33 | ...::read::<...> | deallocation.rs:20:3:20:21 | ...::dealloc | deallocation.rs:37:14:37:33 | ...::read::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:3:20:21 | ...::dealloc | invalid |
| deallocation.rs:37:14:37:33 | ...::read::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:37:14:37:33 | ...::read::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
+| deallocation.rs:44:6:44:7 | m1 | deallocation.rs:20:3:20:21 | ...::dealloc | deallocation.rs:44:6:44:7 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:3:20:21 | ...::dealloc | invalid |
| deallocation.rs:44:6:44:7 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:44:6:44:7 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
+| deallocation.rs:49:5:49:25 | ...::write::<...> | deallocation.rs:20:3:20:21 | ...::dealloc | deallocation.rs:49:5:49:25 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:3:20:21 | ...::dealloc | invalid |
| deallocation.rs:49:5:49:25 | ...::write::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:49:5:49:25 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
| deallocation.rs:76:16:76:17 | m2 | deallocation.rs:70:23:70:24 | m2 | deallocation.rs:76:16:76:17 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:70:23:70:24 | m2 | invalid |
| deallocation.rs:81:16:81:17 | m2 | deallocation.rs:70:23:70:24 | m2 | deallocation.rs:81:16:81:17 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:70:23:70:24 | m2 | invalid |
@@ -12,9 +16,16 @@
| deallocation.rs:130:14:130:15 | p1 | deallocation.rs:123:23:123:40 | ...::dangling | deallocation.rs:130:14:130:15 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:123:23:123:40 | ...::dangling | invalid |
| deallocation.rs:131:14:131:15 | p2 | deallocation.rs:124:21:124:42 | ...::dangling_mut | deallocation.rs:131:14:131:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:124:21:124:42 | ...::dangling_mut | invalid |
| deallocation.rs:132:14:132:15 | p3 | deallocation.rs:125:23:125:36 | ...::null | deallocation.rs:132:14:132:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:125:23:125:36 | ...::null | invalid |
+| deallocation.rs:180:15:180:16 | p1 | deallocation.rs:176:3:176:25 | ...::drop_in_place | deallocation.rs:180:15:180:16 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:176:3:176:25 | ...::drop_in_place | invalid |
| deallocation.rs:180:15:180:16 | p1 | deallocation.rs:176:27:176:28 | p1 | deallocation.rs:180:15:180:16 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:176:27:176:28 | p1 | invalid |
+| deallocation.rs:214:18:214:20 | ptr | deallocation.rs:208:3:208:25 | ...::drop_in_place | deallocation.rs:214:18:214:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:208:3:208:25 | ...::drop_in_place | invalid |
| deallocation.rs:214:18:214:20 | ptr | deallocation.rs:208:27:208:29 | ptr | deallocation.rs:214:18:214:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:208:27:208:29 | ptr | invalid |
edges
+| deallocation.rs:20:3:20:21 | ...::dealloc | deallocation.rs:20:23:20:24 | [post] m1 | provenance | Src:MaD:3 MaD:3 |
+| deallocation.rs:20:23:20:24 | [post] m1 | deallocation.rs:26:15:26:16 | m1 | provenance | |
+| deallocation.rs:20:23:20:24 | [post] m1 | deallocation.rs:37:35:37:36 | m1 | provenance | |
+| deallocation.rs:20:23:20:24 | [post] m1 | deallocation.rs:44:6:44:7 | m1 | provenance | |
+| deallocation.rs:20:23:20:24 | [post] m1 | deallocation.rs:49:27:49:28 | m1 | provenance | |
| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:26:15:26:16 | m1 | provenance | |
| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:37:35:37:36 | m1 | provenance | |
| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:44:6:44:7 | m1 | provenance | |
@@ -29,23 +40,31 @@ edges
| deallocation.rs:95:33:95:34 | m2 | deallocation.rs:95:5:95:31 | ...::write::<...> | provenance | MaD:2 Sink:MaD:2 |
| deallocation.rs:112:14:112:19 | my_ptr | deallocation.rs:115:13:115:18 | my_ptr | provenance | |
| deallocation.rs:123:6:123:7 | p1 | deallocation.rs:130:14:130:15 | p1 | provenance | |
-| deallocation.rs:123:23:123:40 | ...::dangling | deallocation.rs:123:23:123:42 | ...::dangling(...) | provenance | Src:MaD:3 MaD:3 |
+| deallocation.rs:123:23:123:40 | ...::dangling | deallocation.rs:123:23:123:42 | ...::dangling(...) | provenance | Src:MaD:4 MaD:4 |
| deallocation.rs:123:23:123:42 | ...::dangling(...) | deallocation.rs:123:6:123:7 | p1 | provenance | |
| deallocation.rs:124:6:124:7 | p2 | deallocation.rs:131:14:131:15 | p2 | provenance | |
-| deallocation.rs:124:21:124:42 | ...::dangling_mut | deallocation.rs:124:21:124:44 | ...::dangling_mut(...) | provenance | Src:MaD:4 MaD:4 |
+| deallocation.rs:124:21:124:42 | ...::dangling_mut | deallocation.rs:124:21:124:44 | ...::dangling_mut(...) | provenance | Src:MaD:5 MaD:5 |
| deallocation.rs:124:21:124:44 | ...::dangling_mut(...) | deallocation.rs:124:6:124:7 | p2 | provenance | |
| deallocation.rs:125:6:125:7 | p3 | deallocation.rs:132:14:132:15 | p3 | provenance | |
-| deallocation.rs:125:23:125:36 | ...::null | deallocation.rs:125:23:125:38 | ...::null(...) | provenance | Src:MaD:5 MaD:5 |
+| deallocation.rs:125:23:125:36 | ...::null | deallocation.rs:125:23:125:38 | ...::null(...) | provenance | Src:MaD:7 MaD:7 |
| deallocation.rs:125:23:125:38 | ...::null(...) | deallocation.rs:125:6:125:7 | p3 | provenance | |
+| deallocation.rs:176:3:176:25 | ...::drop_in_place | deallocation.rs:176:27:176:28 | [post] p1 | provenance | Src:MaD:6 MaD:6 |
+| deallocation.rs:176:27:176:28 | [post] p1 | deallocation.rs:180:15:180:16 | p1 | provenance | |
| deallocation.rs:176:27:176:28 | p1 | deallocation.rs:180:15:180:16 | p1 | provenance | |
+| deallocation.rs:208:3:208:25 | ...::drop_in_place | deallocation.rs:208:27:208:29 | [post] ptr | provenance | Src:MaD:6 MaD:6 |
+| deallocation.rs:208:27:208:29 | [post] ptr | deallocation.rs:214:18:214:20 | ptr | provenance | |
| deallocation.rs:208:27:208:29 | ptr | deallocation.rs:214:18:214:20 | ptr | provenance | |
models
| 1 | Sink: lang:core; crate::ptr::read; pointer-access; Argument[0] |
| 2 | Sink: lang:core; crate::ptr::write; pointer-access; Argument[0] |
-| 3 | Source: lang:core; crate::ptr::dangling; pointer-invalidate; ReturnValue |
-| 4 | Source: lang:core; crate::ptr::dangling_mut; pointer-invalidate; ReturnValue |
-| 5 | Source: lang:core; crate::ptr::null; pointer-invalidate; ReturnValue |
+| 3 | Source: lang:alloc; crate::alloc::dealloc; pointer-invalidate; Argument[0] |
+| 4 | Source: lang:core; crate::ptr::dangling; pointer-invalidate; ReturnValue |
+| 5 | Source: lang:core; crate::ptr::dangling_mut; pointer-invalidate; ReturnValue |
+| 6 | Source: lang:core; crate::ptr::drop_in_place; pointer-invalidate; Argument[0] |
+| 7 | Source: lang:core; crate::ptr::null; pointer-invalidate; ReturnValue |
nodes
+| deallocation.rs:20:3:20:21 | ...::dealloc | semmle.label | ...::dealloc |
+| deallocation.rs:20:23:20:24 | [post] m1 | semmle.label | [post] m1 |
| deallocation.rs:20:23:20:24 | m1 | semmle.label | m1 |
| deallocation.rs:26:15:26:16 | m1 | semmle.label | m1 |
| deallocation.rs:37:14:37:33 | ...::read::<...> | semmle.label | ...::read::<...> |
@@ -74,8 +93,12 @@ nodes
| deallocation.rs:130:14:130:15 | p1 | semmle.label | p1 |
| deallocation.rs:131:14:131:15 | p2 | semmle.label | p2 |
| deallocation.rs:132:14:132:15 | p3 | semmle.label | p3 |
+| deallocation.rs:176:3:176:25 | ...::drop_in_place | semmle.label | ...::drop_in_place |
+| deallocation.rs:176:27:176:28 | [post] p1 | semmle.label | [post] p1 |
| deallocation.rs:176:27:176:28 | p1 | semmle.label | p1 |
| deallocation.rs:180:15:180:16 | p1 | semmle.label | p1 |
+| deallocation.rs:208:3:208:25 | ...::drop_in_place | semmle.label | ...::drop_in_place |
+| deallocation.rs:208:27:208:29 | [post] ptr | semmle.label | [post] ptr |
| deallocation.rs:208:27:208:29 | ptr | semmle.label | ptr |
| deallocation.rs:214:18:214:20 | ptr | semmle.label | ptr |
subpaths
From c84e2cd7cb5467a38e603714c13ea617796c3d85 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 26 Mar 2025 15:35:44 +0000
Subject: [PATCH 040/409] Rust: Reduce the workaround (fixes duplicate
results).
---
.../security/AccessInvalidPointerExtensions.qll | 2 +-
.../CWE-825/AccessInvalidPointer.expected | 15 ---------------
2 files changed, 1 insertion(+), 16 deletions(-)
diff --git a/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll b/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
index 9f895ef6f87e..c20a4966edd8 100644
--- a/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
+++ b/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
@@ -50,7 +50,7 @@ module AccessInvalidPointer {
sourceNode(n, "pointer-invalidate") and
n.(FlowSummaryNode).getSourceElement() = ce.getFunction() and
arg = ce.getArgList().getAnArg() and
- this.asExpr().getExpr().getParentNode*() = arg
+ this.asExpr().getExpr().getParentNode+() = arg
)
}
}
diff --git a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
index 78c94169f195..ca5982fdb2d7 100644
--- a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
+++ b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
@@ -1,12 +1,8 @@
#select
| deallocation.rs:26:15:26:16 | m1 | deallocation.rs:20:3:20:21 | ...::dealloc | deallocation.rs:26:15:26:16 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:3:20:21 | ...::dealloc | invalid |
-| deallocation.rs:26:15:26:16 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:26:15:26:16 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
| deallocation.rs:37:14:37:33 | ...::read::<...> | deallocation.rs:20:3:20:21 | ...::dealloc | deallocation.rs:37:14:37:33 | ...::read::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:3:20:21 | ...::dealloc | invalid |
-| deallocation.rs:37:14:37:33 | ...::read::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:37:14:37:33 | ...::read::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
| deallocation.rs:44:6:44:7 | m1 | deallocation.rs:20:3:20:21 | ...::dealloc | deallocation.rs:44:6:44:7 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:3:20:21 | ...::dealloc | invalid |
-| deallocation.rs:44:6:44:7 | m1 | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:44:6:44:7 | m1 | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
| deallocation.rs:49:5:49:25 | ...::write::<...> | deallocation.rs:20:3:20:21 | ...::dealloc | deallocation.rs:49:5:49:25 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:3:20:21 | ...::dealloc | invalid |
-| deallocation.rs:49:5:49:25 | ...::write::<...> | deallocation.rs:20:23:20:24 | m1 | deallocation.rs:49:5:49:25 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:20:23:20:24 | m1 | invalid |
| deallocation.rs:76:16:76:17 | m2 | deallocation.rs:70:23:70:24 | m2 | deallocation.rs:76:16:76:17 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:70:23:70:24 | m2 | invalid |
| deallocation.rs:81:16:81:17 | m2 | deallocation.rs:70:23:70:24 | m2 | deallocation.rs:81:16:81:17 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:70:23:70:24 | m2 | invalid |
| deallocation.rs:86:7:86:8 | m2 | deallocation.rs:70:23:70:24 | m2 | deallocation.rs:86:7:86:8 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:70:23:70:24 | m2 | invalid |
@@ -17,19 +13,13 @@
| deallocation.rs:131:14:131:15 | p2 | deallocation.rs:124:21:124:42 | ...::dangling_mut | deallocation.rs:131:14:131:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:124:21:124:42 | ...::dangling_mut | invalid |
| deallocation.rs:132:14:132:15 | p3 | deallocation.rs:125:23:125:36 | ...::null | deallocation.rs:132:14:132:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:125:23:125:36 | ...::null | invalid |
| deallocation.rs:180:15:180:16 | p1 | deallocation.rs:176:3:176:25 | ...::drop_in_place | deallocation.rs:180:15:180:16 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:176:3:176:25 | ...::drop_in_place | invalid |
-| deallocation.rs:180:15:180:16 | p1 | deallocation.rs:176:27:176:28 | p1 | deallocation.rs:180:15:180:16 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:176:27:176:28 | p1 | invalid |
| deallocation.rs:214:18:214:20 | ptr | deallocation.rs:208:3:208:25 | ...::drop_in_place | deallocation.rs:214:18:214:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:208:3:208:25 | ...::drop_in_place | invalid |
-| deallocation.rs:214:18:214:20 | ptr | deallocation.rs:208:27:208:29 | ptr | deallocation.rs:214:18:214:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:208:27:208:29 | ptr | invalid |
edges
| deallocation.rs:20:3:20:21 | ...::dealloc | deallocation.rs:20:23:20:24 | [post] m1 | provenance | Src:MaD:3 MaD:3 |
| deallocation.rs:20:23:20:24 | [post] m1 | deallocation.rs:26:15:26:16 | m1 | provenance | |
| deallocation.rs:20:23:20:24 | [post] m1 | deallocation.rs:37:35:37:36 | m1 | provenance | |
| deallocation.rs:20:23:20:24 | [post] m1 | deallocation.rs:44:6:44:7 | m1 | provenance | |
| deallocation.rs:20:23:20:24 | [post] m1 | deallocation.rs:49:27:49:28 | m1 | provenance | |
-| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:26:15:26:16 | m1 | provenance | |
-| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:37:35:37:36 | m1 | provenance | |
-| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:44:6:44:7 | m1 | provenance | |
-| deallocation.rs:20:23:20:24 | m1 | deallocation.rs:49:27:49:28 | m1 | provenance | |
| deallocation.rs:37:35:37:36 | m1 | deallocation.rs:37:14:37:33 | ...::read::<...> | provenance | MaD:1 Sink:MaD:1 |
| deallocation.rs:49:27:49:28 | m1 | deallocation.rs:49:5:49:25 | ...::write::<...> | provenance | MaD:2 Sink:MaD:2 |
| deallocation.rs:70:23:70:24 | m2 | deallocation.rs:76:16:76:17 | m2 | provenance | |
@@ -50,10 +40,8 @@ edges
| deallocation.rs:125:23:125:38 | ...::null(...) | deallocation.rs:125:6:125:7 | p3 | provenance | |
| deallocation.rs:176:3:176:25 | ...::drop_in_place | deallocation.rs:176:27:176:28 | [post] p1 | provenance | Src:MaD:6 MaD:6 |
| deallocation.rs:176:27:176:28 | [post] p1 | deallocation.rs:180:15:180:16 | p1 | provenance | |
-| deallocation.rs:176:27:176:28 | p1 | deallocation.rs:180:15:180:16 | p1 | provenance | |
| deallocation.rs:208:3:208:25 | ...::drop_in_place | deallocation.rs:208:27:208:29 | [post] ptr | provenance | Src:MaD:6 MaD:6 |
| deallocation.rs:208:27:208:29 | [post] ptr | deallocation.rs:214:18:214:20 | ptr | provenance | |
-| deallocation.rs:208:27:208:29 | ptr | deallocation.rs:214:18:214:20 | ptr | provenance | |
models
| 1 | Sink: lang:core; crate::ptr::read; pointer-access; Argument[0] |
| 2 | Sink: lang:core; crate::ptr::write; pointer-access; Argument[0] |
@@ -65,7 +53,6 @@ models
nodes
| deallocation.rs:20:3:20:21 | ...::dealloc | semmle.label | ...::dealloc |
| deallocation.rs:20:23:20:24 | [post] m1 | semmle.label | [post] m1 |
-| deallocation.rs:20:23:20:24 | m1 | semmle.label | m1 |
| deallocation.rs:26:15:26:16 | m1 | semmle.label | m1 |
| deallocation.rs:37:14:37:33 | ...::read::<...> | semmle.label | ...::read::<...> |
| deallocation.rs:37:35:37:36 | m1 | semmle.label | m1 |
@@ -95,10 +82,8 @@ nodes
| deallocation.rs:132:14:132:15 | p3 | semmle.label | p3 |
| deallocation.rs:176:3:176:25 | ...::drop_in_place | semmle.label | ...::drop_in_place |
| deallocation.rs:176:27:176:28 | [post] p1 | semmle.label | [post] p1 |
-| deallocation.rs:176:27:176:28 | p1 | semmle.label | p1 |
| deallocation.rs:180:15:180:16 | p1 | semmle.label | p1 |
| deallocation.rs:208:3:208:25 | ...::drop_in_place | semmle.label | ...::drop_in_place |
| deallocation.rs:208:27:208:29 | [post] ptr | semmle.label | [post] ptr |
-| deallocation.rs:208:27:208:29 | ptr | semmle.label | ptr |
| deallocation.rs:214:18:214:20 | ptr | semmle.label | ptr |
subpaths
From d1a0237e87cf1f7fe780bba86b413e535d57d87c Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 27 Mar 2025 09:20:25 +0000
Subject: [PATCH 041/409] Rust: Correct a few details in the test.
---
.../security/CWE-825/AccessInvalidPointer.expected | 12 ++++++------
.../query-tests/security/CWE-825/deallocation.rs | 14 +++++++++-----
rust/ql/test/query-tests/security/CWE-825/main.rs | 2 +-
3 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
index ca5982fdb2d7..05fb54775121 100644
--- a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
+++ b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
@@ -13,7 +13,7 @@
| deallocation.rs:131:14:131:15 | p2 | deallocation.rs:124:21:124:42 | ...::dangling_mut | deallocation.rs:131:14:131:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:124:21:124:42 | ...::dangling_mut | invalid |
| deallocation.rs:132:14:132:15 | p3 | deallocation.rs:125:23:125:36 | ...::null | deallocation.rs:132:14:132:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:125:23:125:36 | ...::null | invalid |
| deallocation.rs:180:15:180:16 | p1 | deallocation.rs:176:3:176:25 | ...::drop_in_place | deallocation.rs:180:15:180:16 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:176:3:176:25 | ...::drop_in_place | invalid |
-| deallocation.rs:214:18:214:20 | ptr | deallocation.rs:208:3:208:25 | ...::drop_in_place | deallocation.rs:214:18:214:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:208:3:208:25 | ...::drop_in_place | invalid |
+| deallocation.rs:216:18:216:20 | ptr | deallocation.rs:210:3:210:25 | ...::drop_in_place | deallocation.rs:216:18:216:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:210:3:210:25 | ...::drop_in_place | invalid |
edges
| deallocation.rs:20:3:20:21 | ...::dealloc | deallocation.rs:20:23:20:24 | [post] m1 | provenance | Src:MaD:3 MaD:3 |
| deallocation.rs:20:23:20:24 | [post] m1 | deallocation.rs:26:15:26:16 | m1 | provenance | |
@@ -40,8 +40,8 @@ edges
| deallocation.rs:125:23:125:38 | ...::null(...) | deallocation.rs:125:6:125:7 | p3 | provenance | |
| deallocation.rs:176:3:176:25 | ...::drop_in_place | deallocation.rs:176:27:176:28 | [post] p1 | provenance | Src:MaD:6 MaD:6 |
| deallocation.rs:176:27:176:28 | [post] p1 | deallocation.rs:180:15:180:16 | p1 | provenance | |
-| deallocation.rs:208:3:208:25 | ...::drop_in_place | deallocation.rs:208:27:208:29 | [post] ptr | provenance | Src:MaD:6 MaD:6 |
-| deallocation.rs:208:27:208:29 | [post] ptr | deallocation.rs:214:18:214:20 | ptr | provenance | |
+| deallocation.rs:210:3:210:25 | ...::drop_in_place | deallocation.rs:210:27:210:29 | [post] ptr | provenance | Src:MaD:6 MaD:6 |
+| deallocation.rs:210:27:210:29 | [post] ptr | deallocation.rs:216:18:216:20 | ptr | provenance | |
models
| 1 | Sink: lang:core; crate::ptr::read; pointer-access; Argument[0] |
| 2 | Sink: lang:core; crate::ptr::write; pointer-access; Argument[0] |
@@ -83,7 +83,7 @@ nodes
| deallocation.rs:176:3:176:25 | ...::drop_in_place | semmle.label | ...::drop_in_place |
| deallocation.rs:176:27:176:28 | [post] p1 | semmle.label | [post] p1 |
| deallocation.rs:180:15:180:16 | p1 | semmle.label | p1 |
-| deallocation.rs:208:3:208:25 | ...::drop_in_place | semmle.label | ...::drop_in_place |
-| deallocation.rs:208:27:208:29 | [post] ptr | semmle.label | [post] ptr |
-| deallocation.rs:214:18:214:20 | ptr | semmle.label | ptr |
+| deallocation.rs:210:3:210:25 | ...::drop_in_place | semmle.label | ...::drop_in_place |
+| deallocation.rs:210:27:210:29 | [post] ptr | semmle.label | [post] ptr |
+| deallocation.rs:216:18:216:20 | ptr | semmle.label | ptr |
subpaths
diff --git a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
index 77f687b5ae28..de3b7cbc16c3 100644
--- a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
@@ -187,11 +187,13 @@ pub fn test_ptr_drop(mode: i32) {
}
}
+// --- qhelp examples ---
+
fn do_something(s: &String) {
println!(" s = {}", s);
}
-fn test_qhelp_test_good(ptr: *mut String) {
+fn test_qhelp_example_good(ptr: *mut String) {
unsafe {
do_something(&*ptr);
}
@@ -203,7 +205,7 @@ fn test_qhelp_test_good(ptr: *mut String) {
}
}
-fn test_qhelp_test_bad(ptr: *mut String) {
+fn test_qhelp_example_bad(ptr: *mut String) {
unsafe {
std::ptr::drop_in_place(ptr); // $ Source=drop_in_place
}
@@ -215,7 +217,7 @@ fn test_qhelp_test_bad(ptr: *mut String) {
}
}
-pub fn test_qhelp_tests() {
+pub fn test_qhelp_examples() {
let layout = std::alloc::Layout::new::<[String; 2]>();
unsafe {
let ptr = std::alloc::alloc(layout);
@@ -226,14 +228,16 @@ pub fn test_qhelp_tests() {
*ptr1 = String::from("123");
*ptr2 = String::from("456");
- test_qhelp_test_good(ptr1);
+ test_qhelp_example_good(ptr1);
- test_qhelp_test_bad(ptr2);
+ test_qhelp_example_bad(ptr2);
std::alloc::dealloc(ptr, layout);
}
}
+// --- Vec ---
+
pub fn test_vec_reserve() {
let mut vec1 = Vec::::new();
vec1.push(100);
diff --git a/rust/ql/test/query-tests/security/CWE-825/main.rs b/rust/ql/test/query-tests/security/CWE-825/main.rs
index 0b3fc423de12..ec135011f705 100644
--- a/rust/ql/test/query-tests/security/CWE-825/main.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/main.rs
@@ -129,7 +129,7 @@ fn main() {
test_ptr_drop(mode);
println!("test_qhelp_tests:");
- test_qhelp_tests();
+ test_qhelp_examples();
println!("test_vec_reserve:");
test_vec_reserve();
From 8598d619f231a19db8734712019668ce3c368437 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 27 Mar 2025 09:39:25 +0000
Subject: [PATCH 042/409] Rust: Add a test case involving a Drop method.
---
.../CWE-825/AccessInvalidPointer.expected | 14 +++++----
.../security/CWE-825/deallocation.rs | 29 +++++++++++++++++++
2 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
index 05fb54775121..479a53ba823d 100644
--- a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
+++ b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
@@ -13,7 +13,8 @@
| deallocation.rs:131:14:131:15 | p2 | deallocation.rs:124:21:124:42 | ...::dangling_mut | deallocation.rs:131:14:131:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:124:21:124:42 | ...::dangling_mut | invalid |
| deallocation.rs:132:14:132:15 | p3 | deallocation.rs:125:23:125:36 | ...::null | deallocation.rs:132:14:132:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:125:23:125:36 | ...::null | invalid |
| deallocation.rs:180:15:180:16 | p1 | deallocation.rs:176:3:176:25 | ...::drop_in_place | deallocation.rs:180:15:180:16 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:176:3:176:25 | ...::drop_in_place | invalid |
-| deallocation.rs:216:18:216:20 | ptr | deallocation.rs:210:3:210:25 | ...::drop_in_place | deallocation.rs:216:18:216:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:210:3:210:25 | ...::drop_in_place | invalid |
+| deallocation.rs:212:10:212:17 | self.ptr | deallocation.rs:212:10:212:17 | self.ptr | deallocation.rs:212:10:212:17 | self.ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:212:10:212:17 | self.ptr | invalid |
+| deallocation.rs:245:18:245:20 | ptr | deallocation.rs:239:3:239:25 | ...::drop_in_place | deallocation.rs:245:18:245:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:239:3:239:25 | ...::drop_in_place | invalid |
edges
| deallocation.rs:20:3:20:21 | ...::dealloc | deallocation.rs:20:23:20:24 | [post] m1 | provenance | Src:MaD:3 MaD:3 |
| deallocation.rs:20:23:20:24 | [post] m1 | deallocation.rs:26:15:26:16 | m1 | provenance | |
@@ -40,8 +41,8 @@ edges
| deallocation.rs:125:23:125:38 | ...::null(...) | deallocation.rs:125:6:125:7 | p3 | provenance | |
| deallocation.rs:176:3:176:25 | ...::drop_in_place | deallocation.rs:176:27:176:28 | [post] p1 | provenance | Src:MaD:6 MaD:6 |
| deallocation.rs:176:27:176:28 | [post] p1 | deallocation.rs:180:15:180:16 | p1 | provenance | |
-| deallocation.rs:210:3:210:25 | ...::drop_in_place | deallocation.rs:210:27:210:29 | [post] ptr | provenance | Src:MaD:6 MaD:6 |
-| deallocation.rs:210:27:210:29 | [post] ptr | deallocation.rs:216:18:216:20 | ptr | provenance | |
+| deallocation.rs:239:3:239:25 | ...::drop_in_place | deallocation.rs:239:27:239:29 | [post] ptr | provenance | Src:MaD:6 MaD:6 |
+| deallocation.rs:239:27:239:29 | [post] ptr | deallocation.rs:245:18:245:20 | ptr | provenance | |
models
| 1 | Sink: lang:core; crate::ptr::read; pointer-access; Argument[0] |
| 2 | Sink: lang:core; crate::ptr::write; pointer-access; Argument[0] |
@@ -83,7 +84,8 @@ nodes
| deallocation.rs:176:3:176:25 | ...::drop_in_place | semmle.label | ...::drop_in_place |
| deallocation.rs:176:27:176:28 | [post] p1 | semmle.label | [post] p1 |
| deallocation.rs:180:15:180:16 | p1 | semmle.label | p1 |
-| deallocation.rs:210:3:210:25 | ...::drop_in_place | semmle.label | ...::drop_in_place |
-| deallocation.rs:210:27:210:29 | [post] ptr | semmle.label | [post] ptr |
-| deallocation.rs:216:18:216:20 | ptr | semmle.label | ptr |
+| deallocation.rs:212:10:212:17 | self.ptr | semmle.label | self.ptr |
+| deallocation.rs:239:3:239:25 | ...::drop_in_place | semmle.label | ...::drop_in_place |
+| deallocation.rs:239:27:239:29 | [post] ptr | semmle.label | [post] ptr |
+| deallocation.rs:245:18:245:20 | ptr | semmle.label | ptr |
subpaths
diff --git a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
index de3b7cbc16c3..ed507fee408e 100644
--- a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
@@ -187,6 +187,35 @@ pub fn test_ptr_drop(mode: i32) {
}
}
+struct MyDropBuffer {
+ ptr: *mut u8,
+}
+
+impl MyDropBuffer {
+ unsafe fn new() -> MyDropBuffer {
+ let layout = std::alloc::Layout::from_size_align(1024, 1).unwrap();
+
+ MyDropBuffer {
+ ptr: std::alloc::alloc(layout),
+ }
+
+ // ...
+ }
+}
+
+impl Drop for MyDropBuffer {
+ fn drop(&mut self) {
+ let layout = std::alloc::Layout::from_size_align(1024, 1).unwrap();
+
+ unsafe {
+ _ = *self.ptr;
+ drop(*self.ptr); // $ MISSING: Source=drop SPURIOUS: Alert[rust/access-invalid-pointer]=drop
+ _ = *self.ptr; // $ MISSING: Alert[rust/access-invalid-pointer]=drop
+ std::alloc::dealloc(self.ptr, layout);
+ }
+ }
+}
+
// --- qhelp examples ---
fn do_something(s: &String) {
From 4e496fe7b2d7229610c63bc7f3f438bf98dc42c8 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 27 Mar 2025 09:48:53 +0000
Subject: [PATCH 043/409] Rust: Lets just not model 'drop' incorrectly, for
now.
---
.../ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml | 2 --
.../codeql/rust/security/AccessInvalidPointerExtensions.qll | 5 +++++
.../security/CWE-825/AccessInvalidPointer.expected | 2 --
rust/ql/test/query-tests/security/CWE-825/deallocation.rs | 2 +-
4 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
index 0960dd9c541a..69c5a1f3ba49 100644
--- a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
+++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
@@ -30,8 +30,6 @@ extensions:
pack: codeql/rust-all
extensible: sourceModel
data:
- # Mem
- - ["lang:core", "crate::mem::drop", "Argument[0]", "pointer-invalidate", "manual"]
# Ptr
- ["lang:core", "crate::ptr::drop_in_place", "Argument[0]", "pointer-invalidate", "manual"]
- ["lang:core", "crate::ptr::dangling", "ReturnValue", "pointer-invalidate", "manual"]
diff --git a/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll b/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
index c20a4966edd8..360a66e402c0 100644
--- a/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
+++ b/rust/ql/lib/codeql/rust/security/AccessInvalidPointerExtensions.qll
@@ -36,6 +36,11 @@ module AccessInvalidPointer {
/**
* A pointer invalidation from model data.
+ *
+ * Note: we don't currently support invalidation via the object itself rather than via a pointer, such as:
+ * ```
+ * drop(obj)
+ * ```
*/
private class ModelsAsDataSource extends Source {
ModelsAsDataSource() { sourceNode(this, "pointer-invalidate") }
diff --git a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
index 479a53ba823d..19dabe2fe8be 100644
--- a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
+++ b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
@@ -13,7 +13,6 @@
| deallocation.rs:131:14:131:15 | p2 | deallocation.rs:124:21:124:42 | ...::dangling_mut | deallocation.rs:131:14:131:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:124:21:124:42 | ...::dangling_mut | invalid |
| deallocation.rs:132:14:132:15 | p3 | deallocation.rs:125:23:125:36 | ...::null | deallocation.rs:132:14:132:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:125:23:125:36 | ...::null | invalid |
| deallocation.rs:180:15:180:16 | p1 | deallocation.rs:176:3:176:25 | ...::drop_in_place | deallocation.rs:180:15:180:16 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:176:3:176:25 | ...::drop_in_place | invalid |
-| deallocation.rs:212:10:212:17 | self.ptr | deallocation.rs:212:10:212:17 | self.ptr | deallocation.rs:212:10:212:17 | self.ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:212:10:212:17 | self.ptr | invalid |
| deallocation.rs:245:18:245:20 | ptr | deallocation.rs:239:3:239:25 | ...::drop_in_place | deallocation.rs:245:18:245:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:239:3:239:25 | ...::drop_in_place | invalid |
edges
| deallocation.rs:20:3:20:21 | ...::dealloc | deallocation.rs:20:23:20:24 | [post] m1 | provenance | Src:MaD:3 MaD:3 |
@@ -84,7 +83,6 @@ nodes
| deallocation.rs:176:3:176:25 | ...::drop_in_place | semmle.label | ...::drop_in_place |
| deallocation.rs:176:27:176:28 | [post] p1 | semmle.label | [post] p1 |
| deallocation.rs:180:15:180:16 | p1 | semmle.label | p1 |
-| deallocation.rs:212:10:212:17 | self.ptr | semmle.label | self.ptr |
| deallocation.rs:239:3:239:25 | ...::drop_in_place | semmle.label | ...::drop_in_place |
| deallocation.rs:239:27:239:29 | [post] ptr | semmle.label | [post] ptr |
| deallocation.rs:245:18:245:20 | ptr | semmle.label | ptr |
diff --git a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
index ed507fee408e..9ddb011c4b27 100644
--- a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
@@ -209,7 +209,7 @@ impl Drop for MyDropBuffer {
unsafe {
_ = *self.ptr;
- drop(*self.ptr); // $ MISSING: Source=drop SPURIOUS: Alert[rust/access-invalid-pointer]=drop
+ drop(*self.ptr); // $ MISSING: Source=drop
_ = *self.ptr; // $ MISSING: Alert[rust/access-invalid-pointer]=drop
std::alloc::dealloc(self.ptr, layout);
}
From 9ae271a7d14c688de98d7dc3d0e4e1d0ec76e10b Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Thu, 27 Mar 2025 12:55:36 +0000
Subject: [PATCH 044/409] Rust: Fix incidentally affected test merge conflict.
---
.../test/query-tests/security/CWE-020/RegexInjection.expected | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected b/rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected
index 0e1ea0fb063a..2902f9a4f51e 100644
--- a/rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected
+++ b/rust/ql/test/query-tests/security/CWE-020/RegexInjection.expected
@@ -3,14 +3,14 @@
edges
| main.rs:4:9:4:16 | username | main.rs:5:25:5:44 | MacroExpr | provenance | |
| main.rs:4:20:4:32 | ...::var | main.rs:4:20:4:40 | ...::var(...) [Ok] | provenance | Src:MaD:63 |
-| main.rs:4:20:4:40 | ...::var(...) [Ok] | main.rs:4:20:4:66 | ... .unwrap_or(...) | provenance | MaD:1607 |
+| main.rs:4:20:4:40 | ...::var(...) [Ok] | main.rs:4:20:4:66 | ... .unwrap_or(...) | provenance | MaD:1606 |
| main.rs:4:20:4:66 | ... .unwrap_or(...) | main.rs:4:9:4:16 | username | provenance | |
| main.rs:5:9:5:13 | regex | main.rs:6:26:6:30 | regex | provenance | |
| main.rs:5:17:5:45 | res | main.rs:5:25:5:44 | { ... } | provenance | |
| main.rs:5:25:5:44 | ...::format(...) | main.rs:5:17:5:45 | res | provenance | |
| main.rs:5:25:5:44 | ...::must_use(...) | main.rs:5:9:5:13 | regex | provenance | |
| main.rs:5:25:5:44 | MacroExpr | main.rs:5:25:5:44 | ...::format(...) | provenance | MaD:67 |
-| main.rs:5:25:5:44 | { ... } | main.rs:5:25:5:44 | ...::must_use(...) | provenance | MaD:3030 |
+| main.rs:5:25:5:44 | { ... } | main.rs:5:25:5:44 | ...::must_use(...) | provenance | MaD:3029 |
| main.rs:6:26:6:30 | regex | main.rs:6:25:6:30 | ®ex | provenance | |
nodes
| main.rs:4:9:4:16 | username | semmle.label | username |
From f6ac82aff04c09471f36281abe46225c121ab156 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Thu, 27 Mar 2025 15:10:14 +0100
Subject: [PATCH 045/409] Rust: Add more path resolution tests
---
.../library-tests/path-resolution/main.rs | 22 ++++
.../test/library-tests/path-resolution/my.rs | 6 +
.../path-resolution/my/my4/my5/mod.rs | 3 +
.../path-resolution/path-resolution.expected | 124 ++++++++++--------
4 files changed, 101 insertions(+), 54 deletions(-)
create mode 100644 rust/ql/test/library-tests/path-resolution/my/my4/my5/mod.rs
diff --git a/rust/ql/test/library-tests/path-resolution/main.rs b/rust/ql/test/library-tests/path-resolution/main.rs
index 7857ddc6cf5f..6b2052a1b3c9 100644
--- a/rust/ql/test/library-tests/path-resolution/main.rs
+++ b/rust/ql/test/library-tests/path-resolution/main.rs
@@ -473,6 +473,26 @@ mod m17 {
} // I99
}
+mod m18 {
+ fn f() {
+ println!("m18::f");
+ } // I101
+
+ pub mod m19 {
+ fn f() {
+ println!("m18::m19::f");
+ } // I102
+
+ pub mod m20 {
+ pub fn g() {
+ println!("m18::m19::m20::g");
+ super::f(); // $ item=I102
+ super::super::f(); // $ item=I101
+ } // I103
+ }
+ }
+}
+
fn main() {
my::nested::nested1::nested2::f(); // $ item=I4
my::f(); // $ item=I38
@@ -498,4 +518,6 @@ fn main() {
nested6::f(); // $ item=I116
nested8::f(); // $ item=I119
my3::f(); // $ item=I200
+ nested_f(); // $ MISSING: item=I201
+ m18::m19::m20::g(); // $ item=I103
}
diff --git a/rust/ql/test/library-tests/path-resolution/my.rs b/rust/ql/test/library-tests/path-resolution/my.rs
index fd9511a21181..487b0e78769c 100644
--- a/rust/ql/test/library-tests/path-resolution/my.rs
+++ b/rust/ql/test/library-tests/path-resolution/my.rs
@@ -10,3 +10,9 @@ pub fn h() {
println!("my.rs::h");
g(); // $ item=I7
} // I39
+
+mod my4 {
+ pub mod my5;
+}
+
+pub use my4::my5::f as nested_f; // $ MISSING: item=I201
diff --git a/rust/ql/test/library-tests/path-resolution/my/my4/my5/mod.rs b/rust/ql/test/library-tests/path-resolution/my/my4/my5/mod.rs
new file mode 100644
index 000000000000..25a94fee7c14
--- /dev/null
+++ b/rust/ql/test/library-tests/path-resolution/my/my4/my5/mod.rs
@@ -0,0 +1,3 @@
+pub fn f() {
+ println!("my/my4/my5/mod.rs::f");
+} // I201
diff --git a/rust/ql/test/library-tests/path-resolution/path-resolution.expected b/rust/ql/test/library-tests/path-resolution/path-resolution.expected
index 51dcc55b9e2d..6bf3f6567346 100644
--- a/rust/ql/test/library-tests/path-resolution/path-resolution.expected
+++ b/rust/ql/test/library-tests/path-resolution/path-resolution.expected
@@ -21,6 +21,9 @@ mod
| main.rs:294:1:348:1 | mod m15 |
| main.rs:350:1:442:1 | mod m16 |
| main.rs:444:1:474:1 | mod m17 |
+| main.rs:476:1:494:1 | mod m18 |
+| main.rs:481:5:493:5 | mod m19 |
+| main.rs:486:9:492:9 | mod m20 |
| my2/mod.rs:1:1:1:16 | mod nested2 |
| my2/mod.rs:12:1:12:12 | mod my3 |
| my2/nested2.rs:1:1:11:1 | mod nested3 |
@@ -30,6 +33,8 @@ mod
| my2/nested2.rs:21:1:27:1 | mod nested7 |
| my2/nested2.rs:22:5:26:5 | mod nested8 |
| my.rs:1:1:1:15 | mod nested |
+| my.rs:14:1:16:1 | mod my4 |
+| my.rs:15:5:15:16 | mod my5 |
| my/nested.rs:1:1:17:1 | mod nested1 |
| my/nested.rs:2:5:11:5 | mod nested2 |
resolvePath
@@ -51,7 +56,7 @@ resolvePath
| main.rs:30:17:30:21 | super | main.rs:18:5:36:5 | mod m2 |
| main.rs:30:17:30:24 | ...::f | main.rs:19:9:21:9 | fn f |
| main.rs:33:17:33:17 | f | main.rs:19:9:21:9 | fn f |
-| main.rs:40:9:40:13 | super | main.rs:1:1:501:2 | SourceFile |
+| main.rs:40:9:40:13 | super | main.rs:1:1:523:2 | SourceFile |
| main.rs:40:9:40:17 | ...::m1 | main.rs:13:1:37:1 | mod m1 |
| main.rs:40:9:40:21 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
| main.rs:40:9:40:24 | ...::g | main.rs:23:9:27:9 | fn g |
@@ -63,7 +68,7 @@ resolvePath
| main.rs:61:17:61:19 | Foo | main.rs:59:9:59:21 | struct Foo |
| main.rs:64:13:64:15 | Foo | main.rs:53:5:53:17 | struct Foo |
| main.rs:66:5:66:5 | f | main.rs:55:5:62:5 | fn f |
-| main.rs:68:5:68:8 | self | main.rs:1:1:501:2 | SourceFile |
+| main.rs:68:5:68:8 | self | main.rs:1:1:523:2 | SourceFile |
| main.rs:68:5:68:11 | ...::i | main.rs:71:1:83:1 | fn i |
| main.rs:74:13:74:15 | Foo | main.rs:48:1:48:13 | struct Foo |
| main.rs:81:17:81:19 | Foo | main.rs:77:9:79:9 | struct Foo |
@@ -77,7 +82,7 @@ resolvePath
| main.rs:87:57:87:66 | ...::g | my2/nested2.rs:7:9:9:9 | fn g |
| main.rs:87:80:87:86 | nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |
| main.rs:100:5:100:22 | f_defined_in_macro | main.rs:99:18:99:42 | fn f_defined_in_macro |
-| main.rs:117:13:117:17 | super | main.rs:1:1:501:2 | SourceFile |
+| main.rs:117:13:117:17 | super | main.rs:1:1:523:2 | SourceFile |
| main.rs:117:13:117:21 | ...::m5 | main.rs:103:1:107:1 | mod m5 |
| main.rs:118:9:118:9 | f | main.rs:104:5:106:5 | fn f |
| main.rs:118:9:118:9 | f | main.rs:110:5:112:5 | fn f |
@@ -210,56 +215,65 @@ resolvePath
| main.rs:465:9:465:18 | ...::f | main.rs:446:9:446:20 | fn f |
| main.rs:470:9:470:9 | g | main.rs:459:5:466:5 | fn g |
| main.rs:471:11:471:11 | S | main.rs:449:5:449:13 | struct S |
-| main.rs:477:5:477:6 | my | main.rs:1:1:1:7 | mod my |
-| main.rs:477:5:477:14 | ...::nested | my.rs:1:1:1:15 | mod nested |
-| main.rs:477:5:477:23 | ...::nested1 | my/nested.rs:1:1:17:1 | mod nested1 |
-| main.rs:477:5:477:32 | ...::nested2 | my/nested.rs:2:5:11:5 | mod nested2 |
-| main.rs:477:5:477:35 | ...::f | my/nested.rs:3:9:5:9 | fn f |
-| main.rs:478:5:478:6 | my | main.rs:1:1:1:7 | mod my |
-| main.rs:478:5:478:9 | ...::f | my.rs:5:1:7:1 | fn f |
-| main.rs:479:5:479:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 |
-| main.rs:479:5:479:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 |
-| main.rs:479:5:479:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |
-| main.rs:479:5:479:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f |
-| main.rs:480:5:480:5 | f | my2/nested2.rs:3:9:5:9 | fn f |
-| main.rs:481:5:481:5 | g | my2/nested2.rs:7:9:9:9 | fn g |
-| main.rs:482:5:482:9 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) |
-| main.rs:482:5:482:12 | ...::h | main.rs:50:1:69:1 | fn h |
-| main.rs:483:5:483:6 | m1 | main.rs:13:1:37:1 | mod m1 |
-| main.rs:483:5:483:10 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
-| main.rs:483:5:483:13 | ...::g | main.rs:23:9:27:9 | fn g |
-| main.rs:484:5:484:6 | m1 | main.rs:13:1:37:1 | mod m1 |
-| main.rs:484:5:484:10 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
-| main.rs:484:5:484:14 | ...::m3 | main.rs:29:9:35:9 | mod m3 |
-| main.rs:484:5:484:17 | ...::h | main.rs:30:27:34:13 | fn h |
-| main.rs:485:5:485:6 | m4 | main.rs:39:1:46:1 | mod m4 |
-| main.rs:485:5:485:9 | ...::i | main.rs:42:5:45:5 | fn i |
-| main.rs:486:5:486:5 | h | main.rs:50:1:69:1 | fn h |
-| main.rs:487:5:487:11 | f_alias | my2/nested2.rs:3:9:5:9 | fn f |
-| main.rs:488:5:488:11 | g_alias | my2/nested2.rs:7:9:9:9 | fn g |
-| main.rs:489:5:489:5 | j | main.rs:97:1:101:1 | fn j |
-| main.rs:490:5:490:6 | m6 | main.rs:109:1:120:1 | mod m6 |
-| main.rs:490:5:490:9 | ...::g | main.rs:114:5:119:5 | fn g |
-| main.rs:491:5:491:6 | m7 | main.rs:122:1:137:1 | mod m7 |
-| main.rs:491:5:491:9 | ...::f | main.rs:129:5:136:5 | fn f |
-| main.rs:492:5:492:6 | m8 | main.rs:139:1:193:1 | mod m8 |
-| main.rs:492:5:492:9 | ...::g | main.rs:177:5:192:5 | fn g |
-| main.rs:493:5:493:6 | m9 | main.rs:195:1:203:1 | mod m9 |
-| main.rs:493:5:493:9 | ...::f | main.rs:198:5:202:5 | fn f |
-| main.rs:494:5:494:7 | m11 | main.rs:226:1:263:1 | mod m11 |
-| main.rs:494:5:494:10 | ...::f | main.rs:231:5:234:5 | fn f |
-| main.rs:495:5:495:7 | m15 | main.rs:294:1:348:1 | mod m15 |
-| main.rs:495:5:495:10 | ...::f | main.rs:335:5:347:5 | fn f |
-| main.rs:496:5:496:7 | m16 | main.rs:350:1:442:1 | mod m16 |
-| main.rs:496:5:496:10 | ...::f | main.rs:417:5:441:5 | fn f |
-| main.rs:497:5:497:7 | m17 | main.rs:444:1:474:1 | mod m17 |
-| main.rs:497:5:497:10 | ...::f | main.rs:468:5:473:5 | fn f |
-| main.rs:498:5:498:11 | nested6 | my2/nested2.rs:14:5:18:5 | mod nested6 |
-| main.rs:498:5:498:14 | ...::f | my2/nested2.rs:15:9:17:9 | fn f |
-| main.rs:499:5:499:11 | nested8 | my2/nested2.rs:22:5:26:5 | mod nested8 |
-| main.rs:499:5:499:14 | ...::f | my2/nested2.rs:23:9:25:9 | fn f |
-| main.rs:500:5:500:7 | my3 | my2/mod.rs:12:1:12:12 | mod my3 |
-| main.rs:500:5:500:10 | ...::f | my2/my3/mod.rs:1:1:5:1 | fn f |
+| main.rs:489:17:489:21 | super | main.rs:481:5:493:5 | mod m19 |
+| main.rs:489:17:489:24 | ...::f | main.rs:482:9:484:9 | fn f |
+| main.rs:490:17:490:21 | super | main.rs:481:5:493:5 | mod m19 |
+| main.rs:490:17:490:28 | ...::super | main.rs:476:1:494:1 | mod m18 |
+| main.rs:490:17:490:31 | ...::f | main.rs:477:5:479:5 | fn f |
+| main.rs:497:5:497:6 | my | main.rs:1:1:1:7 | mod my |
+| main.rs:497:5:497:14 | ...::nested | my.rs:1:1:1:15 | mod nested |
+| main.rs:497:5:497:23 | ...::nested1 | my/nested.rs:1:1:17:1 | mod nested1 |
+| main.rs:497:5:497:32 | ...::nested2 | my/nested.rs:2:5:11:5 | mod nested2 |
+| main.rs:497:5:497:35 | ...::f | my/nested.rs:3:9:5:9 | fn f |
+| main.rs:498:5:498:6 | my | main.rs:1:1:1:7 | mod my |
+| main.rs:498:5:498:9 | ...::f | my.rs:5:1:7:1 | fn f |
+| main.rs:499:5:499:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 |
+| main.rs:499:5:499:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 |
+| main.rs:499:5:499:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |
+| main.rs:499:5:499:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f |
+| main.rs:500:5:500:5 | f | my2/nested2.rs:3:9:5:9 | fn f |
+| main.rs:501:5:501:5 | g | my2/nested2.rs:7:9:9:9 | fn g |
+| main.rs:502:5:502:9 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) |
+| main.rs:502:5:502:12 | ...::h | main.rs:50:1:69:1 | fn h |
+| main.rs:503:5:503:6 | m1 | main.rs:13:1:37:1 | mod m1 |
+| main.rs:503:5:503:10 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
+| main.rs:503:5:503:13 | ...::g | main.rs:23:9:27:9 | fn g |
+| main.rs:504:5:504:6 | m1 | main.rs:13:1:37:1 | mod m1 |
+| main.rs:504:5:504:10 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
+| main.rs:504:5:504:14 | ...::m3 | main.rs:29:9:35:9 | mod m3 |
+| main.rs:504:5:504:17 | ...::h | main.rs:30:27:34:13 | fn h |
+| main.rs:505:5:505:6 | m4 | main.rs:39:1:46:1 | mod m4 |
+| main.rs:505:5:505:9 | ...::i | main.rs:42:5:45:5 | fn i |
+| main.rs:506:5:506:5 | h | main.rs:50:1:69:1 | fn h |
+| main.rs:507:5:507:11 | f_alias | my2/nested2.rs:3:9:5:9 | fn f |
+| main.rs:508:5:508:11 | g_alias | my2/nested2.rs:7:9:9:9 | fn g |
+| main.rs:509:5:509:5 | j | main.rs:97:1:101:1 | fn j |
+| main.rs:510:5:510:6 | m6 | main.rs:109:1:120:1 | mod m6 |
+| main.rs:510:5:510:9 | ...::g | main.rs:114:5:119:5 | fn g |
+| main.rs:511:5:511:6 | m7 | main.rs:122:1:137:1 | mod m7 |
+| main.rs:511:5:511:9 | ...::f | main.rs:129:5:136:5 | fn f |
+| main.rs:512:5:512:6 | m8 | main.rs:139:1:193:1 | mod m8 |
+| main.rs:512:5:512:9 | ...::g | main.rs:177:5:192:5 | fn g |
+| main.rs:513:5:513:6 | m9 | main.rs:195:1:203:1 | mod m9 |
+| main.rs:513:5:513:9 | ...::f | main.rs:198:5:202:5 | fn f |
+| main.rs:514:5:514:7 | m11 | main.rs:226:1:263:1 | mod m11 |
+| main.rs:514:5:514:10 | ...::f | main.rs:231:5:234:5 | fn f |
+| main.rs:515:5:515:7 | m15 | main.rs:294:1:348:1 | mod m15 |
+| main.rs:515:5:515:10 | ...::f | main.rs:335:5:347:5 | fn f |
+| main.rs:516:5:516:7 | m16 | main.rs:350:1:442:1 | mod m16 |
+| main.rs:516:5:516:10 | ...::f | main.rs:417:5:441:5 | fn f |
+| main.rs:517:5:517:7 | m17 | main.rs:444:1:474:1 | mod m17 |
+| main.rs:517:5:517:10 | ...::f | main.rs:468:5:473:5 | fn f |
+| main.rs:518:5:518:11 | nested6 | my2/nested2.rs:14:5:18:5 | mod nested6 |
+| main.rs:518:5:518:14 | ...::f | my2/nested2.rs:15:9:17:9 | fn f |
+| main.rs:519:5:519:11 | nested8 | my2/nested2.rs:22:5:26:5 | mod nested8 |
+| main.rs:519:5:519:14 | ...::f | my2/nested2.rs:23:9:25:9 | fn f |
+| main.rs:520:5:520:7 | my3 | my2/mod.rs:12:1:12:12 | mod my3 |
+| main.rs:520:5:520:10 | ...::f | my2/my3/mod.rs:1:1:5:1 | fn f |
+| main.rs:522:5:522:7 | m18 | main.rs:476:1:494:1 | mod m18 |
+| main.rs:522:5:522:12 | ...::m19 | main.rs:481:5:493:5 | mod m19 |
+| main.rs:522:5:522:17 | ...::m20 | main.rs:486:9:492:9 | mod m20 |
+| main.rs:522:5:522:20 | ...::g | main.rs:487:13:491:13 | fn g |
| my2/mod.rs:5:5:5:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 |
| my2/mod.rs:5:5:5:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 |
| my2/mod.rs:5:5:5:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |
@@ -273,13 +287,15 @@ resolvePath
| my2/my3/mod.rs:3:5:3:5 | g | my2/mod.rs:3:1:6:1 | fn g |
| my2/my3/mod.rs:4:5:4:5 | h | main.rs:50:1:69:1 | fn h |
| my2/my3/mod.rs:7:5:7:9 | super | my2/mod.rs:1:1:12:13 | SourceFile |
-| my2/my3/mod.rs:7:5:7:16 | ...::super | main.rs:1:1:501:2 | SourceFile |
+| my2/my3/mod.rs:7:5:7:16 | ...::super | main.rs:1:1:523:2 | SourceFile |
| my2/my3/mod.rs:7:5:7:19 | ...::h | main.rs:50:1:69:1 | fn h |
| my2/my3/mod.rs:8:5:8:9 | super | my2/mod.rs:1:1:12:13 | SourceFile |
| my2/my3/mod.rs:8:5:8:12 | ...::g | my2/mod.rs:3:1:6:1 | fn g |
| my.rs:3:5:3:10 | nested | my.rs:1:1:1:15 | mod nested |
| my.rs:3:5:3:13 | ...::g | my/nested.rs:19:1:22:1 | fn g |
| my.rs:11:5:11:5 | g | my/nested.rs:19:1:22:1 | fn g |
+| my.rs:18:9:18:11 | my4 | my.rs:14:1:16:1 | mod my4 |
+| my.rs:18:9:18:16 | ...::my5 | my.rs:15:5:15:16 | mod my5 |
| my/nested.rs:9:13:9:13 | f | my/nested.rs:3:9:5:9 | fn f |
| my/nested.rs:15:9:15:15 | nested2 | my/nested.rs:2:5:11:5 | mod nested2 |
| my/nested.rs:15:9:15:18 | ...::f | my/nested.rs:3:9:5:9 | fn f |
From 2dcd7895ec963ce8379bb89b3923922a03b620b9 Mon Sep 17 00:00:00 2001
From: Taus
Date: Thu, 27 Mar 2025 15:27:42 +0000
Subject: [PATCH 046/409] Python: Modernise `py/mixed-tuple-returns`
Removes the dependence on points-to in favour of an approach based on
(local) data-flow.
I first tried a version that used type tracking, as this more accurately
mimics the behaviour of the old query. However, I soon discovered that
there were _many_ false positives in this setup. The main bad pattern I
saw was a helper function somewhere deep inside the code that both
receives and returns an argument that can be tuples with different sizes
and origins. In this case, global flow produces something akin to a
cartesian product of "n-tuples that flow into the function" and
"m-tuples that flow into the function" where m < n.
To combat this, I decided to instead focus on only flow _within_ a given
function (and so local data-flow was sufficient).
Additionally, another class of false positives I saw was cases where the
return type actually witnessed that the function in question could
return tuples of varying sizes. In this case it seems reasonable to not
flag these instances, since they are already (presumably) being checked
by a type checker.
More generally, if you've annotated the return type of the function with
anything (not just `Tuple[...]`), then there's probably little need to
flag it.
---
.../src/Functions/ReturnConsistentTupleSizes.ql | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/python/ql/src/Functions/ReturnConsistentTupleSizes.ql b/python/ql/src/Functions/ReturnConsistentTupleSizes.ql
index 9046f52cecbd..f0cb83067e0f 100644
--- a/python/ql/src/Functions/ReturnConsistentTupleSizes.ql
+++ b/python/ql/src/Functions/ReturnConsistentTupleSizes.ql
@@ -4,6 +4,7 @@
* @kind problem
* @tags reliability
* maintainability
+ * quality
* @problem.severity recommendation
* @sub-severity high
* @precision high
@@ -11,13 +12,15 @@
*/
import python
+import semmle.python.ApiGraphs
-predicate returns_tuple_of_size(Function func, int size, AstNode origin) {
- exists(Return return, TupleValue val |
+predicate returns_tuple_of_size(Function func, int size, Tuple tuple) {
+ exists(Return return, DataFlow::Node value |
+ value.asExpr() = return.getValue() and
return.getScope() = func and
- return.getValue().pointsTo(val, origin)
+ any(DataFlow::LocalSourceNode n | n.asExpr() = tuple).flowsTo(value)
|
- size = val.length()
+ size = count(int n | exists(tuple.getElt(n)))
)
}
@@ -25,6 +28,8 @@ from Function func, int s1, int s2, AstNode t1, AstNode t2
where
returns_tuple_of_size(func, s1, t1) and
returns_tuple_of_size(func, s2, t2) and
- s1 < s2
+ s1 < s2 and
+ // Don't report on functions that have a return type annotation
+ not exists(func.getDefinition().(FunctionExpr).getReturns())
select func, func.getQualifiedName() + " returns $@ and $@.", t1, "tuple of size " + s1, t2,
"tuple of size " + s2
From f601f4ad9ba2a5d56365ef7692b7f7b6bb8e1ee9 Mon Sep 17 00:00:00 2001
From: Taus
Date: Thu, 27 Mar 2025 15:31:28 +0000
Subject: [PATCH 047/409] Python: Update test expectations
As we're no longer tracking tuples across function boundaries, we lose
the result that related to this setup (which, as the preceding commit
explains, lead to a lot of false positives).
---
.../Functions/return_values/ReturnConsistentTupleSizes.expected | 1 -
1 file changed, 1 deletion(-)
diff --git a/python/ql/test/query-tests/Functions/return_values/ReturnConsistentTupleSizes.expected b/python/ql/test/query-tests/Functions/return_values/ReturnConsistentTupleSizes.expected
index fd4f1ee2dd70..2733ae8c26ac 100644
--- a/python/ql/test/query-tests/Functions/return_values/ReturnConsistentTupleSizes.expected
+++ b/python/ql/test/query-tests/Functions/return_values/ReturnConsistentTupleSizes.expected
@@ -1,2 +1 @@
| functions_test.py:306:1:306:39 | Function returning_different_tuple_sizes | returning_different_tuple_sizes returns $@ and $@. | functions_test.py:308:16:308:18 | Tuple | tuple of size 2 | functions_test.py:310:16:310:20 | Tuple | tuple of size 3 |
-| functions_test.py:324:1:324:50 | Function indirectly_returning_different_tuple_sizes | indirectly_returning_different_tuple_sizes returns $@ and $@. | functions_test.py:319:12:319:14 | Tuple | tuple of size 2 | functions_test.py:322:12:322:16 | Tuple | tuple of size 3 |
From 980c7d83dac91f6dae11d352a5603a45d23b52ca Mon Sep 17 00:00:00 2001
From: Taus
Date: Thu, 27 Mar 2025 15:33:00 +0000
Subject: [PATCH 048/409] Python: Add change note
---
.../2025-03-27-modernize-mixed-tuple-returns-query.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 python/ql/src/change-notes/2025-03-27-modernize-mixed-tuple-returns-query.md
diff --git a/python/ql/src/change-notes/2025-03-27-modernize-mixed-tuple-returns-query.md b/python/ql/src/change-notes/2025-03-27-modernize-mixed-tuple-returns-query.md
new file mode 100644
index 000000000000..9f527b6b5a3e
--- /dev/null
+++ b/python/ql/src/change-notes/2025-03-27-modernize-mixed-tuple-returns-query.md
@@ -0,0 +1,5 @@
+---
+category: minorAnalysis
+---
+
+- The `py/mixed-tuple-returns` query no longer flags instances where the tuple is passed into the function as an argument, as this lead to too many false positives.
From 68668b8e224a95591342610812b07e1f6489b113 Mon Sep 17 00:00:00 2001
From: Taus
Date: Thu, 27 Mar 2025 23:23:29 +0100
Subject: [PATCH 049/409] Python: Fix grammar in change note
---
.../2025-03-27-modernize-mixed-tuple-returns-query.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/python/ql/src/change-notes/2025-03-27-modernize-mixed-tuple-returns-query.md b/python/ql/src/change-notes/2025-03-27-modernize-mixed-tuple-returns-query.md
index 9f527b6b5a3e..57cf5c69a139 100644
--- a/python/ql/src/change-notes/2025-03-27-modernize-mixed-tuple-returns-query.md
+++ b/python/ql/src/change-notes/2025-03-27-modernize-mixed-tuple-returns-query.md
@@ -2,4 +2,4 @@
category: minorAnalysis
---
-- The `py/mixed-tuple-returns` query no longer flags instances where the tuple is passed into the function as an argument, as this lead to too many false positives.
+- The `py/mixed-tuple-returns` query no longer flags instances where the tuple is passed into the function as an argument, as this led to too many false positives.
From ff99d5c6880c347171183712a909bac3ec9bee85 Mon Sep 17 00:00:00 2001
From: Asger F
Date: Mon, 24 Mar 2025 12:36:52 +0100
Subject: [PATCH 050/409] JS: Add test for API graph through spread args
---
.../ql/test/ApiGraphs/spread/VerifyAssertions.expected | 2 ++
javascript/ql/test/ApiGraphs/spread/tst.js | 9 +++++++++
2 files changed, 11 insertions(+)
diff --git a/javascript/ql/test/ApiGraphs/spread/VerifyAssertions.expected b/javascript/ql/test/ApiGraphs/spread/VerifyAssertions.expected
index e69de29bb2d1..366c66f07636 100644
--- a/javascript/ql/test/ApiGraphs/spread/VerifyAssertions.expected
+++ b/javascript/ql/test/ApiGraphs/spread/VerifyAssertions.expected
@@ -0,0 +1,2 @@
+| tst.js:15:14:15:101 | /* def= ... r(0) */ | use moduleImport("something").getMember("exports").getMember("m2") has no outgoing edge labelled getParameter(0); it does have outgoing edges labelled getReceiver(), getReturn(). |
+| tst.js:16:14:16:101 | /* def= ... r(1) */ | use moduleImport("something").getMember("exports").getMember("m2") has no outgoing edge labelled getParameter(1); it does have outgoing edges labelled getReceiver(), getReturn(). |
diff --git a/javascript/ql/test/ApiGraphs/spread/tst.js b/javascript/ql/test/ApiGraphs/spread/tst.js
index cece4692043e..ebacd48d1f30 100644
--- a/javascript/ql/test/ApiGraphs/spread/tst.js
+++ b/javascript/ql/test/ApiGraphs/spread/tst.js
@@ -9,3 +9,12 @@ function f() {
lib.m1({
...f()
})
+
+function getArgs() {
+ return [
+ 'x', /* def=moduleImport("something").getMember("exports").getMember("m2").getParameter(0) */
+ 'y', /* def=moduleImport("something").getMember("exports").getMember("m2").getParameter(1) */
+ ]
+}
+
+lib.m2(...getArgs());
From 1ad471cb32559d8c6ff7505ff70aa199405ca5c9 Mon Sep 17 00:00:00 2001
From: Asger F
Date: Mon, 24 Mar 2025 13:33:58 +0100
Subject: [PATCH 051/409] JS: Track through spread/rest params in API graphs
---
.../ql/lib/semmle/javascript/ApiGraphs.qll | 50 +++++++++++++++++++
.../semmle/javascript/dataflow/Sources.qll | 6 +++
.../spread/VerifyAssertions.expected | 2 -
javascript/ql/test/ApiGraphs/spread/tst.js | 4 +-
.../Security/CWE-918/RequestForgery.expected | 12 +++++
.../Security/CWE-918/apollo.serverSide.ts | 4 +-
6 files changed, 72 insertions(+), 6 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index 4ef187de4d89..c53d7e4279c9 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -318,6 +318,11 @@ module API {
Node getParameter(int i) {
Stages::ApiStage::ref() and
result = this.getASuccessor(Label::parameter(i))
+ or
+ exists(int spreadIndex, string arrayProp |
+ result = this.getASuccessor(Label::spreadArgument(spreadIndex)).getMember(arrayProp) and
+ i = spreadIndex + arrayProp.toInt()
+ )
}
/**
@@ -860,6 +865,15 @@ module API {
.getStaticMember(name, DataFlow::MemberKind::getter())
.getAReturn()
)
+ or
+ exists(Function fun, DataFlow::InvokeNode invoke, int argIndex, Parameter rest |
+ fun.getRestParameter() = rest and
+ rest.flow() = pred and
+ invoke.getACallee() = fun and
+ invoke.getArgument(argIndex) = rhs and
+ argIndex >= rest.getIndex() and
+ lbl = Label::member((argIndex - rest.getIndex()).toString())
+ )
)
or
exists(DataFlow::ClassNode cls, string name |
@@ -888,6 +902,11 @@ module API {
i = -1 and lbl = Label::receiver()
)
or
+ exists(int i |
+ spreadArgumentPassing(base, i, rhs) and
+ lbl = Label::spreadArgument(i)
+ )
+ or
exists(DataFlow::SourceNode src, DataFlow::PropWrite pw |
use(base, src) and pw = trackUseNode(src).getAPropertyWrite() and rhs = pw.getRhs()
|
@@ -931,6 +950,21 @@ module API {
)
}
+ pragma[nomagic]
+ private int firstSpreadIndex(InvokeExpr expr) {
+ result = min(int i | expr.getArgument(i) instanceof SpreadElement)
+ }
+
+ private predicate spreadArgumentPassing(TApiNode base, int i, DataFlow::Node spreadArray) {
+ exists(DataFlow::Node use, DataFlow::SourceNode pred, int bound, InvokeExpr invoke |
+ use(base, use) and
+ pred = trackUseNode(use, _, bound, "") and
+ invoke = pred.getAnInvocation().asExpr() and
+ i = firstSpreadIndex(invoke) and
+ spreadArray = invoke.getArgument(i - bound).(SpreadElement).getOperand().flow()
+ )
+ }
+
/**
* Holds if `rhs` is the right-hand side of a definition of node `nd`.
*/
@@ -1579,6 +1613,9 @@ module API {
/** Gets the edge label for the receiver. */
LabelReceiver receiver() { any() }
+ /** Gets the edge label for a spread argument passed at index `i`. */
+ LabelSpreadArgument spreadArgument(int i) { result.getIndex() = i }
+
/** Gets the `return` edge label. */
LabelReturn return() { any() }
@@ -1628,6 +1665,7 @@ module API {
} or
MkLabelReceiver() or
MkLabelReturn() or
+ MkLabelSpreadArgument(int index) { index = [0 .. 10] } or
MkLabelDecoratedClass() or
MkLabelDecoratedMember() or
MkLabelDecoratedParameter() or
@@ -1743,6 +1781,18 @@ module API {
override string toString() { result = "getReceiver()" }
}
+ /** A label representing an array passed as a spread argument at a given index. */
+ class LabelSpreadArgument extends ApiLabel, MkLabelSpreadArgument {
+ private int index;
+
+ LabelSpreadArgument() { this = MkLabelSpreadArgument(index) }
+
+ /** The argument index at which the spread argument appears. */
+ int getIndex() { result = index }
+
+ override string toString() { result = "getSpreadArgument(" + index + ")" }
+ }
+
/** A label for a function that is a wrapper around another function. */
class LabelForwardingFunction extends ApiLabel, MkLabelForwardingFunction {
override string toString() { result = "getForwardingFunction()" }
diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll b/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll
index de103ef1c903..06729815e9a4 100644
--- a/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll
+++ b/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll
@@ -254,6 +254,12 @@ private module Cached {
cached
predicate invocation(DataFlow::SourceNode func, DataFlow::InvokeNode invoke) {
hasLocalSource(invoke.getCalleeNode(), func)
+ or
+ exists(ClassDefinition cls, SuperCall call |
+ hasLocalSource(cls.getSuperClass().flow(), func) and
+ call.getBinder() = cls.getConstructor().getBody() and
+ invoke = call.flow()
+ )
}
/**
diff --git a/javascript/ql/test/ApiGraphs/spread/VerifyAssertions.expected b/javascript/ql/test/ApiGraphs/spread/VerifyAssertions.expected
index 366c66f07636..e69de29bb2d1 100644
--- a/javascript/ql/test/ApiGraphs/spread/VerifyAssertions.expected
+++ b/javascript/ql/test/ApiGraphs/spread/VerifyAssertions.expected
@@ -1,2 +0,0 @@
-| tst.js:15:14:15:101 | /* def= ... r(0) */ | use moduleImport("something").getMember("exports").getMember("m2") has no outgoing edge labelled getParameter(0); it does have outgoing edges labelled getReceiver(), getReturn(). |
-| tst.js:16:14:16:101 | /* def= ... r(1) */ | use moduleImport("something").getMember("exports").getMember("m2") has no outgoing edge labelled getParameter(1); it does have outgoing edges labelled getReceiver(), getReturn(). |
diff --git a/javascript/ql/test/ApiGraphs/spread/tst.js b/javascript/ql/test/ApiGraphs/spread/tst.js
index ebacd48d1f30..67fed3ef13e1 100644
--- a/javascript/ql/test/ApiGraphs/spread/tst.js
+++ b/javascript/ql/test/ApiGraphs/spread/tst.js
@@ -12,8 +12,8 @@ lib.m1({
function getArgs() {
return [
- 'x', /* def=moduleImport("something").getMember("exports").getMember("m2").getParameter(0) */
- 'y', /* def=moduleImport("something").getMember("exports").getMember("m2").getParameter(1) */
+ 'x', /* def=moduleImport("something").getMember("exports").getMember("m2").getSpreadArgument(0).getArrayElement() */
+ 'y', /* def=moduleImport("something").getMember("exports").getMember("m2").getSpreadArgument(0).getArrayElement() */
]
}
diff --git a/javascript/ql/test/query-tests/Security/CWE-918/RequestForgery.expected b/javascript/ql/test/query-tests/Security/CWE-918/RequestForgery.expected
index 6b33506d502f..78b02c5f7db4 100644
--- a/javascript/ql/test/query-tests/Security/CWE-918/RequestForgery.expected
+++ b/javascript/ql/test/query-tests/Security/CWE-918/RequestForgery.expected
@@ -1,5 +1,6 @@
#select
| apollo.serverSide.ts:8:39:8:64 | get(fil ... => {}) | apollo.serverSide.ts:7:36:7:44 | { files } | apollo.serverSide.ts:8:43:8:50 | file.url | The $@ of this request depends on a $@. | apollo.serverSide.ts:8:43:8:50 | file.url | URL | apollo.serverSide.ts:7:36:7:44 | { files } | user-provided value |
+| apollo.serverSide.ts:18:37:18:62 | get(fil ... => {}) | apollo.serverSide.ts:17:34:17:42 | { files } | apollo.serverSide.ts:18:41:18:48 | file.url | The $@ of this request depends on a $@. | apollo.serverSide.ts:18:41:18:48 | file.url | URL | apollo.serverSide.ts:17:34:17:42 | { files } | user-provided value |
| axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | axiosInterceptors.serverSide.js:19:21:19:28 | req.body | axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | The $@ of this request depends on a $@. | axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | endpoint | axiosInterceptors.serverSide.js:19:21:19:28 | req.body | user-provided value |
| serverSide.js:18:5:18:20 | request(tainted) | serverSide.js:14:29:14:35 | req.url | serverSide.js:18:13:18:19 | tainted | The $@ of this request depends on a $@. | serverSide.js:18:13:18:19 | tainted | URL | serverSide.js:14:29:14:35 | req.url | user-provided value |
| serverSide.js:20:5:20:24 | request.get(tainted) | serverSide.js:14:29:14:35 | req.url | serverSide.js:20:17:20:23 | tainted | The $@ of this request depends on a $@. | serverSide.js:20:17:20:23 | tainted | URL | serverSide.js:14:29:14:35 | req.url | user-provided value |
@@ -31,6 +32,11 @@ edges
| apollo.serverSide.ts:8:13:8:17 | files | apollo.serverSide.ts:8:28:8:31 | file | provenance | |
| apollo.serverSide.ts:8:28:8:31 | file | apollo.serverSide.ts:8:43:8:46 | file | provenance | |
| apollo.serverSide.ts:8:43:8:46 | file | apollo.serverSide.ts:8:43:8:50 | file.url | provenance | |
+| apollo.serverSide.ts:17:34:17:42 | files | apollo.serverSide.ts:18:11:18:15 | files | provenance | |
+| apollo.serverSide.ts:17:34:17:42 | { files } | apollo.serverSide.ts:17:34:17:42 | files | provenance | |
+| apollo.serverSide.ts:18:11:18:15 | files | apollo.serverSide.ts:18:26:18:29 | file | provenance | |
+| apollo.serverSide.ts:18:26:18:29 | file | apollo.serverSide.ts:18:41:18:44 | file | provenance | |
+| apollo.serverSide.ts:18:41:18:44 | file | apollo.serverSide.ts:18:41:18:48 | file.url | provenance | |
| axiosInterceptors.serverSide.js:19:11:19:17 | { url } | axiosInterceptors.serverSide.js:19:11:19:28 | url | provenance | |
| axiosInterceptors.serverSide.js:19:11:19:28 | url | axiosInterceptors.serverSide.js:20:23:20:25 | url | provenance | |
| axiosInterceptors.serverSide.js:19:21:19:28 | req.body | axiosInterceptors.serverSide.js:19:11:19:17 | { url } | provenance | |
@@ -91,6 +97,12 @@ nodes
| apollo.serverSide.ts:8:28:8:31 | file | semmle.label | file |
| apollo.serverSide.ts:8:43:8:46 | file | semmle.label | file |
| apollo.serverSide.ts:8:43:8:50 | file.url | semmle.label | file.url |
+| apollo.serverSide.ts:17:34:17:42 | files | semmle.label | files |
+| apollo.serverSide.ts:17:34:17:42 | { files } | semmle.label | { files } |
+| apollo.serverSide.ts:18:11:18:15 | files | semmle.label | files |
+| apollo.serverSide.ts:18:26:18:29 | file | semmle.label | file |
+| apollo.serverSide.ts:18:41:18:44 | file | semmle.label | file |
+| apollo.serverSide.ts:18:41:18:48 | file.url | semmle.label | file.url |
| axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | semmle.label | userProvidedUrl |
| axiosInterceptors.serverSide.js:19:11:19:17 | { url } | semmle.label | { url } |
| axiosInterceptors.serverSide.js:19:11:19:28 | url | semmle.label | url |
diff --git a/javascript/ql/test/query-tests/Security/CWE-918/apollo.serverSide.ts b/javascript/ql/test/query-tests/Security/CWE-918/apollo.serverSide.ts
index 1d6aabd87fa5..0f1c4afa554c 100644
--- a/javascript/ql/test/query-tests/Security/CWE-918/apollo.serverSide.ts
+++ b/javascript/ql/test/query-tests/Security/CWE-918/apollo.serverSide.ts
@@ -14,8 +14,8 @@ function createApolloServer(typeDefs) {
const resolvers2 = {
Mutation: {
- downloadFiles: async (_, { files }) => { // $ MISSING: Source[js/request-forgery]
- files.forEach((file) => { get(file.url, (res) => {}); }); // $ MISSING: Alert[js/request-forgery] Sink[js/request-forgery]
+ downloadFiles: async (_, { files }) => { // $ Source[js/request-forgery]
+ files.forEach((file) => { get(file.url, (res) => {}); }); // $ Alert[js/request-forgery] Sink[js/request-forgery]
return true;
},
},
From b834ffe246afb01eff645c0049063a68204da6cc Mon Sep 17 00:00:00 2001
From: Asger F
Date: Thu, 27 Mar 2025 20:53:32 +0100
Subject: [PATCH 052/409] JS: Fix a bad join order
---
javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index c53d7e4279c9..f7b7a3e96d48 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -955,12 +955,17 @@ module API {
result = min(int i | expr.getArgument(i) instanceof SpreadElement)
}
+ pragma[nomagic]
+ private InvokeExpr getAnInvocationWithSpread(DataFlow::SourceNode node, int i) {
+ result = node.getAnInvocation().asExpr() and
+ i = firstSpreadIndex(result)
+ }
+
private predicate spreadArgumentPassing(TApiNode base, int i, DataFlow::Node spreadArray) {
exists(DataFlow::Node use, DataFlow::SourceNode pred, int bound, InvokeExpr invoke |
use(base, use) and
pred = trackUseNode(use, _, bound, "") and
- invoke = pred.getAnInvocation().asExpr() and
- i = firstSpreadIndex(invoke) and
+ invoke = getAnInvocationWithSpread(pred, i) and
spreadArray = invoke.getArgument(i - bound).(SpreadElement).getOperand().flow()
)
}
From ce7a0fd094e5b1b131aa85daefff69014dd3f2fe Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Fri, 28 Mar 2025 10:45:54 +0000
Subject: [PATCH 053/409] Rust: Test for sinks inside sources.
---
.../security/CWE-825/AccessInvalidPointer.expected | 14 ++++++++------
.../query-tests/security/CWE-825/deallocation.rs | 5 ++++-
2 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
index 19dabe2fe8be..9479cffc7f5e 100644
--- a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
+++ b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected
@@ -13,7 +13,8 @@
| deallocation.rs:131:14:131:15 | p2 | deallocation.rs:124:21:124:42 | ...::dangling_mut | deallocation.rs:131:14:131:15 | p2 | This operation dereferences a pointer that may be $@. | deallocation.rs:124:21:124:42 | ...::dangling_mut | invalid |
| deallocation.rs:132:14:132:15 | p3 | deallocation.rs:125:23:125:36 | ...::null | deallocation.rs:132:14:132:15 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:125:23:125:36 | ...::null | invalid |
| deallocation.rs:180:15:180:16 | p1 | deallocation.rs:176:3:176:25 | ...::drop_in_place | deallocation.rs:180:15:180:16 | p1 | This operation dereferences a pointer that may be $@. | deallocation.rs:176:3:176:25 | ...::drop_in_place | invalid |
-| deallocation.rs:245:18:245:20 | ptr | deallocation.rs:239:3:239:25 | ...::drop_in_place | deallocation.rs:245:18:245:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:239:3:239:25 | ...::drop_in_place | invalid |
+| deallocation.rs:189:29:189:30 | p3 | deallocation.rs:189:29:189:30 | p3 | deallocation.rs:189:29:189:30 | p3 | This operation dereferences a pointer that may be $@. | deallocation.rs:189:29:189:30 | p3 | invalid |
+| deallocation.rs:248:18:248:20 | ptr | deallocation.rs:242:3:242:25 | ...::drop_in_place | deallocation.rs:248:18:248:20 | ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:242:3:242:25 | ...::drop_in_place | invalid |
edges
| deallocation.rs:20:3:20:21 | ...::dealloc | deallocation.rs:20:23:20:24 | [post] m1 | provenance | Src:MaD:3 MaD:3 |
| deallocation.rs:20:23:20:24 | [post] m1 | deallocation.rs:26:15:26:16 | m1 | provenance | |
@@ -40,8 +41,8 @@ edges
| deallocation.rs:125:23:125:38 | ...::null(...) | deallocation.rs:125:6:125:7 | p3 | provenance | |
| deallocation.rs:176:3:176:25 | ...::drop_in_place | deallocation.rs:176:27:176:28 | [post] p1 | provenance | Src:MaD:6 MaD:6 |
| deallocation.rs:176:27:176:28 | [post] p1 | deallocation.rs:180:15:180:16 | p1 | provenance | |
-| deallocation.rs:239:3:239:25 | ...::drop_in_place | deallocation.rs:239:27:239:29 | [post] ptr | provenance | Src:MaD:6 MaD:6 |
-| deallocation.rs:239:27:239:29 | [post] ptr | deallocation.rs:245:18:245:20 | ptr | provenance | |
+| deallocation.rs:242:3:242:25 | ...::drop_in_place | deallocation.rs:242:27:242:29 | [post] ptr | provenance | Src:MaD:6 MaD:6 |
+| deallocation.rs:242:27:242:29 | [post] ptr | deallocation.rs:248:18:248:20 | ptr | provenance | |
models
| 1 | Sink: lang:core; crate::ptr::read; pointer-access; Argument[0] |
| 2 | Sink: lang:core; crate::ptr::write; pointer-access; Argument[0] |
@@ -83,7 +84,8 @@ nodes
| deallocation.rs:176:3:176:25 | ...::drop_in_place | semmle.label | ...::drop_in_place |
| deallocation.rs:176:27:176:28 | [post] p1 | semmle.label | [post] p1 |
| deallocation.rs:180:15:180:16 | p1 | semmle.label | p1 |
-| deallocation.rs:239:3:239:25 | ...::drop_in_place | semmle.label | ...::drop_in_place |
-| deallocation.rs:239:27:239:29 | [post] ptr | semmle.label | [post] ptr |
-| deallocation.rs:245:18:245:20 | ptr | semmle.label | ptr |
+| deallocation.rs:189:29:189:30 | p3 | semmle.label | p3 |
+| deallocation.rs:242:3:242:25 | ...::drop_in_place | semmle.label | ...::drop_in_place |
+| deallocation.rs:242:27:242:29 | [post] ptr | semmle.label | [post] ptr |
+| deallocation.rs:248:18:248:20 | ptr | semmle.label | ptr |
subpaths
diff --git a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
index 9ddb011c4b27..dde42aa9414b 100644
--- a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
+++ b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs
@@ -163,7 +163,7 @@ pub fn test_drop() {
pub fn test_ptr_drop(mode: i32) {
let layout = std::alloc::Layout::new::>();
unsafe {
- let p1 = std::alloc::alloc(layout) as *mut Vec; // *mut i64
+ let p1 = std::alloc::alloc(layout) as *mut Vec;
let p2 = p1;
*p1 = vec!(1, 2, 3);
@@ -184,6 +184,9 @@ pub fn test_ptr_drop(mode: i32) {
let v4 = (*p2)[0]; // $ MISSING: Alert
println!(" v4 = {v4} (!)"); // corrupt in practice
}
+
+ let p3 = std::alloc::alloc(layout) as *mut Vec;
+ std::ptr::drop_in_place((*p3).as_mut_ptr()); // $ SPURIOUS: Alert[rust/access-invalid-pointer]
}
}
From 00753a1fe40a8de525d54e77163ba904166f4b9c Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Fri, 28 Mar 2025 14:41:59 +0100
Subject: [PATCH 054/409] C#: Address review comments.
---
.../stringinterpolation/stringInterpolation.ql | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/csharp/ql/test/library-tests/stringinterpolation/stringInterpolation.ql b/csharp/ql/test/library-tests/stringinterpolation/stringInterpolation.ql
index 21b33b12b56d..f4d683858105 100644
--- a/csharp/ql/test/library-tests/stringinterpolation/stringInterpolation.ql
+++ b/csharp/ql/test/library-tests/stringinterpolation/stringInterpolation.ql
@@ -1,11 +1,9 @@
import csharp
-query predicate inserts(InterpolatedStringExpr expr, Expr e) {
- expr.getAnInsert() = e // and inSpecificSource(expr)
-}
+query predicate inserts(InterpolatedStringExpr expr, Expr e) { expr.getAnInsert() = e }
query predicate texts(InterpolatedStringExpr expr, StringLiteral literal) {
- expr.getAText() = literal // and inSpecificSource(expr)
+ expr.getAText() = literal
}
query predicate interpolationInsertsWithAlign(InterpolatedStringExpr expr, Expr insert, Expr align) {
From 605cf359706695f0dbba46c411a393861297d9bf Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Thu, 27 Mar 2025 15:10:25 +0100
Subject: [PATCH 055/409] Rust: More path resolution improvements
---
.../codeql/rust/internal/PathResolution.qll | 101 ++++++++++++++----
.../library-tests/path-resolution/main.rs | 2 +-
.../test/library-tests/path-resolution/my.rs | 2 +-
.../path-resolution/path-resolution.expected | 2 +
4 files changed, 84 insertions(+), 23 deletions(-)
diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll
index 2128bb8e7a82..ae4ed9cf7265 100644
--- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll
+++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll
@@ -116,7 +116,7 @@ abstract class ItemNode extends Locatable {
}
pragma[nomagic]
- private ItemNode getASuccessorRec(string name) {
+ ItemNode getASuccessorRec(string name) {
sourceFileEdge(this, name, result)
or
this = result.getImmediateParent() and
@@ -613,11 +613,11 @@ private predicate fileModule(SourceFile f, string name, Folder folder) {
}
/**
- * Holds if `m` is a `mod name;` module declaration happening in a file named
- * `fileName.rs`, inside the folder `parent`.
+ * Holds if `m` is a `mod name;` module declaration, where the corresponding
+ * module file needs to be looked up in `lookup` or one of its descandants.
*/
-private predicate modImport(Module m, string fileName, string name, Folder parent) {
- exists(File f |
+private predicate modImport0(Module m, string name, Folder lookup) {
+ exists(File f, Folder parent, string fileName |
f = m.getFile() and
not m.hasItemList() and
// TODO: handle
@@ -629,17 +629,63 @@ private predicate modImport(Module m, string fileName, string name, Folder paren
name = m.getName().getText() and
parent = f.getParentContainer() and
fileName = f.getStem()
+ |
+ // sibling import
+ lookup = parent and
+ (
+ m.getFile() = any(CrateItemNode c).getModuleNode().(SourceFileItemNode).getFile()
+ or
+ m.getFile().getBaseName() = "mod.rs"
+ )
+ or
+ // child import
+ lookup = parent.getFolder(fileName)
+ )
+}
+
+/**
+ * Holds if `m` is a `mod name;` module declaration, which happens inside a
+ * nested module, and `pred -> succ` is a module edge leading to `m`.
+ */
+private predicate modImportNested(ModuleItemNode m, ModuleItemNode pred, ModuleItemNode succ) {
+ pred.getAnItemInScope() = succ and
+ (
+ modImport0(m, _, _) and
+ succ = m
+ or
+ modImportNested(m, succ, _)
+ )
+}
+
+/**
+ * Holds if `m` is a `mod name;` module declaration, which happens inside a
+ * nested module, where `ancestor` is a reflexive transitive ancestor module
+ * of `m` with corresponding lookup folder `lookup`.
+ */
+private predicate modImportNestedLookup(Module m, ModuleItemNode ancestor, Folder lookup) {
+ modImport0(m, _, lookup) and
+ modImportNested(m, ancestor, _) and
+ not modImportNested(m, _, ancestor)
+ or
+ exists(ModuleItemNode m1, Folder mid |
+ modImportNestedLookup(m, m1, mid) and
+ modImportNested(m, m1, ancestor) and
+ lookup = mid.getFolder(m1.getName())
)
}
/** Holds if `m` is a `mod name;` item importing file `f`. */
private predicate fileImport(Module m, SourceFile f) {
- exists(string fileName, string name, Folder parent | modImport(m, fileName, name, parent) |
- // sibling import
+ exists(string name, Folder parent |
+ modImport0(m, name, _) and
fileModule(f, name, parent)
+ |
+ // `m` is not inside a nested module
+ modImport0(m, name, parent) and
+ not modImportNested(m, _, _)
or
- // child import
- fileModule(f, name, parent.getFolder(fileName))
+ // `m` is inside a nested module
+ modImportNestedLookup(m, m, parent)
)
}
@@ -651,7 +697,7 @@ pragma[nomagic]
private predicate fileImportEdge(Module mod, string name, ItemNode item) {
exists(SourceFileItemNode f |
fileImport(mod, f) and
- item = f.getASuccessor(name)
+ item = f.getASuccessorRec(name)
)
}
@@ -660,7 +706,7 @@ private predicate fileImportEdge(Module mod, string name, ItemNode item) {
*/
pragma[nomagic]
private predicate crateDefEdge(CrateItemNode c, string name, ItemNode i) {
- i = c.getModuleNode().getASuccessor(name) and
+ i = c.getModuleNode().getASuccessorRec(name) and
not i instanceof Crate
}
@@ -742,7 +788,16 @@ private predicate unqualifiedPathLookup(RelevantPath p, string name, Namespace n
// lookup in an outer scope, but only if the item is not declared in inner scope
exists(ItemNode mid |
unqualifiedPathLookup(p, name, ns, mid) and
- not declares(mid, ns, name)
+ not declares(mid, ns, name) and
+ not name = ["super", "self"] and
+ not (
+ name = "Self" and
+ mid = any(ImplOrTraitItemNode i).getAnItemInSelfScope()
+ ) and
+ not (
+ name = "crate" and
+ mid = any(CrateItemNode i).getASourceFile()
+ )
|
// nested modules do not have unqualified access to items from outer modules,
// except for items declared at top-level in the source file
@@ -943,15 +998,19 @@ private predicate useImportEdge(Use use, string name, ItemNode item) {
encl.getADescendant() = use and
item = getASuccessor(used, name, ns) and
// glob imports can be shadowed
- not declares(encl, ns, name)
+ not declares(encl, ns, name) and
+ not name = ["super", "self", "Self", "crate"]
)
- else item = used
- |
- not tree.hasRename() and
- name = item.getName()
- or
- name = tree.getRename().getName().getText() and
- name != "_"
+ else (
+ item = used and
+ (
+ not tree.hasRename() and
+ name = item.getName()
+ or
+ name = tree.getRename().getName().getText() and
+ name != "_"
+ )
+ )
)
}
@@ -961,7 +1020,7 @@ private module Debug {
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
filepath.matches("%/main.rs") and
- startline = 1
+ startline = [1, 3]
)
}
diff --git a/rust/ql/test/library-tests/path-resolution/main.rs b/rust/ql/test/library-tests/path-resolution/main.rs
index 6b2052a1b3c9..374f290b00e1 100644
--- a/rust/ql/test/library-tests/path-resolution/main.rs
+++ b/rust/ql/test/library-tests/path-resolution/main.rs
@@ -518,6 +518,6 @@ fn main() {
nested6::f(); // $ item=I116
nested8::f(); // $ item=I119
my3::f(); // $ item=I200
- nested_f(); // $ MISSING: item=I201
+ nested_f(); // $ item=I201
m18::m19::m20::g(); // $ item=I103
}
diff --git a/rust/ql/test/library-tests/path-resolution/my.rs b/rust/ql/test/library-tests/path-resolution/my.rs
index 487b0e78769c..2dcb1c76aebc 100644
--- a/rust/ql/test/library-tests/path-resolution/my.rs
+++ b/rust/ql/test/library-tests/path-resolution/my.rs
@@ -15,4 +15,4 @@ mod my4 {
pub mod my5;
}
-pub use my4::my5::f as nested_f; // $ MISSING: item=I201
+pub use my4::my5::f as nested_f; // $ item=I201
diff --git a/rust/ql/test/library-tests/path-resolution/path-resolution.expected b/rust/ql/test/library-tests/path-resolution/path-resolution.expected
index 6bf3f6567346..235ad7451c56 100644
--- a/rust/ql/test/library-tests/path-resolution/path-resolution.expected
+++ b/rust/ql/test/library-tests/path-resolution/path-resolution.expected
@@ -270,6 +270,7 @@ resolvePath
| main.rs:519:5:519:14 | ...::f | my2/nested2.rs:23:9:25:9 | fn f |
| main.rs:520:5:520:7 | my3 | my2/mod.rs:12:1:12:12 | mod my3 |
| main.rs:520:5:520:10 | ...::f | my2/my3/mod.rs:1:1:5:1 | fn f |
+| main.rs:521:5:521:12 | nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f |
| main.rs:522:5:522:7 | m18 | main.rs:476:1:494:1 | mod m18 |
| main.rs:522:5:522:12 | ...::m19 | main.rs:481:5:493:5 | mod m19 |
| main.rs:522:5:522:17 | ...::m20 | main.rs:486:9:492:9 | mod m20 |
@@ -296,6 +297,7 @@ resolvePath
| my.rs:11:5:11:5 | g | my/nested.rs:19:1:22:1 | fn g |
| my.rs:18:9:18:11 | my4 | my.rs:14:1:16:1 | mod my4 |
| my.rs:18:9:18:16 | ...::my5 | my.rs:15:5:15:16 | mod my5 |
+| my.rs:18:9:18:19 | ...::f | my/my4/my5/mod.rs:1:1:3:1 | fn f |
| my/nested.rs:9:13:9:13 | f | my/nested.rs:3:9:5:9 | fn f |
| my/nested.rs:15:9:15:15 | nested2 | my/nested.rs:2:5:11:5 | mod nested2 |
| my/nested.rs:15:9:15:18 | ...::f | my/nested.rs:3:9:5:9 | fn f |
From 52b889f008c310ac3bc03f56d4310559f6d5a342 Mon Sep 17 00:00:00 2001
From: Edward Minnix III
Date: Sat, 8 Mar 2025 17:16:22 -0500
Subject: [PATCH 056/409] Support when a property is specified by a string
literal instead of a `nameof` expression
In earlier versions of the Razor generator, a string literal was used
instead of a `nameof` expression in order to indicate the name of the
property being modified. This means we need to look up the property by
name instead of using a more explicit access.
---
.../csharp/frameworks/microsoft/aspnetcore/Components.qll | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/microsoft/aspnetcore/Components.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/microsoft/aspnetcore/Components.qll
index be937661b477..5fb79418c27e 100644
--- a/csharp/ql/lib/semmle/code/csharp/frameworks/microsoft/aspnetcore/Components.qll
+++ b/csharp/ql/lib/semmle/code/csharp/frameworks/microsoft/aspnetcore/Components.qll
@@ -159,7 +159,13 @@ private module JumpNodes {
*/
Property getParameterProperty() {
result.getAnAttribute() instanceof MicrosoftAspNetCoreComponentsParameterAttribute and
- exists(NameOfExpr ne | ne = this.getArgument(1) | result.getAnAccess() = ne.getAccess())
+ (
+ exists(NameOfExpr ne | ne = this.getArgument(1) | result.getAnAccess() = ne.getAccess())
+ or
+ exists(string propertyName | propertyName = this.getArgument(1).(StringLiteral).getValue() |
+ result.hasName(propertyName)
+ )
+ )
}
/**
From 3d0a85b3cd5a608e964e865dffe27d16a0f636c8 Mon Sep 17 00:00:00 2001
From: Edward Minnix III
Date: Sat, 8 Mar 2025 17:18:15 -0500
Subject: [PATCH 057/409] Add test case using string literal in property name
---
.../microsoft/aspnetcore/blazor/NameList2.cs | 50 +++++++++++++++++++
.../microsoft/aspnetcore/blazor/Xss.expected | 3 ++
.../blazor/remoteFlowSource.expected | 3 ++
3 files changed, 56 insertions(+)
create mode 100644 csharp/ql/test/library-tests/frameworks/microsoft/aspnetcore/blazor/NameList2.cs
diff --git a/csharp/ql/test/library-tests/frameworks/microsoft/aspnetcore/blazor/NameList2.cs b/csharp/ql/test/library-tests/frameworks/microsoft/aspnetcore/blazor/NameList2.cs
new file mode 100644
index 000000000000..d27d6f2dcde9
--- /dev/null
+++ b/csharp/ql/test/library-tests/frameworks/microsoft/aspnetcore/blazor/NameList2.cs
@@ -0,0 +1,50 @@
+namespace VulnerableBlazorApp.Components
+{
+ using System.Collections.Generic;
+ using Microsoft.AspNetCore.Components;
+
+ [RouteAttribute("/names2/{name?}")]
+ public partial class NameList2 : Microsoft.AspNetCore.Components.ComponentBase
+ {
+ protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder)
+ {
+ if (Names is not null)
+ {
+ builder.OpenElement(0, "div");
+ builder.OpenElement(1, "ul");
+ foreach (var name in Names)
+ {
+ builder.OpenElement(2, "li");
+ builder.OpenComponent(3);
+ builder.AddComponentParameter(4, "TheName", name);
+ builder.CloseComponent();
+ builder.CloseElement();
+ }
+ builder.CloseElement();
+ builder.CloseElement();
+ }
+
+ builder.OpenElement(5, "div");
+ builder.OpenElement(6, "p");
+ builder.AddContent(7, "Name: ");
+ builder.OpenComponent(8);
+ builder.AddComponentParameter(9, "TheName", Name);
+ builder.CloseComponent();
+ builder.CloseElement();
+ }
+
+ [Parameter]
+ public string Name { get; set; }
+
+ protected override void OnParametersSet()
+ {
+ if (Name is not null)
+ {
+ Names.Add(Name);
+ }
+ }
+
+
+ public List Names { get; set; } = new List();
+ }
+}
\ No newline at end of file
diff --git a/csharp/ql/test/library-tests/frameworks/microsoft/aspnetcore/blazor/Xss.expected b/csharp/ql/test/library-tests/frameworks/microsoft/aspnetcore/blazor/Xss.expected
index 951269f2b580..3b9a54fafb3d 100644
--- a/csharp/ql/test/library-tests/frameworks/microsoft/aspnetcore/blazor/Xss.expected
+++ b/csharp/ql/test/library-tests/frameworks/microsoft/aspnetcore/blazor/Xss.expected
@@ -1,12 +1,15 @@
edges
+| NameList2.cs:31:57:31:60 | access to property Name : String | Name.cs:13:53:13:59 | access to property TheName | provenance | Sink:MaD:149 |
| NameList.cs:31:99:31:102 | access to property Name : String | Name.cs:13:53:13:59 | access to property TheName | provenance | Sink:MaD:149 |
nodes
| Components_Pages_TestPage_razor.g.cs:138:15:138:22 | access to property UrlParam | semmle.label | access to property UrlParam |
| Components_Pages_TestPage_razor.g.cs:188:18:188:27 | access to property QueryParam | semmle.label | access to property QueryParam |
| Name.cs:13:53:13:59 | access to property TheName | semmle.label | access to property TheName |
+| NameList2.cs:31:57:31:60 | access to property Name : String | semmle.label | access to property Name : String |
| NameList.cs:31:99:31:102 | access to property Name : String | semmle.label | access to property Name : String |
subpaths
#select
| Components_Pages_TestPage_razor.g.cs:138:15:138:22 | access to property UrlParam | Components_Pages_TestPage_razor.g.cs:138:15:138:22 | access to property UrlParam | Components_Pages_TestPage_razor.g.cs:138:15:138:22 | access to property UrlParam | $@ flows to here and is written to HTML or JavaScript. | Components_Pages_TestPage_razor.g.cs:138:15:138:22 | access to property UrlParam | User-provided value |
| Components_Pages_TestPage_razor.g.cs:188:18:188:27 | access to property QueryParam | Components_Pages_TestPage_razor.g.cs:188:18:188:27 | access to property QueryParam | Components_Pages_TestPage_razor.g.cs:188:18:188:27 | access to property QueryParam | $@ flows to here and is written to HTML or JavaScript. | Components_Pages_TestPage_razor.g.cs:188:18:188:27 | access to property QueryParam | User-provided value |
+| Name.cs:13:53:13:59 | access to property TheName | NameList2.cs:31:57:31:60 | access to property Name : String | Name.cs:13:53:13:59 | access to property TheName | $@ flows to here and is written to HTML or JavaScript. | NameList2.cs:31:57:31:60 | access to property Name : String | User-provided value |
| Name.cs:13:53:13:59 | access to property TheName | NameList.cs:31:99:31:102 | access to property Name : String | Name.cs:13:53:13:59 | access to property TheName | $@ flows to here and is written to HTML or JavaScript. | NameList.cs:31:99:31:102 | access to property Name : String | User-provided value |
diff --git a/csharp/ql/test/library-tests/frameworks/microsoft/aspnetcore/blazor/remoteFlowSource.expected b/csharp/ql/test/library-tests/frameworks/microsoft/aspnetcore/blazor/remoteFlowSource.expected
index 2a9268cf01e3..e1b3724f44d6 100644
--- a/csharp/ql/test/library-tests/frameworks/microsoft/aspnetcore/blazor/remoteFlowSource.expected
+++ b/csharp/ql/test/library-tests/frameworks/microsoft/aspnetcore/blazor/remoteFlowSource.expected
@@ -2,6 +2,9 @@
| Components_Pages_TestPage_razor.g.cs:138:15:138:22 | access to property UrlParam | ASP.NET Core component route parameter |
| Components_Pages_TestPage_razor.g.cs:176:1:176:10 | access to property QueryParam | external |
| Components_Pages_TestPage_razor.g.cs:188:18:188:27 | access to property QueryParam | external |
+| NameList2.cs:31:57:31:60 | access to property Name | ASP.NET Core component route parameter |
+| NameList2.cs:41:17:41:20 | access to property Name | ASP.NET Core component route parameter |
+| NameList2.cs:43:27:43:30 | access to property Name | ASP.NET Core component route parameter |
| NameList.cs:31:99:31:102 | access to property Name | ASP.NET Core component route parameter |
| NameList.cs:41:17:41:20 | access to property Name | ASP.NET Core component route parameter |
| NameList.cs:43:27:43:30 | access to property Name | ASP.NET Core component route parameter |
From d601c26355f27c2079fa38fbec99199cdbc20e77 Mon Sep 17 00:00:00 2001
From: Edward Minnix III
Date: Sat, 8 Mar 2025 17:24:49 -0500
Subject: [PATCH 058/409] [change-note] Blazor parameter passing string literal
---
.../2025-03-08-blazor-parameter-passing-string-literal.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 csharp/ql/lib/change-notes/2025-03-08-blazor-parameter-passing-string-literal.md
diff --git a/csharp/ql/lib/change-notes/2025-03-08-blazor-parameter-passing-string-literal.md b/csharp/ql/lib/change-notes/2025-03-08-blazor-parameter-passing-string-literal.md
new file mode 100644
index 000000000000..66ebd26f653d
--- /dev/null
+++ b/csharp/ql/lib/change-notes/2025-03-08-blazor-parameter-passing-string-literal.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* Blazor support can now better recognize when a property being set is specified with a string literal, rather than referenced in a `nameof` expression.
\ No newline at end of file
From 72fb6ed078c3de87871a87a9fe8315f9eb10b4d9 Mon Sep 17 00:00:00 2001
From: Tamas Vajk
Date: Fri, 28 Mar 2025 11:52:52 +0100
Subject: [PATCH 059/409] Restrict name based property lookup to opened
component types
---
.../microsoft/aspnetcore/Components.qll | 75 ++++++++++++++++++-
1 file changed, 73 insertions(+), 2 deletions(-)
diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/microsoft/aspnetcore/Components.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/microsoft/aspnetcore/Components.qll
index 5fb79418c27e..8cf5ce659e43 100644
--- a/csharp/ql/lib/semmle/code/csharp/frameworks/microsoft/aspnetcore/Components.qll
+++ b/csharp/ql/lib/semmle/code/csharp/frameworks/microsoft/aspnetcore/Components.qll
@@ -122,6 +122,38 @@ private class MicrosoftAspNetCoreComponentsAddComponentParameterMethod extends M
}
}
+/**
+ * The `Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder::OpenComponent` method.
+ */
+private class MicrosoftAspNetCoreComponentsOpenComponentTComponentMethod extends Method {
+ MicrosoftAspNetCoreComponentsOpenComponentTComponentMethod() {
+ this.hasFullyQualifiedName("Microsoft.AspNetCore.Components.Rendering", "RenderTreeBuilder",
+ "OpenComponent`1") and
+ this.getNumberOfParameters() = 1
+ }
+}
+
+/**
+ * The `Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder::OpenComponent` method.
+ */
+private class MicrosoftAspNetCoreComponentsOpenComponentMethod extends Method {
+ MicrosoftAspNetCoreComponentsOpenComponentMethod() {
+ this.hasFullyQualifiedName("Microsoft.AspNetCore.Components.Rendering", "RenderTreeBuilder",
+ "OpenComponent") and
+ this.getNumberOfParameters() = 2
+ }
+}
+
+/**
+ * The `Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder::CloseComponent` method.
+ */
+private class MicrosoftAspNetCoreComponentsCloseComponentMethod extends Method {
+ MicrosoftAspNetCoreComponentsCloseComponentMethod() {
+ this.hasFullyQualifiedName("Microsoft.AspNetCore.Components.Rendering", "RenderTreeBuilder",
+ "CloseComponent")
+ }
+}
+
private module Sources {
private import semmle.code.csharp.security.dataflow.flowsources.Remote
@@ -144,6 +176,38 @@ private module Sources {
}
}
+/**
+ * Holds for matching `RenderTreeBuilder.OpenComponent` and `RenderTreeBuilder.CloseComponent` calls with index `openCallIndex` and `closeCallIndex` respectively
+ * within the `enclosing` enclosing callabale. The `componentType` is the type of the component that is being opened and closed.
+ */
+private predicate matchingOpenCloseComponentCalls(
+ MethodCall openCall, int openCallIndex, MethodCall closeCall, int closeCallIndex,
+ Callable enclosing, Type componentType
+) {
+ (
+ openCall.getTarget().getUnboundDeclaration() instanceof
+ MicrosoftAspNetCoreComponentsOpenComponentTComponentMethod and
+ openCall.getTarget().(ConstructedGeneric).getTypeArgument(0) = componentType
+ or
+ openCall.getTarget() instanceof MicrosoftAspNetCoreComponentsOpenComponentMethod and
+ openCall.getArgument(1).(TypeofExpr).getTypeAccess().getTarget() = componentType
+ ) and
+ openCall.getEnclosingCallable() = enclosing and
+ closeCall.getTarget() instanceof MicrosoftAspNetCoreComponentsCloseComponentMethod and
+ closeCall.getEnclosingCallable() = enclosing and
+ closeCall.getParent().getParent() = openCall.getParent().getParent() and
+ openCall.getParent().getIndex() = openCallIndex and
+ closeCall.getParent().getIndex() = closeCallIndex and
+ closeCallIndex > openCallIndex and
+ not exists(int k, MethodCall otherCloseCall |
+ k in [openCallIndex + 1 .. closeCallIndex - 1] and
+ otherCloseCall.getTarget() instanceof MicrosoftAspNetCoreComponentsCloseComponentMethod and
+ otherCloseCall.getEnclosingCallable() = enclosing and
+ otherCloseCall.getParent().getParent() = openCall.getParent().getParent() and
+ otherCloseCall.getParent().getIndex() = k
+ )
+}
+
private module JumpNodes {
/**
* A call to `Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder::AddComponentParameter` which
@@ -162,8 +226,15 @@ private module JumpNodes {
(
exists(NameOfExpr ne | ne = this.getArgument(1) | result.getAnAccess() = ne.getAccess())
or
- exists(string propertyName | propertyName = this.getArgument(1).(StringLiteral).getValue() |
- result.hasName(propertyName)
+ exists(
+ string propertyName, MethodCall openComponent, int i, MethodCall closeComponent, int j
+ |
+ propertyName = this.getArgument(1).(StringLiteral).getValue() and
+ result.hasName(propertyName) and
+ matchingOpenCloseComponentCalls(openComponent, i, closeComponent, j,
+ this.getEnclosingCallable(), result.getDeclaringType()) and
+ this.getParent().getParent() = openComponent.getParent().getParent() and
+ this.getParent().getIndex() in [i + 1 .. j - 1]
)
)
}
From 32448c14bd9253f55afc9d0e92370b598f5dc2d7 Mon Sep 17 00:00:00 2001
From: Tamas Vajk
Date: Fri, 28 Mar 2025 13:06:36 +0100
Subject: [PATCH 060/409] Adjust expected test file
---
.../all-platforms/blazor_net_8/XSS.expected | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/csharp/ql/integration-tests/all-platforms/blazor_net_8/XSS.expected b/csharp/ql/integration-tests/all-platforms/blazor_net_8/XSS.expected
index 204c31945956..dbf056053b30 100644
--- a/csharp/ql/integration-tests/all-platforms/blazor_net_8/XSS.expected
+++ b/csharp/ql/integration-tests/all-platforms/blazor_net_8/XSS.expected
@@ -1,8 +1,18 @@
#select
+| BlazorTest/Components/MyOutput.razor:5:53:5:57 | access to property Value | BlazorTest/Components/Pages/TestPage.razor:85:23:85:32 | access to property QueryParam : String | BlazorTest/Components/MyOutput.razor:5:53:5:57 | access to property Value | $@ flows to here and is written to HTML or JavaScript. | BlazorTest/Components/Pages/TestPage.razor:85:23:85:32 | access to property QueryParam : String | User-provided value |
| BlazorTest/Components/Pages/TestPage.razor:11:48:11:55 | access to property UrlParam | BlazorTest/Components/Pages/TestPage.razor:11:48:11:55 | access to property UrlParam | BlazorTest/Components/Pages/TestPage.razor:11:48:11:55 | access to property UrlParam | $@ flows to here and is written to HTML or JavaScript. | BlazorTest/Components/Pages/TestPage.razor:11:48:11:55 | access to property UrlParam | User-provided value |
| BlazorTest/Components/Pages/TestPage.razor:20:60:20:69 | access to property QueryParam | BlazorTest/Components/Pages/TestPage.razor:20:60:20:69 | access to property QueryParam | BlazorTest/Components/Pages/TestPage.razor:20:60:20:69 | access to property QueryParam | $@ flows to here and is written to HTML or JavaScript. | BlazorTest/Components/Pages/TestPage.razor:20:60:20:69 | access to property QueryParam | User-provided value |
edges
+| BlazorTest/Components/Pages/TestPage.razor:85:23:85:32 | access to property QueryParam : String | BlazorTest/obj/Debug/net8.0/generated/Microsoft.CodeAnalysis.Razor.Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators.RazorSourceGenerator/Components_Pages_TestPage_razor.g.cs:497:59:505:13 | call to method TypeCheck : String | provenance | Src:MaD:2 MaD:3 |
+| BlazorTest/obj/Debug/net8.0/generated/Microsoft.CodeAnalysis.Razor.Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators.RazorSourceGenerator/Components_Pages_TestPage_razor.g.cs:497:59:505:13 | call to method TypeCheck : String | BlazorTest/Components/MyOutput.razor:5:53:5:57 | access to property Value | provenance | Sink:MaD:1 |
+models
+| 1 | Sink: Microsoft.AspNetCore.Components; MarkupString; false; MarkupString; (System.String); ; Argument[0]; html-injection; manual |
+| 2 | Source: Microsoft.AspNetCore.Components; SupplyParameterFromQueryAttribute; false; ; ; Attribute.Getter; ReturnValue; remote; manual |
+| 3 | Summary: Microsoft.AspNetCore.Components.CompilerServices; RuntimeHelpers; false; TypeCheck; (T); ; Argument[0]; ReturnValue; value; manual |
nodes
+| BlazorTest/Components/MyOutput.razor:5:53:5:57 | access to property Value | semmle.label | access to property Value |
| BlazorTest/Components/Pages/TestPage.razor:11:48:11:55 | access to property UrlParam | semmle.label | access to property UrlParam |
| BlazorTest/Components/Pages/TestPage.razor:20:60:20:69 | access to property QueryParam | semmle.label | access to property QueryParam |
+| BlazorTest/Components/Pages/TestPage.razor:85:23:85:32 | access to property QueryParam : String | semmle.label | access to property QueryParam : String |
+| BlazorTest/obj/Debug/net8.0/generated/Microsoft.CodeAnalysis.Razor.Compiler/Microsoft.NET.Sdk.Razor.SourceGenerators.RazorSourceGenerator/Components_Pages_TestPage_razor.g.cs:497:59:505:13 | call to method TypeCheck : String | semmle.label | call to method TypeCheck : String |
subpaths
From 6674288fd2bdb9425e3e64ae4eb83711b096b6c8 Mon Sep 17 00:00:00 2001
From: Taus
Date: Fri, 28 Mar 2025 15:12:39 +0000
Subject: [PATCH 061/409] Python: Update test cases
Adds a comment explaining why we no longer flag the indirect tuple
example.
Also adds a test case which _would_ be flagged if not for the type
annotation.
---
.../query-tests/Functions/return_values/functions_test.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/python/ql/test/query-tests/Functions/return_values/functions_test.py b/python/ql/test/query-tests/Functions/return_values/functions_test.py
index 24b1943feeb5..9f72a7fec600 100644
--- a/python/ql/test/query-tests/Functions/return_values/functions_test.py
+++ b/python/ql/test/query-tests/Functions/return_values/functions_test.py
@@ -321,7 +321,7 @@ def function_returning_2_tuple():
def function_returning_3_tuple():
return 1,2,3
-def indirectly_returning_different_tuple_sizes(x):
+def indirectly_returning_different_tuple_sizes(x): # OK, since we only look at local tuple returns
if x:
return function_returning_2_tuple()
else:
@@ -347,3 +347,9 @@ def ok_match2(x): # FP
return 0
case _:
return 1
+
+def ok_tuple_returns_captured_in_type(x: bool) -> tuple[int, ...]: # OK because there is a type annotation present
+ if x:
+ return 1, 2
+ else:
+ return 1, 2, 3
From 4a76b5b3db817b90b82d97a4b049ef456dbf046f Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Fri, 28 Mar 2025 15:40:18 +0000
Subject: [PATCH 062/409] Rust: Accept consistency check failures.
---
.../CWE-825/CONSISTENCY/DataFlowConsistency.expected | 10 ++++++++++
1 file changed, 10 insertions(+)
create mode 100644 rust/ql/test/query-tests/security/CWE-825/CONSISTENCY/DataFlowConsistency.expected
diff --git a/rust/ql/test/query-tests/security/CWE-825/CONSISTENCY/DataFlowConsistency.expected b/rust/ql/test/query-tests/security/CWE-825/CONSISTENCY/DataFlowConsistency.expected
new file mode 100644
index 000000000000..f518ed81ffab
--- /dev/null
+++ b/rust/ql/test/query-tests/security/CWE-825/CONSISTENCY/DataFlowConsistency.expected
@@ -0,0 +1,10 @@
+postWithInFlow
+| deallocation.rs:20:23:20:24 | [post] m1 | PostUpdateNode should not be the target of local flow. |
+| deallocation.rs:70:23:70:35 | [post] m2 as ... | PostUpdateNode should not be the target of local flow. |
+| deallocation.rs:112:14:112:40 | [post] my_ptr as ... | PostUpdateNode should not be the target of local flow. |
+| deallocation.rs:176:27:176:28 | [post] p1 | PostUpdateNode should not be the target of local flow. |
+| deallocation.rs:189:27:189:44 | [post] ... .as_mut_ptr(...) | PostUpdateNode should not be the target of local flow. |
+| deallocation.rs:217:24:217:31 | [post] self.ptr | PostUpdateNode should not be the target of local flow. |
+| deallocation.rs:236:27:236:29 | [post] ptr | PostUpdateNode should not be the target of local flow. |
+| deallocation.rs:242:27:242:29 | [post] ptr | PostUpdateNode should not be the target of local flow. |
+| deallocation.rs:267:23:267:25 | [post] ptr | PostUpdateNode should not be the target of local flow. |
From ca6444ce98faae024d48b36915a4661449ff10f6 Mon Sep 17 00:00:00 2001
From: Anders Schack-Mulligen
Date: Thu, 27 Mar 2025 11:02:46 +0100
Subject: [PATCH 063/409] VariableCapture: Replace phi-read reference with SSA
data flow integration module.
---
.../codeql/dataflow/VariableCapture.qll | 148 ++++++++++--------
1 file changed, 83 insertions(+), 65 deletions(-)
diff --git a/shared/dataflow/codeql/dataflow/VariableCapture.qll b/shared/dataflow/codeql/dataflow/VariableCapture.qll
index 3077739338ec..c76e1320a37e 100644
--- a/shared/dataflow/codeql/dataflow/VariableCapture.qll
+++ b/shared/dataflow/codeql/dataflow/VariableCapture.qll
@@ -699,6 +699,7 @@ module Flow Input> implements OutputSig
class SourceVariable = CaptureContainer;
predicate variableWrite(BasicBlock bb, int i, SourceVariable cc, boolean certain) {
+ Cached::ref() and
(
exists(CapturedVariable v | cc = TVariable(v) and captureWrite(v, bb, i, true, _))
or
@@ -721,23 +722,55 @@ module Flow Input> implements OutputSig
private module CaptureSsa = Ssa::Make;
- private newtype TClosureNode =
- TSynthRead(CapturedVariable v, BasicBlock bb, int i, Boolean isPost) {
- synthRead(v, bb, i, _, _)
- } or
- TSynthThisQualifier(BasicBlock bb, int i, Boolean isPost) { synthThisQualifier(bb, i) } or
- TSynthPhi(CaptureSsa::DefinitionExt phi) {
- phi instanceof CaptureSsa::PhiNode or phi instanceof CaptureSsa::PhiReadNode
- } or
- TExprNode(Expr expr, Boolean isPost) {
- expr instanceof VariableRead
- or
- synthRead(_, _, _, _, expr)
- } or
- TParamNode(CapturedParameter p) or
- TThisParamNode(Callable c) { captureAccess(_, c) } or
- TMallocNode(ClosureExpr ce) { hasConstructorCapture(ce, _) } or
- TVariableWriteSourceNode(VariableWrite write)
+ private module DataFlowIntegrationInput implements CaptureSsa::DataFlowIntegrationInputSig {
+ private import codeql.util.Void
+
+ class Expr instanceof Input::ControlFlowNode {
+ string toString() { result = super.toString() }
+
+ predicate hasCfgNode(BasicBlock bb, int i) { bb.getNode(i) = this }
+ }
+
+ class Guard extends Void {
+ predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) { none() }
+ }
+
+ predicate guardDirectlyControlsBlock(Guard guard, BasicBlock bb, boolean branch) { none() }
+
+ predicate includeWriteDefsInFlowStep() { none() }
+
+ predicate supportBarrierGuardsOnPhiEdges() { none() }
+ }
+
+ private module SsaFlow = CaptureSsa::DataFlowIntegration;
+
+ cached
+ private module Cached {
+ cached
+ predicate ref() { any() }
+
+ cached
+ predicate backref() { localFlowStep(_, _) implies any() }
+
+ cached
+ newtype TClosureNode =
+ TSynthRead(CapturedVariable v, BasicBlock bb, int i, Boolean isPost) {
+ synthRead(v, bb, i, _, _)
+ } or
+ TSynthThisQualifier(BasicBlock bb, int i, Boolean isPost) { synthThisQualifier(bb, i) } or
+ TSynthSsa(SsaFlow::SsaNode n) or
+ TExprNode(Expr expr, Boolean isPost) {
+ expr instanceof VariableRead
+ or
+ synthRead(_, _, _, _, expr)
+ } or
+ TParamNode(CapturedParameter p) or
+ TThisParamNode(Callable c) { captureAccess(_, c) } or
+ TMallocNode(ClosureExpr ce) { hasConstructorCapture(ce, _) } or
+ TVariableWriteSourceNode(VariableWrite write)
+ }
+
+ private import Cached
class ClosureNode extends TClosureNode {
/** Gets a textual representation of this node. */
@@ -746,11 +779,7 @@ module Flow Input> implements OutputSig
or
result = "this" and this = TSynthThisQualifier(_, _, _)
or
- exists(CaptureSsa::DefinitionExt phi, CaptureContainer cc |
- this = TSynthPhi(phi) and
- phi.definesAt(cc, _, _, _) and
- result = "phi(" + cc.toString() + ")"
- )
+ exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and result = n.toString())
or
exists(Expr expr, boolean isPost | this = TExprNode(expr, isPost) |
isPost = false and result = expr.toString()
@@ -784,9 +813,7 @@ module Flow Input> implements OutputSig
captureWrite(_, bb, i, false, any(VariableWrite vw | result = vw.getLocation()))
)
or
- exists(CaptureSsa::DefinitionExt phi, BasicBlock bb |
- this = TSynthPhi(phi) and phi.definesAt(_, bb, _, _) and result = bb.getLocation()
- )
+ exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and result = n.getLocation())
or
exists(Expr expr | this = TExprNode(expr, _) and result = expr.getLocation())
or
@@ -802,7 +829,7 @@ module Flow Input> implements OutputSig
}
}
- private class TSynthesizedCaptureNode = TSynthRead or TSynthThisQualifier or TSynthPhi;
+ private class TSynthesizedCaptureNode = TSynthRead or TSynthThisQualifier or TSynthSsa;
class SynthesizedCaptureNode extends ClosureNode, TSynthesizedCaptureNode {
BasicBlock getBasicBlock() {
@@ -810,9 +837,7 @@ module Flow Input> implements OutputSig
or
this = TSynthThisQualifier(result, _, _)
or
- exists(CaptureSsa::DefinitionExt phi |
- this = TSynthPhi(phi) and phi.definesAt(_, result, _, _)
- )
+ exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and n.getBasicBlock() = result)
}
Callable getEnclosingCallable() { result = this.getBasicBlock().getEnclosingCallable() }
@@ -820,17 +845,13 @@ module Flow Input> implements OutputSig
predicate isVariableAccess(CapturedVariable v) {
this = TSynthRead(v, _, _, _)
or
- exists(CaptureSsa::DefinitionExt phi |
- this = TSynthPhi(phi) and phi.definesAt(TVariable(v), _, _, _)
- )
+ exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and n.getSourceVariable() = TVariable(v))
}
predicate isInstanceAccess() {
this instanceof TSynthThisQualifier
or
- exists(CaptureSsa::DefinitionExt phi |
- this = TSynthPhi(phi) and phi.definesAt(TThis(_), _, _, _)
- )
+ exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and n.getSourceVariable() = TThis(_))
}
}
@@ -872,18 +893,7 @@ module Flow Input> implements OutputSig
)
}
- private predicate step(CaptureContainer cc, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
- CaptureSsa::adjacentDefReadExt(_, cc, bb1, i1, bb2, i2)
- }
-
- private predicate stepToPhi(CaptureContainer cc, BasicBlock bb, int i, TSynthPhi phi) {
- exists(CaptureSsa::DefinitionExt next |
- CaptureSsa::lastRefRedefExt(_, cc, bb, i, next) and
- phi = TSynthPhi(next)
- )
- }
-
- private predicate ssaAccessAt(
+ private predicate ssaReadAt(
ClosureNode n, CaptureContainer cc, boolean isPost, BasicBlock bb, int i
) {
exists(CapturedVariable v |
@@ -894,49 +904,57 @@ module Flow Input> implements OutputSig
or
n = TSynthThisQualifier(bb, i, isPost) and cc = TThis(bb.getEnclosingCallable())
or
- exists(CaptureSsa::DefinitionExt phi |
- n = TSynthPhi(phi) and phi.definesAt(cc, bb, i, _) and isPost = false
- )
- or
exists(VariableRead vr, CapturedVariable v |
captureRead(v, bb, i, true, vr) and
n = TExprNode(vr, isPost) and
cc = TVariable(v)
)
- or
+ }
+
+ private predicate ssaWriteAt(ClosureNode n, CaptureContainer cc, BasicBlock bb, int i) {
exists(VariableWrite vw, CapturedVariable v |
captureWrite(v, bb, i, true, vw) and
n = TVariableWriteSourceNode(vw) and
- isPost = false and
cc = TVariable(v)
)
or
exists(CapturedParameter p |
entryDef(cc, bb, i) and
cc = TVariable(p) and
- n = TParamNode(p) and
- isPost = false
+ n = TParamNode(p)
)
or
exists(Callable c |
entryDef(cc, bb, i) and
cc = TThis(c) and
- n = TThisParamNode(c) and
- isPost = false
+ n = TThisParamNode(c)
)
}
- predicate localFlowStep(ClosureNode node1, ClosureNode node2) {
- exists(CaptureContainer cc, BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
- step(cc, bb1, i1, bb2, i2) and
- ssaAccessAt(node1, pragma[only_bind_into](cc), _, bb1, i1) and
- ssaAccessAt(node2, pragma[only_bind_into](cc), false, bb2, i2)
+ bindingset[result, cc]
+ pragma[inline_late]
+ private SsaFlow::Node asNode(CaptureContainer cc, ClosureNode n) {
+ n = TSynthSsa(result)
+ or
+ exists(BasicBlock bb, int i |
+ result.(SsaFlow::ExprNode).getExpr().hasCfgNode(bb, i) and
+ ssaReadAt(n, cc, false, bb, i)
)
or
- exists(CaptureContainer cc, BasicBlock bb, int i |
- stepToPhi(cc, bb, i, node2) and
- ssaAccessAt(node1, cc, _, bb, i)
+ exists(BasicBlock bb, int i |
+ result.(SsaFlow::ExprPostUpdateNode).getExpr().hasCfgNode(bb, i) and
+ ssaReadAt(n, cc, true, bb, i)
)
+ or
+ exists(BasicBlock bb, int i |
+ result.(SsaFlow::WriteDefSourceNode).getDefinition().definesAt(cc, bb, i) and
+ ssaWriteAt(n, cc, bb, i)
+ )
+ }
+
+ cached
+ predicate localFlowStep(ClosureNode n1, ClosureNode n2) {
+ exists(CaptureContainer cc | SsaFlow::localFlowStep(cc, asNode(cc, n1), asNode(cc, n2), _))
}
private predicate storeStepClosure(
From 70e53c2f8b3cca70fa272516f709d4b53fe41a8f Mon Sep 17 00:00:00 2001
From: Anders Schack-Mulligen
Date: Fri, 28 Mar 2025 16:28:12 +0100
Subject: [PATCH 064/409] SSA: Push includeWriteDefsInFlowStep constraint into
newtype.
---
shared/ssa/codeql/ssa/Ssa.qll | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/shared/ssa/codeql/ssa/Ssa.qll b/shared/ssa/codeql/ssa/Ssa.qll
index 2bbdb6e2a478..fcaa1eb6a9f2 100644
--- a/shared/ssa/codeql/ssa/Ssa.qll
+++ b/shared/ssa/codeql/ssa/Ssa.qll
@@ -1661,7 +1661,16 @@ module Make Input> {
private newtype TNode =
TWriteDefSource(WriteDefinition def) { DfInput::ssaDefHasSource(def) } or
TExprNode(DfInput::Expr e, Boolean isPost) { e = DfInput::getARead(_) } or
- TSsaDefinitionNode(DefinitionExt def) { not phiHasUniqNextNode(def) } or
+ TSsaDefinitionNode(DefinitionExt def) {
+ not phiHasUniqNextNode(def) and
+ if DfInput::includeWriteDefsInFlowStep()
+ then any()
+ else (
+ def instanceof PhiNode or
+ def instanceof PhiReadNode or
+ DfInput::allowFlowIntoUncertainDef(def)
+ )
+ } or
TSsaInputNode(SsaPhiExt phi, BasicBlock input) { relevantPhiInputNode(phi, input) }
/**
@@ -1904,14 +1913,7 @@ module Make Input> {
exists(DefinitionExt def |
nodeFrom.(SsaDefinitionExtNodeImpl).getDefExt() = def and
def.definesAt(v, bb, i, _) and
- isUseStep = false and
- if DfInput::includeWriteDefsInFlowStep()
- then any()
- else (
- def instanceof PhiNode or
- def instanceof PhiReadNode or
- DfInput::allowFlowIntoUncertainDef(def)
- )
+ isUseStep = false
)
or
[nodeFrom, nodeFrom.(ExprPostUpdateNode).getPreUpdateNode()].(ReadNode).readsAt(bb, i, v) and
From b4daba30a5eb7500945740a9647f3956695588dc Mon Sep 17 00:00:00 2001
From: Anders Schack-Mulligen
Date: Mon, 31 Mar 2025 10:42:50 +0200
Subject: [PATCH 065/409] SSA: Remove dead code.
---
shared/ssa/codeql/ssa/Ssa.qll | 2 --
1 file changed, 2 deletions(-)
diff --git a/shared/ssa/codeql/ssa/Ssa.qll b/shared/ssa/codeql/ssa/Ssa.qll
index fcaa1eb6a9f2..7e48feb42dc8 100644
--- a/shared/ssa/codeql/ssa/Ssa.qll
+++ b/shared/ssa/codeql/ssa/Ssa.qll
@@ -1757,8 +1757,6 @@ module Make Input> {
this.getExpr().hasCfgNode(bb_, i_)
}
- SourceVariable getVariable() { result = v_ }
-
pragma[nomagic]
predicate readsAt(BasicBlock bb, int i, SourceVariable v) {
bb = bb_ and
From 133f08784fa738aa4ddf3711d505f8bd132ab80c Mon Sep 17 00:00:00 2001
From: Anders Schack-Mulligen
Date: Thu, 20 Mar 2025 13:12:48 +0100
Subject: [PATCH 066/409] C++: Eliminate dead code, uncertain is always false.
---
.../ir/dataflow/internal/DataFlowPrivate.qll | 44 ++++---------------
1 file changed, 9 insertions(+), 35 deletions(-)
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll
index f6371e5b696c..e3e07c1522ce 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll
@@ -1879,15 +1879,6 @@ module IteratorFlow {
phi.definesAt(sv, bb2, i2, _)
)
}
-
- cached
- Node getAPriorDefinition(IteratorSsa::DefinitionExt next) {
- exists(IRBlock bb, int i, SourceVariable sv, IteratorSsa::DefinitionExt def |
- IteratorSsa::lastRefRedefExt(pragma[only_bind_into](def), pragma[only_bind_into](sv),
- pragma[only_bind_into](bb), pragma[only_bind_into](i), next) and
- nodeToDefOrUse(result, sv, bb, i, _)
- )
- }
}
/** The set of nodes necessary for iterator flow. */
@@ -1912,25 +1903,19 @@ module IteratorFlow {
private import IteratorSsaCached
- private predicate defToNode(Node node, Def def, boolean uncertain) {
- (
- nodeHasOperand(node, def.getValue().asOperand(), def.getIndirectionIndex())
- or
- nodeHasInstruction(node, def.getValue().asInstruction(), def.getIndirectionIndex())
- ) and
- uncertain = false
+ private predicate defToNode(Node node, Def def) {
+ nodeHasOperand(node, def.getValue().asOperand(), def.getIndirectionIndex())
+ or
+ nodeHasInstruction(node, def.getValue().asInstruction(), def.getIndirectionIndex())
}
- private predicate nodeToDefOrUse(
- Node node, SourceVariable sv, IRBlock bb, int i, boolean uncertain
- ) {
+ private predicate nodeToDefOrUse(Node node, SourceVariable sv, IRBlock bb, int i) {
exists(Def def |
def.hasIndexInBlock(bb, i, sv) and
- defToNode(node, def, uncertain)
+ defToNode(node, def)
)
or
- useToNode(bb, i, sv, node) and
- uncertain = false
+ useToNode(bb, i, sv, node)
}
private predicate useToNode(IRBlock bb, int i, SourceVariable sv, Node nodeTo) {
@@ -1949,21 +1934,10 @@ module IteratorFlow {
* Holds if `nodeFrom` flows to `nodeTo` in a single step.
*/
predicate localFlowStep(Node nodeFrom, Node nodeTo) {
- exists(
- Node nFrom, SourceVariable sv, IRBlock bb1, int i1, IRBlock bb2, int i2, boolean uncertain
- |
+ exists(SourceVariable sv, IRBlock bb1, int i1, IRBlock bb2, int i2 |
adjacentDefRead(bb1, i1, sv, bb2, i2) and
- nodeToDefOrUse(nFrom, sv, bb1, i1, uncertain) and
+ nodeToDefOrUse(nodeFrom, sv, bb1, i1) and
useToNode(bb2, i2, sv, nodeTo)
- |
- if uncertain = true
- then
- nodeFrom =
- [
- nFrom,
- getAPriorDefinition(any(IteratorSsa::DefinitionExt next | next.definesAt(sv, bb1, i1, _)))
- ]
- else nFrom = nodeFrom
)
}
}
From aaa7e4cf95f00fcad879e187a96ef1f7ef3a5405 Mon Sep 17 00:00:00 2001
From: Anders Schack-Mulligen
Date: Wed, 26 Mar 2025 13:58:58 +0100
Subject: [PATCH 067/409] C++: Def is only used in defToNode, which doesn't
include phi reads nodes.
---
.../semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll
index e3e07c1522ce..13243f2b22ea 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll
@@ -1834,7 +1834,7 @@ module IteratorFlow {
private module IteratorSsa = SsaImpl::Make;
- private class Def extends IteratorSsa::DefinitionExt {
+ private class Def extends IteratorSsa::Definition {
final override Location getLocation() { result = this.getImpl().getLocation() }
/**
@@ -1842,7 +1842,7 @@ module IteratorFlow {
* and is a definition (or use) of the variable `sv`.
*/
predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) {
- super.definesAt(sv, block, index, _)
+ super.definesAt(sv, block, index)
}
private Ssa::DefImpl getImpl() {
From a6a694dec65b2e086cebc3676ddbadaab9a2ad92 Mon Sep 17 00:00:00 2001
From: Anders Schack-Mulligen
Date: Thu, 20 Mar 2025 14:36:17 +0100
Subject: [PATCH 068/409] C++: Use DataFlowIntegration in IteratorFlow.
---
.../ir/dataflow/internal/DataFlowPrivate.qll | 100 ++++++++++--------
.../cpp/ir/dataflow/internal/SsaInternals.qll | 2 +-
2 files changed, 55 insertions(+), 47 deletions(-)
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll
index 13243f2b22ea..8a5155239304 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll
@@ -1834,6 +1834,46 @@ module IteratorFlow {
private module IteratorSsa = SsaImpl::Make;
+ private module DataFlowIntegrationInput implements IteratorSsa::DataFlowIntegrationInputSig {
+ private import codeql.util.Void
+
+ class Expr extends Instruction {
+ Expr() {
+ exists(IRBlock bb, int i |
+ SsaInput::variableRead(bb, i, _, true) and
+ this = bb.getInstruction(i)
+ )
+ }
+
+ predicate hasCfgNode(SsaInput::BasicBlock bb, int i) { bb.getInstruction(i) = this }
+ }
+
+ predicate ssaDefHasSource(IteratorSsa::WriteDefinition def) { none() }
+
+ predicate allowFlowIntoUncertainDef(IteratorSsa::UncertainWriteDefinition def) { any() }
+
+ class Guard extends Void {
+ predicate controlsBranchEdge(
+ SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch
+ ) {
+ none()
+ }
+ }
+
+ predicate guardDirectlyControlsBlock(Guard guard, SsaInput::BasicBlock bb, boolean branch) {
+ none()
+ }
+
+ predicate supportBarrierGuardsOnPhiEdges() { none() }
+ }
+
+ private module DataFlowIntegrationImpl =
+ IteratorSsa::DataFlowIntegration;
+
+ private class IteratorSynthNode extends DataFlowIntegrationImpl::SsaNode {
+ IteratorSynthNode() { not this.asDefinition() instanceof IteratorSsa::WriteDefinition }
+ }
+
private class Def extends IteratorSsa::Definition {
final override Location getLocation() { result = this.getImpl().getLocation() }
@@ -1859,37 +1899,15 @@ module IteratorFlow {
int getIndirectionIndex() { result = this.getImpl().getIndirectionIndex() }
}
- private class PhiNode extends IteratorSsa::DefinitionExt {
- PhiNode() {
- this instanceof IteratorSsa::PhiNode or
- this instanceof IteratorSsa::PhiReadNode
- }
-
- SsaIteratorNode getNode() { result.getIteratorFlowNode() = this }
- }
-
- cached
- private module IteratorSsaCached {
- cached
- predicate adjacentDefRead(IRBlock bb1, int i1, SourceVariable sv, IRBlock bb2, int i2) {
- IteratorSsa::adjacentDefReadExt(_, sv, bb1, i1, bb2, i2)
- or
- exists(PhiNode phi |
- IteratorSsa::lastRefRedefExt(_, sv, bb1, i1, phi) and
- phi.definesAt(sv, bb2, i2, _)
- )
- }
- }
-
/** The set of nodes necessary for iterator flow. */
- class IteratorFlowNode instanceof PhiNode {
+ class IteratorFlowNode instanceof IteratorSynthNode {
/** Gets a textual representation of this node. */
string toString() { result = super.toString() }
/** Gets the type of this node. */
DataFlowType getType() {
exists(Ssa::SourceVariable sv |
- super.definesAt(sv, _, _, _) and
+ super.getSourceVariable() = sv and
result = sv.getType()
)
}
@@ -1901,43 +1919,33 @@ module IteratorFlow {
Location getLocation() { result = super.getBasicBlock().getLocation() }
}
- private import IteratorSsaCached
-
private predicate defToNode(Node node, Def def) {
nodeHasOperand(node, def.getValue().asOperand(), def.getIndirectionIndex())
or
nodeHasInstruction(node, def.getValue().asInstruction(), def.getIndirectionIndex())
}
- private predicate nodeToDefOrUse(Node node, SourceVariable sv, IRBlock bb, int i) {
- exists(Def def |
- def.hasIndexInBlock(bb, i, sv) and
- defToNode(node, def)
- )
+ bindingset[result, v]
+ pragma[inline_late]
+ private DataFlowIntegrationImpl::Node fromDfNode(Node n, SourceVariable v) {
+ result = n.(SsaIteratorNode).getIteratorFlowNode()
or
- useToNode(bb, i, sv, node)
- }
-
- private predicate useToNode(IRBlock bb, int i, SourceVariable sv, Node nodeTo) {
- exists(PhiNode phi |
- phi.definesAt(sv, bb, i, _) and
- nodeTo = phi.getNode()
+ exists(Ssa::UseImpl use, IRBlock bb, int i |
+ result.(DataFlowIntegrationImpl::ExprNode).getExpr().hasCfgNode(bb, i) and
+ use.hasIndexInBlock(bb, i, v) and
+ use.getNode() = n
)
or
- exists(Ssa::UseImpl use |
- use.hasIndexInBlock(bb, i, sv) and
- nodeTo = use.getNode()
- )
+ defToNode(n, result.(DataFlowIntegrationImpl::SsaDefinitionNode).getDefinition())
}
/**
* Holds if `nodeFrom` flows to `nodeTo` in a single step.
*/
predicate localFlowStep(Node nodeFrom, Node nodeTo) {
- exists(SourceVariable sv, IRBlock bb1, int i1, IRBlock bb2, int i2 |
- adjacentDefRead(bb1, i1, sv, bb2, i2) and
- nodeToDefOrUse(nodeFrom, sv, bb1, i1) and
- useToNode(bb2, i2, sv, nodeTo)
+ exists(SourceVariable v |
+ nodeFrom != nodeTo and
+ DataFlowIntegrationImpl::localFlowStep(v, fromDfNode(nodeFrom, v), fromDfNode(nodeTo, v), _)
)
}
}
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll
index 202d3fa32c80..51829f13df51 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll
@@ -1069,7 +1069,7 @@ module BarrierGuard {
bindingset[result, v]
pragma[inline_late]
-DataFlowIntegrationImpl::Node fromDfNode(Node n, SourceVariable v) {
+private DataFlowIntegrationImpl::Node fromDfNode(Node n, SourceVariable v) {
result = n.(SsaSynthNode).getSynthNode()
or
exists(UseImpl use, IRBlock bb, int i |
From 8a67e4fddcb9e4ad5ae5aa93be573d1fd6a38785 Mon Sep 17 00:00:00 2001
From: Anders Schack-Mulligen
Date: Mon, 31 Mar 2025 11:20:40 +0200
Subject: [PATCH 069/409] Misc: Add stage overlap script
---
misc/scripts/stageoverlap.py | 81 ++++++++++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)
create mode 100755 misc/scripts/stageoverlap.py
diff --git a/misc/scripts/stageoverlap.py b/misc/scripts/stageoverlap.py
new file mode 100755
index 000000000000..42b3d8db0b22
--- /dev/null
+++ b/misc/scripts/stageoverlap.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python3
+
+import sys
+import os
+import re
+
+# read first argument
+if len(sys.argv) < 2:
+ print("Usage: stagestats.py ")
+ sys.exit(1)
+
+dilfile = sys.argv[1]
+
+seen_stages = set()
+computed_predicates = {}
+stage_number = 0
+
+def process_stage(stage, cached):
+ global stage_number
+ stage_key = ' '.join(cached)
+ # skip repeated stages (in case we're looking at DIL for several queries, e.g. from a .qls)
+ if stage_key in seen_stages:
+ return
+ # don't count the query-stage as seen, since we don't want to skip those
+ if not '#select' in cached:
+ seen_stages.add(stage_key)
+ stage_number += 1
+ print('STAGE ' + str(stage_number) + ':')
+ print(str(len(cached)) + ' cached predicate(s)')
+ print(' '.join(cached))
+ for predicate in stage:
+ # strip trailing characters matching the regex '#[bf]+', i.e. disregard magic
+ predicate = re.sub('#[bf]+$', '', predicate)
+ # TODO: maybe also strip the hash?
+ # predicate = re.sub('#[a-f0-9]+$', '', predicate)
+ if predicate in computed_predicates.keys():
+ # skip db-relations and some generated predicates
+ if predicate.startswith('@') or predicate.startswith('project#'):
+ continue
+ prior_stage = computed_predicates[predicate]
+ print('Recompute from ' + str(prior_stage) + ': ' + predicate)
+ else:
+ computed_predicates[predicate] = stage_number
+ print()
+
+with open(dilfile, 'r') as f:
+ stage = []
+ cached = []
+ query = False
+ for line in f:
+ # skip lines starting with a space, i.e. predicate bodies
+ if line.startswith(' '): continue
+ # get the part of the line containing no spaces occuring before the first '('
+ # this is the predicate name
+ parenpos = line.find('(')
+ if parenpos != -1:
+ start = line.rfind(' ', 0, parenpos)
+ predicate = line[start+1:parenpos]
+ if predicate.startswith('`'):
+ # remove the leading and trailing backticks
+ predicate = predicate[1:-1]
+ stage.append(predicate)
+ continue
+ # query predicates, aka cached predicates, are written either as
+ # 'query = ...' on one line, or split across 2+ lines
+ if line.startswith('query '):
+ predicate = line.split(' ')[1]
+ cached.append(predicate)
+ continue
+ if line == 'query\n':
+ query = True
+ continue
+ if query:
+ predicate = line.split(' ')[0]
+ cached.append(predicate)
+ query = False
+ continue
+ if line == '/* ---------- END STAGE ---------- */\n':
+ process_stage(stage, cached)
+ stage = []
+ cached = []
From 9a8ab2d45b2d0ea46c56075357dbde4a4777eb5b Mon Sep 17 00:00:00 2001
From: Anders Schack-Mulligen
Date: Mon, 31 Mar 2025 11:28:29 +0200
Subject: [PATCH 070/409] Update misc/scripts/stageoverlap.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
misc/scripts/stageoverlap.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/misc/scripts/stageoverlap.py b/misc/scripts/stageoverlap.py
index 42b3d8db0b22..979fc61571e5 100755
--- a/misc/scripts/stageoverlap.py
+++ b/misc/scripts/stageoverlap.py
@@ -6,7 +6,7 @@
# read first argument
if len(sys.argv) < 2:
- print("Usage: stagestats.py ")
+ print("Usage: stageoverlap.py ")
sys.exit(1)
dilfile = sys.argv[1]
From 56c46d74f91a17c6f0e25577ab32b46ffb4a85c0 Mon Sep 17 00:00:00 2001
From: Anders Schack-Mulligen
Date: Mon, 31 Mar 2025 11:44:37 +0200
Subject: [PATCH 071/409] Java/Rust/Swift: Accept qltest changes.
---
.../test/library-tests/dataflow/capture/test.expected | 2 --
.../local/CONSISTENCY/DataFlowConsistency.expected | 2 --
.../library-tests/dataflow/local/DataFlowStep.expected | 9 ++++-----
.../library-tests/dataflow/dataflow/LocalFlow.expected | 10 +++++-----
4 files changed, 9 insertions(+), 14 deletions(-)
delete mode 100644 rust/ql/test/library-tests/dataflow/local/CONSISTENCY/DataFlowConsistency.expected
diff --git a/java/ql/test/library-tests/dataflow/capture/test.expected b/java/ql/test/library-tests/dataflow/capture/test.expected
index 1e8a2d7d3349..a744f468fbe9 100644
--- a/java/ql/test/library-tests/dataflow/capture/test.expected
+++ b/java/ql/test/library-tests/dataflow/capture/test.expected
@@ -18,7 +18,6 @@
| A.java:21:11:21:13 | "B" : String | A.java:15:16:15:22 | get(...) : String |
| A.java:21:11:21:13 | "B" : String | A.java:21:7:21:13 | ...=... : String |
| A.java:21:11:21:13 | "B" : String | A.java:25:5:25:26 | SSA phi(s) : String |
-| A.java:21:11:21:13 | "B" : String | A.java:25:5:25:26 | phi(String s) : String |
| A.java:21:11:21:13 | "B" : String | A.java:28:11:38:5 | String s : String |
| A.java:21:11:21:13 | "B" : String | A.java:28:11:38:5 | new (...) : new A(...) { ... } [String s] |
| A.java:21:11:21:13 | "B" : String | A.java:30:14:30:16 | parameter this : new A(...) { ... } [String s] |
@@ -35,7 +34,6 @@
| A.java:23:11:23:13 | "C" : String | A.java:15:16:15:22 | get(...) : String |
| A.java:23:11:23:13 | "C" : String | A.java:23:7:23:13 | ...=... : String |
| A.java:23:11:23:13 | "C" : String | A.java:25:5:25:26 | SSA phi(s) : String |
-| A.java:23:11:23:13 | "C" : String | A.java:25:5:25:26 | phi(String s) : String |
| A.java:23:11:23:13 | "C" : String | A.java:28:11:38:5 | String s : String |
| A.java:23:11:23:13 | "C" : String | A.java:28:11:38:5 | new (...) : new A(...) { ... } [String s] |
| A.java:23:11:23:13 | "C" : String | A.java:30:14:30:16 | parameter this : new A(...) { ... } [String s] |
diff --git a/rust/ql/test/library-tests/dataflow/local/CONSISTENCY/DataFlowConsistency.expected b/rust/ql/test/library-tests/dataflow/local/CONSISTENCY/DataFlowConsistency.expected
deleted file mode 100644
index e20ac1da53f6..000000000000
--- a/rust/ql/test/library-tests/dataflow/local/CONSISTENCY/DataFlowConsistency.expected
+++ /dev/null
@@ -1,2 +0,0 @@
-identityLocalStep
-| main.rs:442:9:442:20 | phi(default_name) | Node steps to itself |
diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected
index 2766d8c0fd8c..7fd8c3fe8a8e 100644
--- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected
+++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected
@@ -647,10 +647,9 @@ localStep
| main.rs:441:24:441:33 | [post] receiver for source(...) | main.rs:441:24:441:33 | [post] source(...) |
| main.rs:441:24:441:33 | source(...) | main.rs:441:24:441:33 | receiver for source(...) |
| main.rs:441:24:441:45 | ... .to_string(...) | main.rs:441:9:441:20 | default_name |
-| main.rs:441:24:441:45 | ... .to_string(...) | main.rs:442:9:442:20 | phi(default_name) |
+| main.rs:441:24:441:45 | ... .to_string(...) | main.rs:442:9:442:20 | SSA phi read(default_name) |
| main.rs:442:5:448:5 | for ... in ... { ... } | main.rs:440:75:449:1 | { ... } |
-| main.rs:442:9:442:20 | phi(default_name) | main.rs:442:9:442:20 | phi(default_name) |
-| main.rs:442:9:442:20 | phi(default_name) | main.rs:444:41:444:67 | default_name |
+| main.rs:442:9:442:20 | SSA phi read(default_name) | main.rs:444:41:444:67 | default_name |
| main.rs:442:10:442:13 | [SSA] cond | main.rs:443:12:443:15 | cond |
| main.rs:442:10:442:13 | cond | main.rs:442:10:442:13 | [SSA] cond |
| main.rs:442:10:442:13 | cond | main.rs:442:10:442:13 | cond |
@@ -664,9 +663,9 @@ localStep
| main.rs:444:21:444:24 | [post] receiver for name | main.rs:444:21:444:24 | [post] name |
| main.rs:444:21:444:24 | name | main.rs:444:21:444:24 | receiver for name |
| main.rs:444:21:444:68 | name.unwrap_or_else(...) | main.rs:444:17:444:17 | n |
-| main.rs:444:41:444:67 | [post] default_name | main.rs:442:9:442:20 | phi(default_name) |
+| main.rs:444:41:444:67 | [post] default_name | main.rs:442:9:442:20 | SSA phi read(default_name) |
| main.rs:444:41:444:67 | closure self in \|...\| ... | main.rs:444:44:444:55 | this |
-| main.rs:444:41:444:67 | default_name | main.rs:442:9:442:20 | phi(default_name) |
+| main.rs:444:41:444:67 | default_name | main.rs:442:9:442:20 | SSA phi read(default_name) |
| main.rs:444:44:444:55 | [post] receiver for default_name | main.rs:444:44:444:55 | [post] default_name |
| main.rs:444:44:444:55 | default_name | main.rs:444:44:444:55 | receiver for default_name |
| main.rs:445:18:445:18 | [post] receiver for n | main.rs:445:18:445:18 | [post] n |
diff --git a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
index 7ec3f1a5aa48..b3dca8680670 100644
--- a/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
+++ b/swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected
@@ -1378,17 +1378,17 @@
| test.swift:888:9:888:9 | stream | test.swift:888:9:888:9 | SSA def(stream) |
| test.swift:888:18:896:6 | call to AsyncStream.init(_:bufferingPolicy:_:) | test.swift:888:9:888:9 | stream |
| test.swift:889:9:889:9 | continuation | test.swift:890:27:895:13 | continuation |
-| test.swift:890:27:895:13 | closure self parameter | test.swift:891:17:891:17 | phi(this) |
+| test.swift:890:27:895:13 | closure self parameter | test.swift:891:17:891:17 | SSA phi read(this) |
| test.swift:891:17:891:17 | $generator | test.swift:891:17:891:17 | &... |
| test.swift:891:17:891:17 | &... | test.swift:891:17:891:17 | $generator |
+| test.swift:891:17:891:17 | SSA phi read(this) | test.swift:892:21:892:21 | this |
+| test.swift:891:17:891:17 | SSA phi read(this) | test.swift:894:17:894:17 | this |
| test.swift:891:17:891:17 | [post] $generator | test.swift:891:17:891:17 | &... |
-| test.swift:891:17:891:17 | phi(this) | test.swift:892:21:892:21 | this |
-| test.swift:891:17:891:17 | phi(this) | test.swift:894:17:894:17 | this |
| test.swift:891:26:891:26 | $generator | test.swift:891:26:891:26 | SSA def($generator) |
| test.swift:891:26:891:26 | SSA def($generator) | test.swift:891:17:891:17 | $generator |
| test.swift:891:26:891:30 | call to makeIterator() | test.swift:891:26:891:26 | $generator |
-| test.swift:892:21:892:21 | this | test.swift:891:17:891:17 | phi(this) |
-| test.swift:892:21:892:21 | this | test.swift:891:17:891:17 | phi(this) |
+| test.swift:892:21:892:21 | this | test.swift:891:17:891:17 | SSA phi read(this) |
+| test.swift:892:21:892:21 | this | test.swift:891:17:891:17 | SSA phi read(this) |
| test.swift:898:5:898:5 | $i$generator | test.swift:898:5:898:5 | &... |
| test.swift:898:5:898:5 | &... | test.swift:898:5:898:5 | $i$generator |
| test.swift:898:5:898:5 | [post] $i$generator | test.swift:898:5:898:5 | &... |
From e30fed6eecf67a28bdc5ca06939d0cc68cee6b73 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Mon, 31 Mar 2025 11:30:40 +0200
Subject: [PATCH 072/409] C#: Improve upgrade script.
---
.../string_interpol_insert.ql | 57 +++++++++++++++++++
.../upgrade.properties | 4 +-
2 files changed, 60 insertions(+), 1 deletion(-)
create mode 100644 csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/string_interpol_insert.ql
diff --git a/csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/string_interpol_insert.ql b/csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/string_interpol_insert.ql
new file mode 100644
index 000000000000..2df164b2842e
--- /dev/null
+++ b/csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/string_interpol_insert.ql
@@ -0,0 +1,57 @@
+class Expr extends @expr {
+ string toString() { none() }
+}
+
+class TypeOrRef extends @type_or_ref {
+ string toString() { none() }
+}
+
+class StringLiteral extends Expr, @string_literal_expr { }
+
+class InterpolatedStringExpr extends Expr, @interpolated_string_expr { }
+
+class StringInterpolationInsert extends Expr, @element {
+ StringInterpolationInsert() {
+ expressions(this, _, _) and
+ expr_parent(this, _, any(InterpolatedStringExpr x)) and
+ not this instanceof StringLiteral
+ }
+}
+
+newtype TAddedElement = TInsert(StringInterpolationInsert e)
+
+module Fresh = QlBuiltins::NewEntity;
+
+class TNewExpr = @expr or Fresh::EntityId;
+
+class NewExpr extends TNewExpr {
+ string toString() { none() }
+}
+
+query predicate new_expressions(NewExpr id, int kind, TypeOrRef t) {
+ expressions(id, kind, t)
+ or
+ exists(StringInterpolationInsert e |
+ // The type of `e` is just copied even though a null type would be preferred.
+ expressions(e, _, t) and
+ Fresh::map(TInsert(e)) = id and
+ kind = 138
+ )
+}
+
+query predicate new_expr_parent(NewExpr id, int child, NewExpr parent) {
+ // Keep all parent child relationships except for string interpolation inserts
+ expr_parent(id, child, parent) and not id instanceof StringInterpolationInsert
+ or
+ exists(StringInterpolationInsert e, int child0, NewExpr p0, NewExpr new_id |
+ expr_parent(e, child0, p0) and new_id = Fresh::map(TInsert(e))
+ |
+ id = new_id and
+ child = child0 and
+ parent = p0
+ or
+ id = e and
+ child = 0 and
+ parent = new_id
+ )
+}
diff --git a/csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/upgrade.properties b/csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/upgrade.properties
index 1989c9c8847b..ef7a5cbf3436 100644
--- a/csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/upgrade.properties
+++ b/csharp/ql/lib/upgrades/a2bda57dbc6eea94c50128522aae536e8edd5a3c/upgrade.properties
@@ -1,2 +1,4 @@
description: Add `interpolated_string_insert_expr` kind.
-compatibility: partial
+compatibility: backwards
+expressions.rel: run string_interpol_insert.qlo new_expressions
+expr_parent.rel: run string_interpol_insert.qlo new_expr_parent
From 8e1282bfde17e8a35194edf9e6adc90d2ff259ec Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Mon, 31 Mar 2025 13:39:03 +0200
Subject: [PATCH 073/409] C#: Improve downgrade script.
---
.../expressions.ql | 13 -------
.../string_interpol_insert.ql | 39 +++++++++++++++++++
.../upgrade.properties | 5 ++-
3 files changed, 42 insertions(+), 15 deletions(-)
delete mode 100644 csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/expressions.ql
create mode 100644 csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/string_interpol_insert.ql
diff --git a/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/expressions.ql b/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/expressions.ql
deleted file mode 100644
index 4f516d1d5cba..000000000000
--- a/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/expressions.ql
+++ /dev/null
@@ -1,13 +0,0 @@
-class Expression extends @expr {
- string toString() { none() }
-}
-
-class TypeOrRef extends @type_or_ref {
- string toString() { none() }
-}
-
-from Expression e, int k, int kind, TypeOrRef t
-where
- expressions(e, k, t) and
- if k = 138 then kind = 106 else kind = k
-select e, kind, t
diff --git a/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/string_interpol_insert.ql b/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/string_interpol_insert.ql
new file mode 100644
index 000000000000..3f83b1ea3cce
--- /dev/null
+++ b/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/string_interpol_insert.ql
@@ -0,0 +1,39 @@
+class Expr extends @expr {
+ string toString() { none() }
+}
+
+class TypeOrRef extends @type_or_ref {
+ string toString() { none() }
+}
+
+class InterpolatedStringInsertExpr extends Expr, @interpolated_string_insert_expr { }
+
+private predicate remove_expr(Expr e) {
+ exists(InterpolatedStringInsertExpr ie |
+ e = ie
+ or
+ // Alignment
+ expr_parent(e, 1, ie)
+ or
+ // Format
+ expr_parent(e, 2, ie)
+ )
+}
+
+query predicate new_expressions(Expr e, int kind, TypeOrRef t) {
+ expressions(e, kind, t) and
+ // Remove the syntheetic intert expression and previously un-extracted children
+ not remove_expr(e)
+}
+
+query predicate new_expr_parent(Expr e, int child, Expr parent) {
+ expr_parent(e, child, parent) and
+ not remove_expr(e) and
+ not remove_expr(parent)
+ or
+ // Use the string interpolation as parent instead of the synthetic insert expression
+ exists(InterpolatedStringInsertExpr ie |
+ expr_parent(e, 0, ie) and
+ expr_parent(ie, child, parent)
+ )
+}
diff --git a/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/upgrade.properties b/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/upgrade.properties
index 9e9a659b10a3..9e8118060f2b 100644
--- a/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/upgrade.properties
+++ b/csharp/downgrades/66044cfa5bbf2ecfabd06ead25e91db2bdd79764/upgrade.properties
@@ -1,3 +1,4 @@
description: Remove `interpolated_string_insert_expr` kind.
-compatibility: partial
-expressions.rel: run expressions.qlo
+compatibility: backwards
+expressions.rel: run string_interpol_insert.qlo new_expressions
+expr_parent.rel: run string_interpol_insert.qlo new_expr_parent
From f64bdccd6de48aa8e758e2cdc0b38aa76dc687c7 Mon Sep 17 00:00:00 2001
From: Asger F
Date: Mon, 31 Mar 2025 15:30:59 +0200
Subject: [PATCH 074/409] Update
javascript/ql/lib/semmle/javascript/ApiGraphs.qll
Co-authored-by: Erik Krogh Kristensen
---
javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index f7b7a3e96d48..1669af0b255e 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -1792,7 +1792,7 @@ module API {
LabelSpreadArgument() { this = MkLabelSpreadArgument(index) }
- /** The argument index at which the spread argument appears. */
+ /** Gets the argument index at which the spread argument appears. */
int getIndex() { result = index }
override string toString() { result = "getSpreadArgument(" + index + ")" }
From 149ec20758460697132cefbf85c401b2a404bdbc Mon Sep 17 00:00:00 2001
From: Asger F
Date: Mon, 31 Mar 2025 15:39:09 +0200
Subject: [PATCH 075/409] JS: Add comment about internal edge
---
javascript/ql/lib/semmle/javascript/ApiGraphs.qll | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
index 1669af0b255e..a1ffc8c02f12 100644
--- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
+++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll
@@ -1795,7 +1795,10 @@ module API {
/** Gets the argument index at which the spread argument appears. */
int getIndex() { result = index }
- override string toString() { result = "getSpreadArgument(" + index + ")" }
+ override string toString() {
+ // Note: This refers to the internal edge that has no corresponding method on API::Node
+ result = "getSpreadArgument(" + index + ")"
+ }
}
/** A label for a function that is a wrapper around another function. */
From e7bb47f335b29661e43ee22e54d66f78c385cb1c Mon Sep 17 00:00:00 2001
From: yoff
Date: Fri, 28 Mar 2025 12:57:58 +0100
Subject: [PATCH 076/409] ruby: add MaD model for permissions needed by actions
Use this to suggest minimal set of nedded permissions
---
actions/ql/lib/codeql/actions/Ast.qll | 2 +
.../lib/codeql/actions/ast/internal/Ast.qll | 2 +
.../ql/lib/codeql/actions/config/Config.qll | 10 +++++
.../actions/config/ConfigExtensions.qll | 5 +++
.../ql/lib/ext/config/actions_permissions.yml | 37 +++++++++++++++++++
.../CWE-275/MissingActionsPermissions.ql | 29 +++++++++++++--
.../CWE-275/.github/workflows/perms6.yml | 13 +++++++
.../MissingActionsPermissions.expected | 7 ++--
8 files changed, 99 insertions(+), 6 deletions(-)
create mode 100644 actions/ql/lib/ext/config/actions_permissions.yml
create mode 100644 actions/ql/test/query-tests/Security/CWE-275/.github/workflows/perms6.yml
diff --git a/actions/ql/lib/codeql/actions/Ast.qll b/actions/ql/lib/codeql/actions/Ast.qll
index 8c1925f3288c..a50febdea973 100644
--- a/actions/ql/lib/codeql/actions/Ast.qll
+++ b/actions/ql/lib/codeql/actions/Ast.qll
@@ -242,6 +242,8 @@ class Step extends AstNode instanceof StepImpl {
If getIf() { result = super.getIf() }
+ AstNode getUses() { result = super.getUses() }
+
StepsContainer getContainer() { result = super.getContainer() }
Step getNextStep() { result = super.getNextStep() }
diff --git a/actions/ql/lib/codeql/actions/ast/internal/Ast.qll b/actions/ql/lib/codeql/actions/ast/internal/Ast.qll
index b0cbb8a1d79e..44ae082a34db 100644
--- a/actions/ql/lib/codeql/actions/ast/internal/Ast.qll
+++ b/actions/ql/lib/codeql/actions/ast/internal/Ast.qll
@@ -1194,6 +1194,8 @@ class StepImpl extends AstNodeImpl, TStepNode {
/** Gets the value of the `if` field in this step, if any. */
IfImpl getIf() { result.getNode() = n.lookup("if") }
+ AstNodeImpl getUses() { result.getNode() = n.lookup("uses") }
+
/** Gets the Runs or LocalJob that this step is in. */
StepsContainerImpl getContainer() {
result = this.getParentNode().(RunsImpl) or
diff --git a/actions/ql/lib/codeql/actions/config/Config.qll b/actions/ql/lib/codeql/actions/config/Config.qll
index 08bc7e860c67..e55d36f1bab8 100644
--- a/actions/ql/lib/codeql/actions/config/Config.qll
+++ b/actions/ql/lib/codeql/actions/config/Config.qll
@@ -154,3 +154,13 @@ predicate untrustedGitCommandDataModel(string cmd_regex, string flag) {
predicate untrustedGhCommandDataModel(string cmd_regex, string flag) {
Extensions::untrustedGhCommandDataModel(cmd_regex, flag)
}
+
+/**
+ * MaD models for permissions needed by actions
+ * Fields:
+ * - action: action name
+ * - permission: permission name
+ */
+predicate actionsPermissionsDataModel(string action, string permission) {
+ Extensions::actionsPermissionsDataModel(action, permission)
+}
diff --git a/actions/ql/lib/codeql/actions/config/ConfigExtensions.qll b/actions/ql/lib/codeql/actions/config/ConfigExtensions.qll
index 68685f5874bb..b86ce68a5fdd 100644
--- a/actions/ql/lib/codeql/actions/config/ConfigExtensions.qll
+++ b/actions/ql/lib/codeql/actions/config/ConfigExtensions.qll
@@ -77,3 +77,8 @@ extensible predicate untrustedGitCommandDataModel(string cmd_regex, string flag)
* Holds for gh commands that may introduce untrusted data
*/
extensible predicate untrustedGhCommandDataModel(string cmd_regex, string flag);
+
+/**
+ * Holds if `action` needs `permission` to run.
+ */
+extensible predicate actionsPermissionsDataModel(string action, string permission);
diff --git a/actions/ql/lib/ext/config/actions_permissions.yml b/actions/ql/lib/ext/config/actions_permissions.yml
new file mode 100644
index 000000000000..6e0081973de6
--- /dev/null
+++ b/actions/ql/lib/ext/config/actions_permissions.yml
@@ -0,0 +1,37 @@
+extensions:
+ - addsTo:
+ pack: codeql/actions-all
+ extensible: actionsPermissionsDataModel
+ data:
+ - ["actions/checkout", "contents: read"]
+ - ["actions/setup-node", "contents: read"]
+ - ["actions/setup-python", "contents: read"]
+ - ["actions/setup-java", "contents: read"]
+ - ["actions/setup-go", "contents: read"]
+ - ["actions/setup-dotnet", "contents: read"]
+ - ["actions/labeler", "contents: read"]
+ - ["actions/labeler", "pull-requests: write"]
+ - ["actions/attest", "id-token: write"]
+ - ["actions/attest", "attestations: write"]
+ # No permissions needed for actions/add-to-project
+ - ["actions/dependency-review-action", "contents: read"]
+ - ["actions/attest-sbom", "id-token: write"]
+ - ["actions/attest-sbom", "attestations: write"]
+ - ["actions/stale", "contents: write"]
+ - ["actions/stale", "issues: write"]
+ - ["actions/stale", "pull-requests: write"]
+ - ["actions/attest-build-provenance", "id-token: write"]
+ - ["actions/attest-build-provenance", "attestations: write"]
+ - ["actions/jekyll-build-pages", "contents: read"]
+ - ["actions/jekyll-build-pages", "pages: write"]
+ - ["actions/jekyll-build-pages", "id-token: write"]
+ - ["actions/publish-action", "contents: write"]
+ - ["actions/versions-package-tools", "contents: read"]
+ - ["actions/versions-package-tools", "actions: read"]
+ - ["actions/reusable-workflows", "contents: read"]
+ - ["actions/reusable-workflows", "actions: read"]
+ # TODO: Add permissions for actions/download-artifact
+ # TODO: Add permissions for actions/upload-artifact
+ # TODO: Add permissions for actions/cache
+
+
diff --git a/actions/ql/src/Security/CWE-275/MissingActionsPermissions.ql b/actions/ql/src/Security/CWE-275/MissingActionsPermissions.ql
index 4f7e951d7ed6..6d5bd04b3e26 100644
--- a/actions/ql/src/Security/CWE-275/MissingActionsPermissions.ql
+++ b/actions/ql/src/Security/CWE-275/MissingActionsPermissions.ql
@@ -14,7 +14,28 @@
import actions
-from Job job
+Step stepInJob(Job job) { result = job.(LocalJob).getAStep() }
+
+bindingset[fullActionSelector]
+string versionedAction(string fullActionSelector) {
+ result = fullActionSelector.substring(0, fullActionSelector.indexOf("@"))
+ or
+ not exists(fullActionSelector.indexOf("@")) and
+ result = fullActionSelector
+}
+
+string stepUses(Step step) { result = step.getUses().(ScalarValue).getValue() }
+
+string jobNeedsPersmission(Job job) {
+ actionsPermissionsDataModel(versionedAction(stepUses(stepInJob(job))), result)
+}
+
+string permissionsForJob(Job job) {
+ result =
+ "{" + concat(string permission | permission = jobNeedsPersmission(job) | permission, ", ") + "}"
+}
+
+from Job job, string permissions
where
not exists(job.getPermissions()) and
not exists(job.getEnclosingWorkflow().getPermissions()) and
@@ -22,5 +43,7 @@ where
exists(Event e |
e = job.getATriggerEvent() and
not e.getName() = "workflow_call"
- )
-select job, "Actions Job or Workflow does not set permissions"
+ ) and
+ permissions = permissionsForJob(job)
+select job,
+ "Actions Job or Workflow does not set permissions. A minimal set might be " + permissions
diff --git a/actions/ql/test/query-tests/Security/CWE-275/.github/workflows/perms6.yml b/actions/ql/test/query-tests/Security/CWE-275/.github/workflows/perms6.yml
new file mode 100644
index 000000000000..2824ca14a7e1
--- /dev/null
+++ b/actions/ql/test/query-tests/Security/CWE-275/.github/workflows/perms6.yml
@@ -0,0 +1,13 @@
+on:
+ workflow_call:
+ workflow_dispatch:
+
+jobs:
+ build:
+ name: Build and test
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/jekyll-build-pages
+
+
diff --git a/actions/ql/test/query-tests/Security/CWE-275/MissingActionsPermissions.expected b/actions/ql/test/query-tests/Security/CWE-275/MissingActionsPermissions.expected
index 8f94d0dc45a6..c7103d6f8ddc 100644
--- a/actions/ql/test/query-tests/Security/CWE-275/MissingActionsPermissions.expected
+++ b/actions/ql/test/query-tests/Security/CWE-275/MissingActionsPermissions.expected
@@ -1,3 +1,4 @@
-| .github/workflows/perms1.yml:6:5:9:32 | Job: build | Actions Job or Workflow does not set permissions |
-| .github/workflows/perms2.yml:6:5:10:2 | Job: build | Actions Job or Workflow does not set permissions |
-| .github/workflows/perms5.yml:7:5:10:32 | Job: build | Actions Job or Workflow does not set permissions |
+| .github/workflows/perms1.yml:6:5:9:32 | Job: build | Actions Job or Workflow does not set permissions. A minimal set might be {contents: read} |
+| .github/workflows/perms2.yml:6:5:10:2 | Job: build | Actions Job or Workflow does not set permissions. A minimal set might be {contents: read} |
+| .github/workflows/perms5.yml:7:5:10:32 | Job: build | Actions Job or Workflow does not set permissions. A minimal set might be {contents: read} |
+| .github/workflows/perms6.yml:7:5:11:39 | Job: build | Actions Job or Workflow does not set permissions. A minimal set might be {contents: read, id-token: write, pages: write} |
From f5d6fd081d1aba415836168cb435fe102737c1e3 Mon Sep 17 00:00:00 2001
From: Paolo Tranquilli
Date: Mon, 31 Mar 2025 16:49:45 +0200
Subject: [PATCH 077/409] Rust: introduce upgrades/downgrades infrastructure
---
misc/scripts/prepare-db-upgrade.sh | 2 +-
rust/BUILD.bazel | 1 +
rust/downgrades/BUILD.bazel | 12 +
rust/downgrades/initial/rust.dbscheme | 3601 ++++++++++++++++++++
rust/downgrades/qlpack.yml | 5 +
rust/ql/lib/upgrades/initial/rust.dbscheme | 3601 ++++++++++++++++++++
6 files changed, 7221 insertions(+), 1 deletion(-)
create mode 100644 rust/downgrades/BUILD.bazel
create mode 100644 rust/downgrades/initial/rust.dbscheme
create mode 100644 rust/downgrades/qlpack.yml
create mode 100644 rust/ql/lib/upgrades/initial/rust.dbscheme
diff --git a/misc/scripts/prepare-db-upgrade.sh b/misc/scripts/prepare-db-upgrade.sh
index 8a8b32d17401..bbbeefc43185 100755
--- a/misc/scripts/prepare-db-upgrade.sh
+++ b/misc/scripts/prepare-db-upgrade.sh
@@ -86,7 +86,7 @@ case "${lang}" in
csharp | cpp | javascript | python)
scheme_file="${lang}/ql/lib/semmlecode.${lang}.dbscheme"
;;
- go | ruby | swift)
+ go | ruby | rust | swift)
scheme_file="${lang}/ql/lib/${lang}.dbscheme"
;;
*)
diff --git a/rust/BUILD.bazel b/rust/BUILD.bazel
index f70f87a9b632..9cdc89dd52fd 100644
--- a/rust/BUILD.bazel
+++ b/rust/BUILD.bazel
@@ -55,6 +55,7 @@ codeql_pack(
srcs = [
":root-files",
":tools",
+ "//rust/downgrades",
],
experimental = True,
)
diff --git a/rust/downgrades/BUILD.bazel b/rust/downgrades/BUILD.bazel
new file mode 100644
index 000000000000..8aff16d8071e
--- /dev/null
+++ b/rust/downgrades/BUILD.bazel
@@ -0,0 +1,12 @@
+load("@rules_pkg//pkg:mappings.bzl", "pkg_files", "strip_prefix")
+
+pkg_files(
+ name = "downgrades",
+ srcs = glob(
+ ["**"],
+ exclude = ["BUILD.bazel"],
+ ),
+ prefix = "downgrades",
+ strip_prefix = strip_prefix.from_pkg(),
+ visibility = ["//rust:__pkg__"],
+)
diff --git a/rust/downgrades/initial/rust.dbscheme b/rust/downgrades/initial/rust.dbscheme
new file mode 100644
index 000000000000..256e80c2dcea
--- /dev/null
+++ b/rust/downgrades/initial/rust.dbscheme
@@ -0,0 +1,3601 @@
+// generated by codegen, do not edit
+
+// from ../shared/tree-sitter-extractor/src/generator/prefix.dbscheme
+/*- Files and folders -*/
+
+/**
+ * The location of an element.
+ * The location spans column `startcolumn` of line `startline` to
+ * column `endcolumn` of line `endline` in file `file`.
+ * For more information, see
+ * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
+ */
+locations_default(
+ unique int id: @location_default,
+ int file: @file ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref
+);
+
+files(
+ unique int id: @file,
+ string name: string ref
+);
+
+folders(
+ unique int id: @folder,
+ string name: string ref
+);
+
+@container = @file | @folder
+
+containerparent(
+ int parent: @container ref,
+ unique int child: @container ref
+);
+
+/*- Empty location -*/
+
+empty_location(
+ int location: @location_default ref
+);
+
+/*- Source location prefix -*/
+
+/**
+ * The source location of the snapshot.
+ */
+sourceLocationPrefix(string prefix : string ref);
+
+/*- Diagnostic messages -*/
+
+diagnostics(
+ unique int id: @diagnostic,
+ int severity: int ref,
+ string error_tag: string ref,
+ string error_message: string ref,
+ string full_error_message: string ref,
+ int location: @location_default ref
+);
+
+/*- Diagnostic messages: severity -*/
+
+case @diagnostic.severity of
+ 10 = @diagnostic_debug
+| 20 = @diagnostic_info
+| 30 = @diagnostic_warning
+| 40 = @diagnostic_error
+;
+
+/*- YAML -*/
+
+#keyset[parent, idx]
+yaml (unique int id: @yaml_node,
+ int kind: int ref,
+ int parent: @yaml_node_parent ref,
+ int idx: int ref,
+ string tag: string ref,
+ string tostring: string ref);
+
+case @yaml_node.kind of
+ 0 = @yaml_scalar_node
+| 1 = @yaml_mapping_node
+| 2 = @yaml_sequence_node
+| 3 = @yaml_alias_node
+;
+
+@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node;
+
+@yaml_node_parent = @yaml_collection_node | @file;
+
+yaml_anchors (unique int node: @yaml_node ref,
+ string anchor: string ref);
+
+yaml_aliases (unique int alias: @yaml_alias_node ref,
+ string target: string ref);
+
+yaml_scalars (unique int scalar: @yaml_scalar_node ref,
+ int style: int ref,
+ string value: string ref);
+
+yaml_errors (unique int id: @yaml_error,
+ string message: string ref);
+
+yaml_locations(unique int locatable: @yaml_locatable ref,
+ int location: @location_default ref);
+
+@yaml_locatable = @yaml_node | @yaml_error;
+
+
+// from prefix.dbscheme
+#keyset[id]
+locatable_locations(
+ int id: @locatable ref,
+ int location: @location_default ref
+);
+
+
+// from schema
+
+@element =
+ @extractor_step
+| @locatable
+| @named_crate
+| @unextracted
+;
+
+extractor_steps(
+ unique int id: @extractor_step,
+ string action: string ref,
+ int duration_ms: int ref
+);
+
+#keyset[id]
+extractor_step_files(
+ int id: @extractor_step ref,
+ int file: @file ref
+);
+
+@locatable =
+ @ast_node
+| @crate
+;
+
+named_crates(
+ unique int id: @named_crate,
+ string name: string ref,
+ int crate: @crate ref
+);
+
+@unextracted =
+ @missing
+| @unimplemented
+;
+
+@ast_node =
+ @abi
+| @addressable
+| @arg_list
+| @asm_dir_spec
+| @asm_operand
+| @asm_operand_expr
+| @asm_option
+| @asm_piece
+| @asm_reg_spec
+| @assoc_item
+| @assoc_item_list
+| @attr
+| @callable
+| @closure_binder
+| @expr
+| @extern_item
+| @extern_item_list
+| @field_list
+| @format_args_arg
+| @generic_arg
+| @generic_arg_list
+| @generic_param
+| @generic_param_list
+| @item_list
+| @label
+| @let_else
+| @macro_items
+| @macro_stmts
+| @match_arm
+| @match_arm_list
+| @match_guard
+| @meta
+| @name
+| @param_base
+| @param_list
+| @parenthesized_arg_list
+| @pat
+| @path
+| @path_segment
+| @rename
+| @resolvable
+| @ret_type_repr
+| @return_type_syntax
+| @source_file
+| @stmt
+| @stmt_list
+| @struct_expr_field
+| @struct_expr_field_list
+| @struct_field
+| @struct_pat_field
+| @struct_pat_field_list
+| @token
+| @token_tree
+| @tuple_field
+| @type_bound
+| @type_bound_list
+| @type_repr
+| @use_bound_generic_arg
+| @use_bound_generic_args
+| @use_tree
+| @use_tree_list
+| @variant_def
+| @variant_list
+| @visibility
+| @where_clause
+| @where_pred
+;
+
+crates(
+ unique int id: @crate
+);
+
+#keyset[id]
+crate_names(
+ int id: @crate ref,
+ string name: string ref
+);
+
+#keyset[id]
+crate_versions(
+ int id: @crate ref,
+ string version: string ref
+);
+
+#keyset[id]
+crate_modules(
+ int id: @crate ref,
+ int module: @module ref
+);
+
+#keyset[id, index]
+crate_cfg_options(
+ int id: @crate ref,
+ int index: int ref,
+ string cfg_option: string ref
+);
+
+#keyset[id, index]
+crate_named_dependencies(
+ int id: @crate ref,
+ int index: int ref,
+ int named_dependency: @named_crate ref
+);
+
+missings(
+ unique int id: @missing
+);
+
+unimplementeds(
+ unique int id: @unimplemented
+);
+
+abis(
+ unique int id: @abi
+);
+
+#keyset[id]
+abi_abi_strings(
+ int id: @abi ref,
+ string abi_string: string ref
+);
+
+@addressable =
+ @item
+| @variant
+;
+
+#keyset[id]
+addressable_extended_canonical_paths(
+ int id: @addressable ref,
+ string extended_canonical_path: string ref
+);
+
+#keyset[id]
+addressable_crate_origins(
+ int id: @addressable ref,
+ string crate_origin: string ref
+);
+
+arg_lists(
+ unique int id: @arg_list
+);
+
+#keyset[id, index]
+arg_list_args(
+ int id: @arg_list ref,
+ int index: int ref,
+ int arg: @expr ref
+);
+
+asm_dir_specs(
+ unique int id: @asm_dir_spec
+);
+
+@asm_operand =
+ @asm_const
+| @asm_label
+| @asm_reg_operand
+| @asm_sym
+;
+
+asm_operand_exprs(
+ unique int id: @asm_operand_expr
+);
+
+#keyset[id]
+asm_operand_expr_in_exprs(
+ int id: @asm_operand_expr ref,
+ int in_expr: @expr ref
+);
+
+#keyset[id]
+asm_operand_expr_out_exprs(
+ int id: @asm_operand_expr ref,
+ int out_expr: @expr ref
+);
+
+asm_options(
+ unique int id: @asm_option
+);
+
+#keyset[id]
+asm_option_is_raw(
+ int id: @asm_option ref
+);
+
+@asm_piece =
+ @asm_clobber_abi
+| @asm_operand_named
+| @asm_options_list
+;
+
+asm_reg_specs(
+ unique int id: @asm_reg_spec
+);
+
+#keyset[id]
+asm_reg_spec_identifiers(
+ int id: @asm_reg_spec ref,
+ int identifier: @name_ref ref
+);
+
+@assoc_item =
+ @const
+| @function
+| @macro_call
+| @type_alias
+;
+
+assoc_item_lists(
+ unique int id: @assoc_item_list
+);
+
+#keyset[id, index]
+assoc_item_list_assoc_items(
+ int id: @assoc_item_list ref,
+ int index: int ref,
+ int assoc_item: @assoc_item ref
+);
+
+#keyset[id, index]
+assoc_item_list_attrs(
+ int id: @assoc_item_list ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+attrs(
+ unique int id: @attr
+);
+
+#keyset[id]
+attr_meta(
+ int id: @attr ref,
+ int meta: @meta ref
+);
+
+@callable =
+ @closure_expr
+| @function
+;
+
+#keyset[id]
+callable_param_lists(
+ int id: @callable ref,
+ int param_list: @param_list ref
+);
+
+#keyset[id, index]
+callable_attrs(
+ int id: @callable ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+closure_binders(
+ unique int id: @closure_binder
+);
+
+#keyset[id]
+closure_binder_generic_param_lists(
+ int id: @closure_binder ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+@expr =
+ @array_expr_internal
+| @asm_expr
+| @await_expr
+| @become_expr
+| @binary_expr
+| @break_expr
+| @call_expr_base
+| @cast_expr
+| @closure_expr
+| @continue_expr
+| @field_expr
+| @format_args_expr
+| @if_expr
+| @index_expr
+| @labelable_expr
+| @let_expr
+| @literal_expr
+| @macro_expr
+| @match_expr
+| @offset_of_expr
+| @paren_expr
+| @path_expr_base
+| @prefix_expr
+| @range_expr
+| @ref_expr
+| @return_expr
+| @struct_expr
+| @try_expr
+| @tuple_expr
+| @underscore_expr
+| @yeet_expr
+| @yield_expr
+;
+
+@extern_item =
+ @function
+| @macro_call
+| @static
+| @type_alias
+;
+
+extern_item_lists(
+ unique int id: @extern_item_list
+);
+
+#keyset[id, index]
+extern_item_list_attrs(
+ int id: @extern_item_list ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+extern_item_list_extern_items(
+ int id: @extern_item_list ref,
+ int index: int ref,
+ int extern_item: @extern_item ref
+);
+
+@field_list =
+ @struct_field_list
+| @tuple_field_list
+;
+
+format_args_args(
+ unique int id: @format_args_arg
+);
+
+#keyset[id]
+format_args_arg_exprs(
+ int id: @format_args_arg ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+format_args_arg_names(
+ int id: @format_args_arg ref,
+ int name: @name ref
+);
+
+@generic_arg =
+ @assoc_type_arg
+| @const_arg
+| @lifetime_arg
+| @type_arg
+;
+
+generic_arg_lists(
+ unique int id: @generic_arg_list
+);
+
+#keyset[id, index]
+generic_arg_list_generic_args(
+ int id: @generic_arg_list ref,
+ int index: int ref,
+ int generic_arg: @generic_arg ref
+);
+
+@generic_param =
+ @const_param
+| @lifetime_param
+| @type_param
+;
+
+generic_param_lists(
+ unique int id: @generic_param_list
+);
+
+#keyset[id, index]
+generic_param_list_generic_params(
+ int id: @generic_param_list ref,
+ int index: int ref,
+ int generic_param: @generic_param ref
+);
+
+item_lists(
+ unique int id: @item_list
+);
+
+#keyset[id, index]
+item_list_attrs(
+ int id: @item_list ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+item_list_items(
+ int id: @item_list ref,
+ int index: int ref,
+ int item: @item ref
+);
+
+labels(
+ unique int id: @label
+);
+
+#keyset[id]
+label_lifetimes(
+ int id: @label ref,
+ int lifetime: @lifetime ref
+);
+
+let_elses(
+ unique int id: @let_else
+);
+
+#keyset[id]
+let_else_block_exprs(
+ int id: @let_else ref,
+ int block_expr: @block_expr ref
+);
+
+macro_items(
+ unique int id: @macro_items
+);
+
+#keyset[id, index]
+macro_items_items(
+ int id: @macro_items ref,
+ int index: int ref,
+ int item: @item ref
+);
+
+macro_stmts(
+ unique int id: @macro_stmts
+);
+
+#keyset[id]
+macro_stmts_exprs(
+ int id: @macro_stmts ref,
+ int expr: @expr ref
+);
+
+#keyset[id, index]
+macro_stmts_statements(
+ int id: @macro_stmts ref,
+ int index: int ref,
+ int statement: @stmt ref
+);
+
+match_arms(
+ unique int id: @match_arm
+);
+
+#keyset[id, index]
+match_arm_attrs(
+ int id: @match_arm ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+match_arm_exprs(
+ int id: @match_arm ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+match_arm_guards(
+ int id: @match_arm ref,
+ int guard: @match_guard ref
+);
+
+#keyset[id]
+match_arm_pats(
+ int id: @match_arm ref,
+ int pat: @pat ref
+);
+
+match_arm_lists(
+ unique int id: @match_arm_list
+);
+
+#keyset[id, index]
+match_arm_list_arms(
+ int id: @match_arm_list ref,
+ int index: int ref,
+ int arm: @match_arm ref
+);
+
+#keyset[id, index]
+match_arm_list_attrs(
+ int id: @match_arm_list ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+match_guards(
+ unique int id: @match_guard
+);
+
+#keyset[id]
+match_guard_conditions(
+ int id: @match_guard ref,
+ int condition: @expr ref
+);
+
+meta(
+ unique int id: @meta
+);
+
+#keyset[id]
+meta_exprs(
+ int id: @meta ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+meta_is_unsafe(
+ int id: @meta ref
+);
+
+#keyset[id]
+meta_paths(
+ int id: @meta ref,
+ int path: @path ref
+);
+
+#keyset[id]
+meta_token_trees(
+ int id: @meta ref,
+ int token_tree: @token_tree ref
+);
+
+names(
+ unique int id: @name
+);
+
+#keyset[id]
+name_texts(
+ int id: @name ref,
+ string text: string ref
+);
+
+@param_base =
+ @param
+| @self_param
+;
+
+#keyset[id, index]
+param_base_attrs(
+ int id: @param_base ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+param_base_type_reprs(
+ int id: @param_base ref,
+ int type_repr: @type_repr ref
+);
+
+param_lists(
+ unique int id: @param_list
+);
+
+#keyset[id, index]
+param_list_params(
+ int id: @param_list ref,
+ int index: int ref,
+ int param: @param ref
+);
+
+#keyset[id]
+param_list_self_params(
+ int id: @param_list ref,
+ int self_param: @self_param ref
+);
+
+parenthesized_arg_lists(
+ unique int id: @parenthesized_arg_list
+);
+
+#keyset[id, index]
+parenthesized_arg_list_type_args(
+ int id: @parenthesized_arg_list ref,
+ int index: int ref,
+ int type_arg: @type_arg ref
+);
+
+@pat =
+ @box_pat
+| @const_block_pat
+| @ident_pat
+| @literal_pat
+| @macro_pat
+| @or_pat
+| @paren_pat
+| @path_pat
+| @range_pat
+| @ref_pat
+| @rest_pat
+| @slice_pat
+| @struct_pat
+| @tuple_pat
+| @tuple_struct_pat
+| @wildcard_pat
+;
+
+paths(
+ unique int id: @path
+);
+
+#keyset[id]
+path_qualifiers(
+ int id: @path ref,
+ int qualifier: @path ref
+);
+
+#keyset[id]
+path_segments_(
+ int id: @path ref,
+ int segment: @path_segment ref
+);
+
+path_segments(
+ unique int id: @path_segment
+);
+
+#keyset[id]
+path_segment_generic_arg_lists(
+ int id: @path_segment ref,
+ int generic_arg_list: @generic_arg_list ref
+);
+
+#keyset[id]
+path_segment_identifiers(
+ int id: @path_segment ref,
+ int identifier: @name_ref ref
+);
+
+#keyset[id]
+path_segment_parenthesized_arg_lists(
+ int id: @path_segment ref,
+ int parenthesized_arg_list: @parenthesized_arg_list ref
+);
+
+#keyset[id]
+path_segment_ret_types(
+ int id: @path_segment ref,
+ int ret_type: @ret_type_repr ref
+);
+
+#keyset[id]
+path_segment_return_type_syntaxes(
+ int id: @path_segment ref,
+ int return_type_syntax: @return_type_syntax ref
+);
+
+#keyset[id]
+path_segment_type_reprs(
+ int id: @path_segment ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+path_segment_trait_type_reprs(
+ int id: @path_segment ref,
+ int trait_type_repr: @path_type_repr ref
+);
+
+renames(
+ unique int id: @rename
+);
+
+#keyset[id]
+rename_names(
+ int id: @rename ref,
+ int name: @name ref
+);
+
+@resolvable =
+ @method_call_expr
+| @path_ast_node
+;
+
+#keyset[id]
+resolvable_resolved_paths(
+ int id: @resolvable ref,
+ string resolved_path: string ref
+);
+
+#keyset[id]
+resolvable_resolved_crate_origins(
+ int id: @resolvable ref,
+ string resolved_crate_origin: string ref
+);
+
+ret_type_reprs(
+ unique int id: @ret_type_repr
+);
+
+#keyset[id]
+ret_type_repr_type_reprs(
+ int id: @ret_type_repr ref,
+ int type_repr: @type_repr ref
+);
+
+return_type_syntaxes(
+ unique int id: @return_type_syntax
+);
+
+source_files(
+ unique int id: @source_file
+);
+
+#keyset[id, index]
+source_file_attrs(
+ int id: @source_file ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+source_file_items(
+ int id: @source_file ref,
+ int index: int ref,
+ int item: @item ref
+);
+
+@stmt =
+ @expr_stmt
+| @item
+| @let_stmt
+;
+
+stmt_lists(
+ unique int id: @stmt_list
+);
+
+#keyset[id, index]
+stmt_list_attrs(
+ int id: @stmt_list ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+stmt_list_statements(
+ int id: @stmt_list ref,
+ int index: int ref,
+ int statement: @stmt ref
+);
+
+#keyset[id]
+stmt_list_tail_exprs(
+ int id: @stmt_list ref,
+ int tail_expr: @expr ref
+);
+
+struct_expr_fields(
+ unique int id: @struct_expr_field
+);
+
+#keyset[id, index]
+struct_expr_field_attrs(
+ int id: @struct_expr_field ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+struct_expr_field_exprs(
+ int id: @struct_expr_field ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+struct_expr_field_identifiers(
+ int id: @struct_expr_field ref,
+ int identifier: @name_ref ref
+);
+
+struct_expr_field_lists(
+ unique int id: @struct_expr_field_list
+);
+
+#keyset[id, index]
+struct_expr_field_list_attrs(
+ int id: @struct_expr_field_list ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+struct_expr_field_list_fields(
+ int id: @struct_expr_field_list ref,
+ int index: int ref,
+ int field: @struct_expr_field ref
+);
+
+#keyset[id]
+struct_expr_field_list_spreads(
+ int id: @struct_expr_field_list ref,
+ int spread: @expr ref
+);
+
+struct_fields(
+ unique int id: @struct_field
+);
+
+#keyset[id, index]
+struct_field_attrs(
+ int id: @struct_field ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+struct_field_defaults(
+ int id: @struct_field ref,
+ int default: @expr ref
+);
+
+#keyset[id]
+struct_field_names(
+ int id: @struct_field ref,
+ int name: @name ref
+);
+
+#keyset[id]
+struct_field_type_reprs(
+ int id: @struct_field ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+struct_field_visibilities(
+ int id: @struct_field ref,
+ int visibility: @visibility ref
+);
+
+struct_pat_fields(
+ unique int id: @struct_pat_field
+);
+
+#keyset[id, index]
+struct_pat_field_attrs(
+ int id: @struct_pat_field ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+struct_pat_field_identifiers(
+ int id: @struct_pat_field ref,
+ int identifier: @name_ref ref
+);
+
+#keyset[id]
+struct_pat_field_pats(
+ int id: @struct_pat_field ref,
+ int pat: @pat ref
+);
+
+struct_pat_field_lists(
+ unique int id: @struct_pat_field_list
+);
+
+#keyset[id, index]
+struct_pat_field_list_fields(
+ int id: @struct_pat_field_list ref,
+ int index: int ref,
+ int field: @struct_pat_field ref
+);
+
+#keyset[id]
+struct_pat_field_list_rest_pats(
+ int id: @struct_pat_field_list ref,
+ int rest_pat: @rest_pat ref
+);
+
+@token =
+ @comment
+;
+
+token_trees(
+ unique int id: @token_tree
+);
+
+tuple_fields(
+ unique int id: @tuple_field
+);
+
+#keyset[id, index]
+tuple_field_attrs(
+ int id: @tuple_field ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+tuple_field_type_reprs(
+ int id: @tuple_field ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+tuple_field_visibilities(
+ int id: @tuple_field ref,
+ int visibility: @visibility ref
+);
+
+type_bounds(
+ unique int id: @type_bound
+);
+
+#keyset[id]
+type_bound_is_async(
+ int id: @type_bound ref
+);
+
+#keyset[id]
+type_bound_is_const(
+ int id: @type_bound ref
+);
+
+#keyset[id]
+type_bound_lifetimes(
+ int id: @type_bound ref,
+ int lifetime: @lifetime ref
+);
+
+#keyset[id]
+type_bound_type_reprs(
+ int id: @type_bound ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+type_bound_use_bound_generic_args(
+ int id: @type_bound ref,
+ int use_bound_generic_args: @use_bound_generic_args ref
+);
+
+type_bound_lists(
+ unique int id: @type_bound_list
+);
+
+#keyset[id, index]
+type_bound_list_bounds(
+ int id: @type_bound_list ref,
+ int index: int ref,
+ int bound: @type_bound ref
+);
+
+@type_repr =
+ @array_type_repr
+| @dyn_trait_type_repr
+| @fn_ptr_type_repr
+| @for_type_repr
+| @impl_trait_type_repr
+| @infer_type_repr
+| @macro_type_repr
+| @never_type_repr
+| @paren_type_repr
+| @path_type_repr
+| @ptr_type_repr
+| @ref_type_repr
+| @slice_type_repr
+| @tuple_type_repr
+;
+
+@use_bound_generic_arg =
+ @lifetime
+| @name_ref
+;
+
+use_bound_generic_args(
+ unique int id: @use_bound_generic_args
+);
+
+#keyset[id, index]
+use_bound_generic_args_use_bound_generic_args(
+ int id: @use_bound_generic_args ref,
+ int index: int ref,
+ int use_bound_generic_arg: @use_bound_generic_arg ref
+);
+
+use_trees(
+ unique int id: @use_tree
+);
+
+#keyset[id]
+use_tree_is_glob(
+ int id: @use_tree ref
+);
+
+#keyset[id]
+use_tree_paths(
+ int id: @use_tree ref,
+ int path: @path ref
+);
+
+#keyset[id]
+use_tree_renames(
+ int id: @use_tree ref,
+ int rename: @rename ref
+);
+
+#keyset[id]
+use_tree_use_tree_lists(
+ int id: @use_tree ref,
+ int use_tree_list: @use_tree_list ref
+);
+
+use_tree_lists(
+ unique int id: @use_tree_list
+);
+
+#keyset[id, index]
+use_tree_list_use_trees(
+ int id: @use_tree_list ref,
+ int index: int ref,
+ int use_tree: @use_tree ref
+);
+
+@variant_def =
+ @struct
+| @union
+| @variant
+;
+
+variant_lists(
+ unique int id: @variant_list
+);
+
+#keyset[id, index]
+variant_list_variants(
+ int id: @variant_list ref,
+ int index: int ref,
+ int variant: @variant ref
+);
+
+visibilities(
+ unique int id: @visibility
+);
+
+#keyset[id]
+visibility_paths(
+ int id: @visibility ref,
+ int path: @path ref
+);
+
+where_clauses(
+ unique int id: @where_clause
+);
+
+#keyset[id, index]
+where_clause_predicates(
+ int id: @where_clause ref,
+ int index: int ref,
+ int predicate: @where_pred ref
+);
+
+where_preds(
+ unique int id: @where_pred
+);
+
+#keyset[id]
+where_pred_generic_param_lists(
+ int id: @where_pred ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+where_pred_lifetimes(
+ int id: @where_pred ref,
+ int lifetime: @lifetime ref
+);
+
+#keyset[id]
+where_pred_type_reprs(
+ int id: @where_pred ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+where_pred_type_bound_lists(
+ int id: @where_pred ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+array_expr_internals(
+ unique int id: @array_expr_internal
+);
+
+#keyset[id, index]
+array_expr_internal_attrs(
+ int id: @array_expr_internal ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+array_expr_internal_exprs(
+ int id: @array_expr_internal ref,
+ int index: int ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+array_expr_internal_is_semicolon(
+ int id: @array_expr_internal ref
+);
+
+array_type_reprs(
+ unique int id: @array_type_repr
+);
+
+#keyset[id]
+array_type_repr_const_args(
+ int id: @array_type_repr ref,
+ int const_arg: @const_arg ref
+);
+
+#keyset[id]
+array_type_repr_element_type_reprs(
+ int id: @array_type_repr ref,
+ int element_type_repr: @type_repr ref
+);
+
+asm_clobber_abis(
+ unique int id: @asm_clobber_abi
+);
+
+asm_consts(
+ unique int id: @asm_const
+);
+
+#keyset[id]
+asm_const_exprs(
+ int id: @asm_const ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+asm_const_is_const(
+ int id: @asm_const ref
+);
+
+asm_exprs(
+ unique int id: @asm_expr
+);
+
+#keyset[id, index]
+asm_expr_asm_pieces(
+ int id: @asm_expr ref,
+ int index: int ref,
+ int asm_piece: @asm_piece ref
+);
+
+#keyset[id, index]
+asm_expr_attrs(
+ int id: @asm_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+asm_expr_templates(
+ int id: @asm_expr ref,
+ int index: int ref,
+ int template: @expr ref
+);
+
+asm_labels(
+ unique int id: @asm_label
+);
+
+#keyset[id]
+asm_label_block_exprs(
+ int id: @asm_label ref,
+ int block_expr: @block_expr ref
+);
+
+asm_operand_nameds(
+ unique int id: @asm_operand_named
+);
+
+#keyset[id]
+asm_operand_named_asm_operands(
+ int id: @asm_operand_named ref,
+ int asm_operand: @asm_operand ref
+);
+
+#keyset[id]
+asm_operand_named_names(
+ int id: @asm_operand_named ref,
+ int name: @name ref
+);
+
+asm_options_lists(
+ unique int id: @asm_options_list
+);
+
+#keyset[id, index]
+asm_options_list_asm_options(
+ int id: @asm_options_list ref,
+ int index: int ref,
+ int asm_option: @asm_option ref
+);
+
+asm_reg_operands(
+ unique int id: @asm_reg_operand
+);
+
+#keyset[id]
+asm_reg_operand_asm_dir_specs(
+ int id: @asm_reg_operand ref,
+ int asm_dir_spec: @asm_dir_spec ref
+);
+
+#keyset[id]
+asm_reg_operand_asm_operand_exprs(
+ int id: @asm_reg_operand ref,
+ int asm_operand_expr: @asm_operand_expr ref
+);
+
+#keyset[id]
+asm_reg_operand_asm_reg_specs(
+ int id: @asm_reg_operand ref,
+ int asm_reg_spec: @asm_reg_spec ref
+);
+
+asm_syms(
+ unique int id: @asm_sym
+);
+
+#keyset[id]
+asm_sym_paths(
+ int id: @asm_sym ref,
+ int path: @path ref
+);
+
+assoc_type_args(
+ unique int id: @assoc_type_arg
+);
+
+#keyset[id]
+assoc_type_arg_const_args(
+ int id: @assoc_type_arg ref,
+ int const_arg: @const_arg ref
+);
+
+#keyset[id]
+assoc_type_arg_generic_arg_lists(
+ int id: @assoc_type_arg ref,
+ int generic_arg_list: @generic_arg_list ref
+);
+
+#keyset[id]
+assoc_type_arg_identifiers(
+ int id: @assoc_type_arg ref,
+ int identifier: @name_ref ref
+);
+
+#keyset[id]
+assoc_type_arg_param_lists(
+ int id: @assoc_type_arg ref,
+ int param_list: @param_list ref
+);
+
+#keyset[id]
+assoc_type_arg_ret_types(
+ int id: @assoc_type_arg ref,
+ int ret_type: @ret_type_repr ref
+);
+
+#keyset[id]
+assoc_type_arg_return_type_syntaxes(
+ int id: @assoc_type_arg ref,
+ int return_type_syntax: @return_type_syntax ref
+);
+
+#keyset[id]
+assoc_type_arg_type_reprs(
+ int id: @assoc_type_arg ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+assoc_type_arg_type_bound_lists(
+ int id: @assoc_type_arg ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+await_exprs(
+ unique int id: @await_expr
+);
+
+#keyset[id, index]
+await_expr_attrs(
+ int id: @await_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+await_expr_exprs(
+ int id: @await_expr ref,
+ int expr: @expr ref
+);
+
+become_exprs(
+ unique int id: @become_expr
+);
+
+#keyset[id, index]
+become_expr_attrs(
+ int id: @become_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+become_expr_exprs(
+ int id: @become_expr ref,
+ int expr: @expr ref
+);
+
+binary_exprs(
+ unique int id: @binary_expr
+);
+
+#keyset[id, index]
+binary_expr_attrs(
+ int id: @binary_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+binary_expr_lhs(
+ int id: @binary_expr ref,
+ int lhs: @expr ref
+);
+
+#keyset[id]
+binary_expr_operator_names(
+ int id: @binary_expr ref,
+ string operator_name: string ref
+);
+
+#keyset[id]
+binary_expr_rhs(
+ int id: @binary_expr ref,
+ int rhs: @expr ref
+);
+
+box_pats(
+ unique int id: @box_pat
+);
+
+#keyset[id]
+box_pat_pats(
+ int id: @box_pat ref,
+ int pat: @pat ref
+);
+
+break_exprs(
+ unique int id: @break_expr
+);
+
+#keyset[id, index]
+break_expr_attrs(
+ int id: @break_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+break_expr_exprs(
+ int id: @break_expr ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+break_expr_lifetimes(
+ int id: @break_expr ref,
+ int lifetime: @lifetime ref
+);
+
+@call_expr_base =
+ @call_expr
+| @method_call_expr
+;
+
+#keyset[id]
+call_expr_base_arg_lists(
+ int id: @call_expr_base ref,
+ int arg_list: @arg_list ref
+);
+
+#keyset[id, index]
+call_expr_base_attrs(
+ int id: @call_expr_base ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+cast_exprs(
+ unique int id: @cast_expr
+);
+
+#keyset[id, index]
+cast_expr_attrs(
+ int id: @cast_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+cast_expr_exprs(
+ int id: @cast_expr ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+cast_expr_type_reprs(
+ int id: @cast_expr ref,
+ int type_repr: @type_repr ref
+);
+
+closure_exprs(
+ unique int id: @closure_expr
+);
+
+#keyset[id]
+closure_expr_bodies(
+ int id: @closure_expr ref,
+ int body: @expr ref
+);
+
+#keyset[id]
+closure_expr_closure_binders(
+ int id: @closure_expr ref,
+ int closure_binder: @closure_binder ref
+);
+
+#keyset[id]
+closure_expr_is_async(
+ int id: @closure_expr ref
+);
+
+#keyset[id]
+closure_expr_is_const(
+ int id: @closure_expr ref
+);
+
+#keyset[id]
+closure_expr_is_gen(
+ int id: @closure_expr ref
+);
+
+#keyset[id]
+closure_expr_is_move(
+ int id: @closure_expr ref
+);
+
+#keyset[id]
+closure_expr_is_static(
+ int id: @closure_expr ref
+);
+
+#keyset[id]
+closure_expr_ret_types(
+ int id: @closure_expr ref,
+ int ret_type: @ret_type_repr ref
+);
+
+comments(
+ unique int id: @comment,
+ int parent: @ast_node ref,
+ string text: string ref
+);
+
+const_args(
+ unique int id: @const_arg
+);
+
+#keyset[id]
+const_arg_exprs(
+ int id: @const_arg ref,
+ int expr: @expr ref
+);
+
+const_block_pats(
+ unique int id: @const_block_pat
+);
+
+#keyset[id]
+const_block_pat_block_exprs(
+ int id: @const_block_pat ref,
+ int block_expr: @block_expr ref
+);
+
+#keyset[id]
+const_block_pat_is_const(
+ int id: @const_block_pat ref
+);
+
+const_params(
+ unique int id: @const_param
+);
+
+#keyset[id, index]
+const_param_attrs(
+ int id: @const_param ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+const_param_default_vals(
+ int id: @const_param ref,
+ int default_val: @const_arg ref
+);
+
+#keyset[id]
+const_param_is_const(
+ int id: @const_param ref
+);
+
+#keyset[id]
+const_param_names(
+ int id: @const_param ref,
+ int name: @name ref
+);
+
+#keyset[id]
+const_param_type_reprs(
+ int id: @const_param ref,
+ int type_repr: @type_repr ref
+);
+
+continue_exprs(
+ unique int id: @continue_expr
+);
+
+#keyset[id, index]
+continue_expr_attrs(
+ int id: @continue_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+continue_expr_lifetimes(
+ int id: @continue_expr ref,
+ int lifetime: @lifetime ref
+);
+
+dyn_trait_type_reprs(
+ unique int id: @dyn_trait_type_repr
+);
+
+#keyset[id]
+dyn_trait_type_repr_type_bound_lists(
+ int id: @dyn_trait_type_repr ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+expr_stmts(
+ unique int id: @expr_stmt
+);
+
+#keyset[id]
+expr_stmt_exprs(
+ int id: @expr_stmt ref,
+ int expr: @expr ref
+);
+
+field_exprs(
+ unique int id: @field_expr
+);
+
+#keyset[id, index]
+field_expr_attrs(
+ int id: @field_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+field_expr_containers(
+ int id: @field_expr ref,
+ int container: @expr ref
+);
+
+#keyset[id]
+field_expr_identifiers(
+ int id: @field_expr ref,
+ int identifier: @name_ref ref
+);
+
+fn_ptr_type_reprs(
+ unique int id: @fn_ptr_type_repr
+);
+
+#keyset[id]
+fn_ptr_type_repr_abis(
+ int id: @fn_ptr_type_repr ref,
+ int abi: @abi ref
+);
+
+#keyset[id]
+fn_ptr_type_repr_is_async(
+ int id: @fn_ptr_type_repr ref
+);
+
+#keyset[id]
+fn_ptr_type_repr_is_const(
+ int id: @fn_ptr_type_repr ref
+);
+
+#keyset[id]
+fn_ptr_type_repr_is_unsafe(
+ int id: @fn_ptr_type_repr ref
+);
+
+#keyset[id]
+fn_ptr_type_repr_param_lists(
+ int id: @fn_ptr_type_repr ref,
+ int param_list: @param_list ref
+);
+
+#keyset[id]
+fn_ptr_type_repr_ret_types(
+ int id: @fn_ptr_type_repr ref,
+ int ret_type: @ret_type_repr ref
+);
+
+for_type_reprs(
+ unique int id: @for_type_repr
+);
+
+#keyset[id]
+for_type_repr_generic_param_lists(
+ int id: @for_type_repr ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+for_type_repr_type_reprs(
+ int id: @for_type_repr ref,
+ int type_repr: @type_repr ref
+);
+
+format_args_exprs(
+ unique int id: @format_args_expr
+);
+
+#keyset[id, index]
+format_args_expr_args(
+ int id: @format_args_expr ref,
+ int index: int ref,
+ int arg: @format_args_arg ref
+);
+
+#keyset[id, index]
+format_args_expr_attrs(
+ int id: @format_args_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+format_args_expr_templates(
+ int id: @format_args_expr ref,
+ int template: @expr ref
+);
+
+ident_pats(
+ unique int id: @ident_pat
+);
+
+#keyset[id, index]
+ident_pat_attrs(
+ int id: @ident_pat ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+ident_pat_is_mut(
+ int id: @ident_pat ref
+);
+
+#keyset[id]
+ident_pat_is_ref(
+ int id: @ident_pat ref
+);
+
+#keyset[id]
+ident_pat_names(
+ int id: @ident_pat ref,
+ int name: @name ref
+);
+
+#keyset[id]
+ident_pat_pats(
+ int id: @ident_pat ref,
+ int pat: @pat ref
+);
+
+if_exprs(
+ unique int id: @if_expr
+);
+
+#keyset[id, index]
+if_expr_attrs(
+ int id: @if_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+if_expr_conditions(
+ int id: @if_expr ref,
+ int condition: @expr ref
+);
+
+#keyset[id]
+if_expr_elses(
+ int id: @if_expr ref,
+ int else: @expr ref
+);
+
+#keyset[id]
+if_expr_thens(
+ int id: @if_expr ref,
+ int then: @block_expr ref
+);
+
+impl_trait_type_reprs(
+ unique int id: @impl_trait_type_repr
+);
+
+#keyset[id]
+impl_trait_type_repr_type_bound_lists(
+ int id: @impl_trait_type_repr ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+index_exprs(
+ unique int id: @index_expr
+);
+
+#keyset[id, index]
+index_expr_attrs(
+ int id: @index_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+index_expr_bases(
+ int id: @index_expr ref,
+ int base: @expr ref
+);
+
+#keyset[id]
+index_expr_indices(
+ int id: @index_expr ref,
+ int index: @expr ref
+);
+
+infer_type_reprs(
+ unique int id: @infer_type_repr
+);
+
+@item =
+ @const
+| @enum
+| @extern_block
+| @extern_crate
+| @function
+| @impl
+| @macro_call
+| @macro_def
+| @macro_rules
+| @module
+| @static
+| @struct
+| @trait
+| @trait_alias
+| @type_alias
+| @union
+| @use
+;
+
+@labelable_expr =
+ @block_expr
+| @looping_expr
+;
+
+#keyset[id]
+labelable_expr_labels(
+ int id: @labelable_expr ref,
+ int label: @label ref
+);
+
+let_exprs(
+ unique int id: @let_expr
+);
+
+#keyset[id, index]
+let_expr_attrs(
+ int id: @let_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+let_expr_scrutinees(
+ int id: @let_expr ref,
+ int scrutinee: @expr ref
+);
+
+#keyset[id]
+let_expr_pats(
+ int id: @let_expr ref,
+ int pat: @pat ref
+);
+
+let_stmts(
+ unique int id: @let_stmt
+);
+
+#keyset[id, index]
+let_stmt_attrs(
+ int id: @let_stmt ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+let_stmt_initializers(
+ int id: @let_stmt ref,
+ int initializer: @expr ref
+);
+
+#keyset[id]
+let_stmt_let_elses(
+ int id: @let_stmt ref,
+ int let_else: @let_else ref
+);
+
+#keyset[id]
+let_stmt_pats(
+ int id: @let_stmt ref,
+ int pat: @pat ref
+);
+
+#keyset[id]
+let_stmt_type_reprs(
+ int id: @let_stmt ref,
+ int type_repr: @type_repr ref
+);
+
+lifetimes(
+ unique int id: @lifetime
+);
+
+#keyset[id]
+lifetime_texts(
+ int id: @lifetime ref,
+ string text: string ref
+);
+
+lifetime_args(
+ unique int id: @lifetime_arg
+);
+
+#keyset[id]
+lifetime_arg_lifetimes(
+ int id: @lifetime_arg ref,
+ int lifetime: @lifetime ref
+);
+
+lifetime_params(
+ unique int id: @lifetime_param
+);
+
+#keyset[id, index]
+lifetime_param_attrs(
+ int id: @lifetime_param ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+lifetime_param_lifetimes(
+ int id: @lifetime_param ref,
+ int lifetime: @lifetime ref
+);
+
+#keyset[id]
+lifetime_param_type_bound_lists(
+ int id: @lifetime_param ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+literal_exprs(
+ unique int id: @literal_expr
+);
+
+#keyset[id, index]
+literal_expr_attrs(
+ int id: @literal_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+literal_expr_text_values(
+ int id: @literal_expr ref,
+ string text_value: string ref
+);
+
+literal_pats(
+ unique int id: @literal_pat
+);
+
+#keyset[id]
+literal_pat_literals(
+ int id: @literal_pat ref,
+ int literal: @literal_expr ref
+);
+
+macro_exprs(
+ unique int id: @macro_expr
+);
+
+#keyset[id]
+macro_expr_macro_calls(
+ int id: @macro_expr ref,
+ int macro_call: @macro_call ref
+);
+
+macro_pats(
+ unique int id: @macro_pat
+);
+
+#keyset[id]
+macro_pat_macro_calls(
+ int id: @macro_pat ref,
+ int macro_call: @macro_call ref
+);
+
+macro_type_reprs(
+ unique int id: @macro_type_repr
+);
+
+#keyset[id]
+macro_type_repr_macro_calls(
+ int id: @macro_type_repr ref,
+ int macro_call: @macro_call ref
+);
+
+match_exprs(
+ unique int id: @match_expr
+);
+
+#keyset[id, index]
+match_expr_attrs(
+ int id: @match_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+match_expr_scrutinees(
+ int id: @match_expr ref,
+ int scrutinee: @expr ref
+);
+
+#keyset[id]
+match_expr_match_arm_lists(
+ int id: @match_expr ref,
+ int match_arm_list: @match_arm_list ref
+);
+
+name_refs(
+ unique int id: @name_ref
+);
+
+#keyset[id]
+name_ref_texts(
+ int id: @name_ref ref,
+ string text: string ref
+);
+
+never_type_reprs(
+ unique int id: @never_type_repr
+);
+
+offset_of_exprs(
+ unique int id: @offset_of_expr
+);
+
+#keyset[id, index]
+offset_of_expr_attrs(
+ int id: @offset_of_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+offset_of_expr_fields(
+ int id: @offset_of_expr ref,
+ int index: int ref,
+ int field: @name_ref ref
+);
+
+#keyset[id]
+offset_of_expr_type_reprs(
+ int id: @offset_of_expr ref,
+ int type_repr: @type_repr ref
+);
+
+or_pats(
+ unique int id: @or_pat
+);
+
+#keyset[id, index]
+or_pat_pats(
+ int id: @or_pat ref,
+ int index: int ref,
+ int pat: @pat ref
+);
+
+params(
+ unique int id: @param
+);
+
+#keyset[id]
+param_pats(
+ int id: @param ref,
+ int pat: @pat ref
+);
+
+paren_exprs(
+ unique int id: @paren_expr
+);
+
+#keyset[id, index]
+paren_expr_attrs(
+ int id: @paren_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+paren_expr_exprs(
+ int id: @paren_expr ref,
+ int expr: @expr ref
+);
+
+paren_pats(
+ unique int id: @paren_pat
+);
+
+#keyset[id]
+paren_pat_pats(
+ int id: @paren_pat ref,
+ int pat: @pat ref
+);
+
+paren_type_reprs(
+ unique int id: @paren_type_repr
+);
+
+#keyset[id]
+paren_type_repr_type_reprs(
+ int id: @paren_type_repr ref,
+ int type_repr: @type_repr ref
+);
+
+@path_ast_node =
+ @path_expr
+| @path_pat
+| @struct_expr
+| @struct_pat
+| @tuple_struct_pat
+;
+
+#keyset[id]
+path_ast_node_paths(
+ int id: @path_ast_node ref,
+ int path: @path ref
+);
+
+@path_expr_base =
+ @path_expr
+;
+
+path_type_reprs(
+ unique int id: @path_type_repr
+);
+
+#keyset[id]
+path_type_repr_paths(
+ int id: @path_type_repr ref,
+ int path: @path ref
+);
+
+prefix_exprs(
+ unique int id: @prefix_expr
+);
+
+#keyset[id, index]
+prefix_expr_attrs(
+ int id: @prefix_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+prefix_expr_exprs(
+ int id: @prefix_expr ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+prefix_expr_operator_names(
+ int id: @prefix_expr ref,
+ string operator_name: string ref
+);
+
+ptr_type_reprs(
+ unique int id: @ptr_type_repr
+);
+
+#keyset[id]
+ptr_type_repr_is_const(
+ int id: @ptr_type_repr ref
+);
+
+#keyset[id]
+ptr_type_repr_is_mut(
+ int id: @ptr_type_repr ref
+);
+
+#keyset[id]
+ptr_type_repr_type_reprs(
+ int id: @ptr_type_repr ref,
+ int type_repr: @type_repr ref
+);
+
+range_exprs(
+ unique int id: @range_expr
+);
+
+#keyset[id, index]
+range_expr_attrs(
+ int id: @range_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+range_expr_ends(
+ int id: @range_expr ref,
+ int end: @expr ref
+);
+
+#keyset[id]
+range_expr_operator_names(
+ int id: @range_expr ref,
+ string operator_name: string ref
+);
+
+#keyset[id]
+range_expr_starts(
+ int id: @range_expr ref,
+ int start: @expr ref
+);
+
+range_pats(
+ unique int id: @range_pat
+);
+
+#keyset[id]
+range_pat_ends(
+ int id: @range_pat ref,
+ int end: @pat ref
+);
+
+#keyset[id]
+range_pat_operator_names(
+ int id: @range_pat ref,
+ string operator_name: string ref
+);
+
+#keyset[id]
+range_pat_starts(
+ int id: @range_pat ref,
+ int start: @pat ref
+);
+
+ref_exprs(
+ unique int id: @ref_expr
+);
+
+#keyset[id, index]
+ref_expr_attrs(
+ int id: @ref_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+ref_expr_exprs(
+ int id: @ref_expr ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+ref_expr_is_const(
+ int id: @ref_expr ref
+);
+
+#keyset[id]
+ref_expr_is_mut(
+ int id: @ref_expr ref
+);
+
+#keyset[id]
+ref_expr_is_raw(
+ int id: @ref_expr ref
+);
+
+ref_pats(
+ unique int id: @ref_pat
+);
+
+#keyset[id]
+ref_pat_is_mut(
+ int id: @ref_pat ref
+);
+
+#keyset[id]
+ref_pat_pats(
+ int id: @ref_pat ref,
+ int pat: @pat ref
+);
+
+ref_type_reprs(
+ unique int id: @ref_type_repr
+);
+
+#keyset[id]
+ref_type_repr_is_mut(
+ int id: @ref_type_repr ref
+);
+
+#keyset[id]
+ref_type_repr_lifetimes(
+ int id: @ref_type_repr ref,
+ int lifetime: @lifetime ref
+);
+
+#keyset[id]
+ref_type_repr_type_reprs(
+ int id: @ref_type_repr ref,
+ int type_repr: @type_repr ref
+);
+
+rest_pats(
+ unique int id: @rest_pat
+);
+
+#keyset[id, index]
+rest_pat_attrs(
+ int id: @rest_pat ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+return_exprs(
+ unique int id: @return_expr
+);
+
+#keyset[id, index]
+return_expr_attrs(
+ int id: @return_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+return_expr_exprs(
+ int id: @return_expr ref,
+ int expr: @expr ref
+);
+
+self_params(
+ unique int id: @self_param
+);
+
+#keyset[id]
+self_param_is_ref(
+ int id: @self_param ref
+);
+
+#keyset[id]
+self_param_is_mut(
+ int id: @self_param ref
+);
+
+#keyset[id]
+self_param_lifetimes(
+ int id: @self_param ref,
+ int lifetime: @lifetime ref
+);
+
+#keyset[id]
+self_param_names(
+ int id: @self_param ref,
+ int name: @name ref
+);
+
+slice_pats(
+ unique int id: @slice_pat
+);
+
+#keyset[id, index]
+slice_pat_pats(
+ int id: @slice_pat ref,
+ int index: int ref,
+ int pat: @pat ref
+);
+
+slice_type_reprs(
+ unique int id: @slice_type_repr
+);
+
+#keyset[id]
+slice_type_repr_type_reprs(
+ int id: @slice_type_repr ref,
+ int type_repr: @type_repr ref
+);
+
+struct_field_lists(
+ unique int id: @struct_field_list
+);
+
+#keyset[id, index]
+struct_field_list_fields(
+ int id: @struct_field_list ref,
+ int index: int ref,
+ int field: @struct_field ref
+);
+
+try_exprs(
+ unique int id: @try_expr
+);
+
+#keyset[id, index]
+try_expr_attrs(
+ int id: @try_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+try_expr_exprs(
+ int id: @try_expr ref,
+ int expr: @expr ref
+);
+
+tuple_exprs(
+ unique int id: @tuple_expr
+);
+
+#keyset[id, index]
+tuple_expr_attrs(
+ int id: @tuple_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+tuple_expr_fields(
+ int id: @tuple_expr ref,
+ int index: int ref,
+ int field: @expr ref
+);
+
+tuple_field_lists(
+ unique int id: @tuple_field_list
+);
+
+#keyset[id, index]
+tuple_field_list_fields(
+ int id: @tuple_field_list ref,
+ int index: int ref,
+ int field: @tuple_field ref
+);
+
+tuple_pats(
+ unique int id: @tuple_pat
+);
+
+#keyset[id, index]
+tuple_pat_fields(
+ int id: @tuple_pat ref,
+ int index: int ref,
+ int field: @pat ref
+);
+
+tuple_type_reprs(
+ unique int id: @tuple_type_repr
+);
+
+#keyset[id, index]
+tuple_type_repr_fields(
+ int id: @tuple_type_repr ref,
+ int index: int ref,
+ int field: @type_repr ref
+);
+
+type_args(
+ unique int id: @type_arg
+);
+
+#keyset[id]
+type_arg_type_reprs(
+ int id: @type_arg ref,
+ int type_repr: @type_repr ref
+);
+
+type_params(
+ unique int id: @type_param
+);
+
+#keyset[id, index]
+type_param_attrs(
+ int id: @type_param ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+type_param_default_types(
+ int id: @type_param ref,
+ int default_type: @type_repr ref
+);
+
+#keyset[id]
+type_param_names(
+ int id: @type_param ref,
+ int name: @name ref
+);
+
+#keyset[id]
+type_param_type_bound_lists(
+ int id: @type_param ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+underscore_exprs(
+ unique int id: @underscore_expr
+);
+
+#keyset[id, index]
+underscore_expr_attrs(
+ int id: @underscore_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+variants(
+ unique int id: @variant
+);
+
+#keyset[id, index]
+variant_attrs(
+ int id: @variant ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+variant_discriminants(
+ int id: @variant ref,
+ int discriminant: @expr ref
+);
+
+#keyset[id]
+variant_field_lists(
+ int id: @variant ref,
+ int field_list: @field_list ref
+);
+
+#keyset[id]
+variant_names(
+ int id: @variant ref,
+ int name: @name ref
+);
+
+#keyset[id]
+variant_visibilities(
+ int id: @variant ref,
+ int visibility: @visibility ref
+);
+
+wildcard_pats(
+ unique int id: @wildcard_pat
+);
+
+yeet_exprs(
+ unique int id: @yeet_expr
+);
+
+#keyset[id, index]
+yeet_expr_attrs(
+ int id: @yeet_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+yeet_expr_exprs(
+ int id: @yeet_expr ref,
+ int expr: @expr ref
+);
+
+yield_exprs(
+ unique int id: @yield_expr
+);
+
+#keyset[id, index]
+yield_expr_attrs(
+ int id: @yield_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+yield_expr_exprs(
+ int id: @yield_expr ref,
+ int expr: @expr ref
+);
+
+block_exprs(
+ unique int id: @block_expr
+);
+
+#keyset[id, index]
+block_expr_attrs(
+ int id: @block_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+block_expr_is_async(
+ int id: @block_expr ref
+);
+
+#keyset[id]
+block_expr_is_const(
+ int id: @block_expr ref
+);
+
+#keyset[id]
+block_expr_is_gen(
+ int id: @block_expr ref
+);
+
+#keyset[id]
+block_expr_is_move(
+ int id: @block_expr ref
+);
+
+#keyset[id]
+block_expr_is_try(
+ int id: @block_expr ref
+);
+
+#keyset[id]
+block_expr_is_unsafe(
+ int id: @block_expr ref
+);
+
+#keyset[id]
+block_expr_stmt_lists(
+ int id: @block_expr ref,
+ int stmt_list: @stmt_list ref
+);
+
+call_exprs(
+ unique int id: @call_expr
+);
+
+#keyset[id]
+call_expr_functions(
+ int id: @call_expr ref,
+ int function: @expr ref
+);
+
+consts(
+ unique int id: @const
+);
+
+#keyset[id, index]
+const_attrs(
+ int id: @const ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+const_bodies(
+ int id: @const ref,
+ int body: @expr ref
+);
+
+#keyset[id]
+const_is_const(
+ int id: @const ref
+);
+
+#keyset[id]
+const_is_default(
+ int id: @const ref
+);
+
+#keyset[id]
+const_names(
+ int id: @const ref,
+ int name: @name ref
+);
+
+#keyset[id]
+const_type_reprs(
+ int id: @const ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+const_visibilities(
+ int id: @const ref,
+ int visibility: @visibility ref
+);
+
+enums(
+ unique int id: @enum
+);
+
+#keyset[id, index]
+enum_attrs(
+ int id: @enum ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+enum_generic_param_lists(
+ int id: @enum ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+enum_names(
+ int id: @enum ref,
+ int name: @name ref
+);
+
+#keyset[id]
+enum_variant_lists(
+ int id: @enum ref,
+ int variant_list: @variant_list ref
+);
+
+#keyset[id]
+enum_visibilities(
+ int id: @enum ref,
+ int visibility: @visibility ref
+);
+
+#keyset[id]
+enum_where_clauses(
+ int id: @enum ref,
+ int where_clause: @where_clause ref
+);
+
+extern_blocks(
+ unique int id: @extern_block
+);
+
+#keyset[id]
+extern_block_abis(
+ int id: @extern_block ref,
+ int abi: @abi ref
+);
+
+#keyset[id, index]
+extern_block_attrs(
+ int id: @extern_block ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+extern_block_extern_item_lists(
+ int id: @extern_block ref,
+ int extern_item_list: @extern_item_list ref
+);
+
+#keyset[id]
+extern_block_is_unsafe(
+ int id: @extern_block ref
+);
+
+extern_crates(
+ unique int id: @extern_crate
+);
+
+#keyset[id, index]
+extern_crate_attrs(
+ int id: @extern_crate ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+extern_crate_identifiers(
+ int id: @extern_crate ref,
+ int identifier: @name_ref ref
+);
+
+#keyset[id]
+extern_crate_renames(
+ int id: @extern_crate ref,
+ int rename: @rename ref
+);
+
+#keyset[id]
+extern_crate_visibilities(
+ int id: @extern_crate ref,
+ int visibility: @visibility ref
+);
+
+functions(
+ unique int id: @function
+);
+
+#keyset[id]
+function_abis(
+ int id: @function ref,
+ int abi: @abi ref
+);
+
+#keyset[id]
+function_bodies(
+ int id: @function ref,
+ int body: @block_expr ref
+);
+
+#keyset[id]
+function_generic_param_lists(
+ int id: @function ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+function_is_async(
+ int id: @function ref
+);
+
+#keyset[id]
+function_is_const(
+ int id: @function ref
+);
+
+#keyset[id]
+function_is_default(
+ int id: @function ref
+);
+
+#keyset[id]
+function_is_gen(
+ int id: @function ref
+);
+
+#keyset[id]
+function_is_unsafe(
+ int id: @function ref
+);
+
+#keyset[id]
+function_names(
+ int id: @function ref,
+ int name: @name ref
+);
+
+#keyset[id]
+function_ret_types(
+ int id: @function ref,
+ int ret_type: @ret_type_repr ref
+);
+
+#keyset[id]
+function_visibilities(
+ int id: @function ref,
+ int visibility: @visibility ref
+);
+
+#keyset[id]
+function_where_clauses(
+ int id: @function ref,
+ int where_clause: @where_clause ref
+);
+
+impls(
+ unique int id: @impl
+);
+
+#keyset[id]
+impl_assoc_item_lists(
+ int id: @impl ref,
+ int assoc_item_list: @assoc_item_list ref
+);
+
+#keyset[id, index]
+impl_attrs(
+ int id: @impl ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+impl_generic_param_lists(
+ int id: @impl ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+impl_is_const(
+ int id: @impl ref
+);
+
+#keyset[id]
+impl_is_default(
+ int id: @impl ref
+);
+
+#keyset[id]
+impl_is_unsafe(
+ int id: @impl ref
+);
+
+#keyset[id]
+impl_self_ties(
+ int id: @impl ref,
+ int self_ty: @type_repr ref
+);
+
+#keyset[id]
+impl_traits(
+ int id: @impl ref,
+ int trait: @type_repr ref
+);
+
+#keyset[id]
+impl_visibilities(
+ int id: @impl ref,
+ int visibility: @visibility ref
+);
+
+#keyset[id]
+impl_where_clauses(
+ int id: @impl ref,
+ int where_clause: @where_clause ref
+);
+
+@looping_expr =
+ @for_expr
+| @loop_expr
+| @while_expr
+;
+
+#keyset[id]
+looping_expr_loop_bodies(
+ int id: @looping_expr ref,
+ int loop_body: @block_expr ref
+);
+
+macro_calls(
+ unique int id: @macro_call
+);
+
+#keyset[id, index]
+macro_call_attrs(
+ int id: @macro_call ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+macro_call_paths(
+ int id: @macro_call ref,
+ int path: @path ref
+);
+
+#keyset[id]
+macro_call_token_trees(
+ int id: @macro_call ref,
+ int token_tree: @token_tree ref
+);
+
+#keyset[id]
+macro_call_expandeds(
+ int id: @macro_call ref,
+ int expanded: @ast_node ref
+);
+
+macro_defs(
+ unique int id: @macro_def
+);
+
+#keyset[id]
+macro_def_args(
+ int id: @macro_def ref,
+ int args: @token_tree ref
+);
+
+#keyset[id, index]
+macro_def_attrs(
+ int id: @macro_def ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+macro_def_bodies(
+ int id: @macro_def ref,
+ int body: @token_tree ref
+);
+
+#keyset[id]
+macro_def_names(
+ int id: @macro_def ref,
+ int name: @name ref
+);
+
+#keyset[id]
+macro_def_visibilities(
+ int id: @macro_def ref,
+ int visibility: @visibility ref
+);
+
+macro_rules(
+ unique int id: @macro_rules
+);
+
+#keyset[id, index]
+macro_rules_attrs(
+ int id: @macro_rules ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+macro_rules_names(
+ int id: @macro_rules ref,
+ int name: @name ref
+);
+
+#keyset[id]
+macro_rules_token_trees(
+ int id: @macro_rules ref,
+ int token_tree: @token_tree ref
+);
+
+#keyset[id]
+macro_rules_visibilities(
+ int id: @macro_rules ref,
+ int visibility: @visibility ref
+);
+
+method_call_exprs(
+ unique int id: @method_call_expr
+);
+
+#keyset[id]
+method_call_expr_generic_arg_lists(
+ int id: @method_call_expr ref,
+ int generic_arg_list: @generic_arg_list ref
+);
+
+#keyset[id]
+method_call_expr_identifiers(
+ int id: @method_call_expr ref,
+ int identifier: @name_ref ref
+);
+
+#keyset[id]
+method_call_expr_receivers(
+ int id: @method_call_expr ref,
+ int receiver: @expr ref
+);
+
+modules(
+ unique int id: @module
+);
+
+#keyset[id, index]
+module_attrs(
+ int id: @module ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+module_item_lists(
+ int id: @module ref,
+ int item_list: @item_list ref
+);
+
+#keyset[id]
+module_names(
+ int id: @module ref,
+ int name: @name ref
+);
+
+#keyset[id]
+module_visibilities(
+ int id: @module ref,
+ int visibility: @visibility ref
+);
+
+path_exprs(
+ unique int id: @path_expr
+);
+
+#keyset[id, index]
+path_expr_attrs(
+ int id: @path_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+path_pats(
+ unique int id: @path_pat
+);
+
+statics(
+ unique int id: @static
+);
+
+#keyset[id, index]
+static_attrs(
+ int id: @static ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+static_bodies(
+ int id: @static ref,
+ int body: @expr ref
+);
+
+#keyset[id]
+static_is_mut(
+ int id: @static ref
+);
+
+#keyset[id]
+static_is_static(
+ int id: @static ref
+);
+
+#keyset[id]
+static_is_unsafe(
+ int id: @static ref
+);
+
+#keyset[id]
+static_names(
+ int id: @static ref,
+ int name: @name ref
+);
+
+#keyset[id]
+static_type_reprs(
+ int id: @static ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+static_visibilities(
+ int id: @static ref,
+ int visibility: @visibility ref
+);
+
+structs(
+ unique int id: @struct
+);
+
+#keyset[id, index]
+struct_attrs(
+ int id: @struct ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+struct_field_lists_(
+ int id: @struct ref,
+ int field_list: @field_list ref
+);
+
+#keyset[id]
+struct_generic_param_lists(
+ int id: @struct ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+struct_names(
+ int id: @struct ref,
+ int name: @name ref
+);
+
+#keyset[id]
+struct_visibilities(
+ int id: @struct ref,
+ int visibility: @visibility ref
+);
+
+#keyset[id]
+struct_where_clauses(
+ int id: @struct ref,
+ int where_clause: @where_clause ref
+);
+
+struct_exprs(
+ unique int id: @struct_expr
+);
+
+#keyset[id]
+struct_expr_struct_expr_field_lists(
+ int id: @struct_expr ref,
+ int struct_expr_field_list: @struct_expr_field_list ref
+);
+
+struct_pats(
+ unique int id: @struct_pat
+);
+
+#keyset[id]
+struct_pat_struct_pat_field_lists(
+ int id: @struct_pat ref,
+ int struct_pat_field_list: @struct_pat_field_list ref
+);
+
+traits(
+ unique int id: @trait
+);
+
+#keyset[id]
+trait_assoc_item_lists(
+ int id: @trait ref,
+ int assoc_item_list: @assoc_item_list ref
+);
+
+#keyset[id, index]
+trait_attrs(
+ int id: @trait ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+trait_generic_param_lists(
+ int id: @trait ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+trait_is_auto(
+ int id: @trait ref
+);
+
+#keyset[id]
+trait_is_unsafe(
+ int id: @trait ref
+);
+
+#keyset[id]
+trait_names(
+ int id: @trait ref,
+ int name: @name ref
+);
+
+#keyset[id]
+trait_type_bound_lists(
+ int id: @trait ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+#keyset[id]
+trait_visibilities(
+ int id: @trait ref,
+ int visibility: @visibility ref
+);
+
+#keyset[id]
+trait_where_clauses(
+ int id: @trait ref,
+ int where_clause: @where_clause ref
+);
+
+trait_aliases(
+ unique int id: @trait_alias
+);
+
+#keyset[id, index]
+trait_alias_attrs(
+ int id: @trait_alias ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+trait_alias_generic_param_lists(
+ int id: @trait_alias ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+trait_alias_names(
+ int id: @trait_alias ref,
+ int name: @name ref
+);
+
+#keyset[id]
+trait_alias_type_bound_lists(
+ int id: @trait_alias ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+#keyset[id]
+trait_alias_visibilities(
+ int id: @trait_alias ref,
+ int visibility: @visibility ref
+);
+
+#keyset[id]
+trait_alias_where_clauses(
+ int id: @trait_alias ref,
+ int where_clause: @where_clause ref
+);
+
+tuple_struct_pats(
+ unique int id: @tuple_struct_pat
+);
+
+#keyset[id, index]
+tuple_struct_pat_fields(
+ int id: @tuple_struct_pat ref,
+ int index: int ref,
+ int field: @pat ref
+);
+
+type_aliases(
+ unique int id: @type_alias
+);
+
+#keyset[id, index]
+type_alias_attrs(
+ int id: @type_alias ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+type_alias_generic_param_lists(
+ int id: @type_alias ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+type_alias_is_default(
+ int id: @type_alias ref
+);
+
+#keyset[id]
+type_alias_names(
+ int id: @type_alias ref,
+ int name: @name ref
+);
+
+#keyset[id]
+type_alias_type_reprs(
+ int id: @type_alias ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+type_alias_type_bound_lists(
+ int id: @type_alias ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+#keyset[id]
+type_alias_visibilities(
+ int id: @type_alias ref,
+ int visibility: @visibility ref
+);
+
+#keyset[id]
+type_alias_where_clauses(
+ int id: @type_alias ref,
+ int where_clause: @where_clause ref
+);
+
+unions(
+ unique int id: @union
+);
+
+#keyset[id, index]
+union_attrs(
+ int id: @union ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+union_generic_param_lists(
+ int id: @union ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+union_names(
+ int id: @union ref,
+ int name: @name ref
+);
+
+#keyset[id]
+union_struct_field_lists(
+ int id: @union ref,
+ int struct_field_list: @struct_field_list ref
+);
+
+#keyset[id]
+union_visibilities(
+ int id: @union ref,
+ int visibility: @visibility ref
+);
+
+#keyset[id]
+union_where_clauses(
+ int id: @union ref,
+ int where_clause: @where_clause ref
+);
+
+uses(
+ unique int id: @use
+);
+
+#keyset[id, index]
+use_attrs(
+ int id: @use ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+use_use_trees(
+ int id: @use ref,
+ int use_tree: @use_tree ref
+);
+
+#keyset[id]
+use_visibilities(
+ int id: @use ref,
+ int visibility: @visibility ref
+);
+
+for_exprs(
+ unique int id: @for_expr
+);
+
+#keyset[id, index]
+for_expr_attrs(
+ int id: @for_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+for_expr_iterables(
+ int id: @for_expr ref,
+ int iterable: @expr ref
+);
+
+#keyset[id]
+for_expr_pats(
+ int id: @for_expr ref,
+ int pat: @pat ref
+);
+
+loop_exprs(
+ unique int id: @loop_expr
+);
+
+#keyset[id, index]
+loop_expr_attrs(
+ int id: @loop_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+while_exprs(
+ unique int id: @while_expr
+);
+
+#keyset[id, index]
+while_expr_attrs(
+ int id: @while_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+while_expr_conditions(
+ int id: @while_expr ref,
+ int condition: @expr ref
+);
diff --git a/rust/downgrades/qlpack.yml b/rust/downgrades/qlpack.yml
new file mode 100644
index 000000000000..5bfaa9be4e50
--- /dev/null
+++ b/rust/downgrades/qlpack.yml
@@ -0,0 +1,5 @@
+name: codeql/rust-downgrades
+groups: rust
+downgrades: .
+library: true
+warnOnImplicitThis: true
diff --git a/rust/ql/lib/upgrades/initial/rust.dbscheme b/rust/ql/lib/upgrades/initial/rust.dbscheme
new file mode 100644
index 000000000000..256e80c2dcea
--- /dev/null
+++ b/rust/ql/lib/upgrades/initial/rust.dbscheme
@@ -0,0 +1,3601 @@
+// generated by codegen, do not edit
+
+// from ../shared/tree-sitter-extractor/src/generator/prefix.dbscheme
+/*- Files and folders -*/
+
+/**
+ * The location of an element.
+ * The location spans column `startcolumn` of line `startline` to
+ * column `endcolumn` of line `endline` in file `file`.
+ * For more information, see
+ * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
+ */
+locations_default(
+ unique int id: @location_default,
+ int file: @file ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref
+);
+
+files(
+ unique int id: @file,
+ string name: string ref
+);
+
+folders(
+ unique int id: @folder,
+ string name: string ref
+);
+
+@container = @file | @folder
+
+containerparent(
+ int parent: @container ref,
+ unique int child: @container ref
+);
+
+/*- Empty location -*/
+
+empty_location(
+ int location: @location_default ref
+);
+
+/*- Source location prefix -*/
+
+/**
+ * The source location of the snapshot.
+ */
+sourceLocationPrefix(string prefix : string ref);
+
+/*- Diagnostic messages -*/
+
+diagnostics(
+ unique int id: @diagnostic,
+ int severity: int ref,
+ string error_tag: string ref,
+ string error_message: string ref,
+ string full_error_message: string ref,
+ int location: @location_default ref
+);
+
+/*- Diagnostic messages: severity -*/
+
+case @diagnostic.severity of
+ 10 = @diagnostic_debug
+| 20 = @diagnostic_info
+| 30 = @diagnostic_warning
+| 40 = @diagnostic_error
+;
+
+/*- YAML -*/
+
+#keyset[parent, idx]
+yaml (unique int id: @yaml_node,
+ int kind: int ref,
+ int parent: @yaml_node_parent ref,
+ int idx: int ref,
+ string tag: string ref,
+ string tostring: string ref);
+
+case @yaml_node.kind of
+ 0 = @yaml_scalar_node
+| 1 = @yaml_mapping_node
+| 2 = @yaml_sequence_node
+| 3 = @yaml_alias_node
+;
+
+@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node;
+
+@yaml_node_parent = @yaml_collection_node | @file;
+
+yaml_anchors (unique int node: @yaml_node ref,
+ string anchor: string ref);
+
+yaml_aliases (unique int alias: @yaml_alias_node ref,
+ string target: string ref);
+
+yaml_scalars (unique int scalar: @yaml_scalar_node ref,
+ int style: int ref,
+ string value: string ref);
+
+yaml_errors (unique int id: @yaml_error,
+ string message: string ref);
+
+yaml_locations(unique int locatable: @yaml_locatable ref,
+ int location: @location_default ref);
+
+@yaml_locatable = @yaml_node | @yaml_error;
+
+
+// from prefix.dbscheme
+#keyset[id]
+locatable_locations(
+ int id: @locatable ref,
+ int location: @location_default ref
+);
+
+
+// from schema
+
+@element =
+ @extractor_step
+| @locatable
+| @named_crate
+| @unextracted
+;
+
+extractor_steps(
+ unique int id: @extractor_step,
+ string action: string ref,
+ int duration_ms: int ref
+);
+
+#keyset[id]
+extractor_step_files(
+ int id: @extractor_step ref,
+ int file: @file ref
+);
+
+@locatable =
+ @ast_node
+| @crate
+;
+
+named_crates(
+ unique int id: @named_crate,
+ string name: string ref,
+ int crate: @crate ref
+);
+
+@unextracted =
+ @missing
+| @unimplemented
+;
+
+@ast_node =
+ @abi
+| @addressable
+| @arg_list
+| @asm_dir_spec
+| @asm_operand
+| @asm_operand_expr
+| @asm_option
+| @asm_piece
+| @asm_reg_spec
+| @assoc_item
+| @assoc_item_list
+| @attr
+| @callable
+| @closure_binder
+| @expr
+| @extern_item
+| @extern_item_list
+| @field_list
+| @format_args_arg
+| @generic_arg
+| @generic_arg_list
+| @generic_param
+| @generic_param_list
+| @item_list
+| @label
+| @let_else
+| @macro_items
+| @macro_stmts
+| @match_arm
+| @match_arm_list
+| @match_guard
+| @meta
+| @name
+| @param_base
+| @param_list
+| @parenthesized_arg_list
+| @pat
+| @path
+| @path_segment
+| @rename
+| @resolvable
+| @ret_type_repr
+| @return_type_syntax
+| @source_file
+| @stmt
+| @stmt_list
+| @struct_expr_field
+| @struct_expr_field_list
+| @struct_field
+| @struct_pat_field
+| @struct_pat_field_list
+| @token
+| @token_tree
+| @tuple_field
+| @type_bound
+| @type_bound_list
+| @type_repr
+| @use_bound_generic_arg
+| @use_bound_generic_args
+| @use_tree
+| @use_tree_list
+| @variant_def
+| @variant_list
+| @visibility
+| @where_clause
+| @where_pred
+;
+
+crates(
+ unique int id: @crate
+);
+
+#keyset[id]
+crate_names(
+ int id: @crate ref,
+ string name: string ref
+);
+
+#keyset[id]
+crate_versions(
+ int id: @crate ref,
+ string version: string ref
+);
+
+#keyset[id]
+crate_modules(
+ int id: @crate ref,
+ int module: @module ref
+);
+
+#keyset[id, index]
+crate_cfg_options(
+ int id: @crate ref,
+ int index: int ref,
+ string cfg_option: string ref
+);
+
+#keyset[id, index]
+crate_named_dependencies(
+ int id: @crate ref,
+ int index: int ref,
+ int named_dependency: @named_crate ref
+);
+
+missings(
+ unique int id: @missing
+);
+
+unimplementeds(
+ unique int id: @unimplemented
+);
+
+abis(
+ unique int id: @abi
+);
+
+#keyset[id]
+abi_abi_strings(
+ int id: @abi ref,
+ string abi_string: string ref
+);
+
+@addressable =
+ @item
+| @variant
+;
+
+#keyset[id]
+addressable_extended_canonical_paths(
+ int id: @addressable ref,
+ string extended_canonical_path: string ref
+);
+
+#keyset[id]
+addressable_crate_origins(
+ int id: @addressable ref,
+ string crate_origin: string ref
+);
+
+arg_lists(
+ unique int id: @arg_list
+);
+
+#keyset[id, index]
+arg_list_args(
+ int id: @arg_list ref,
+ int index: int ref,
+ int arg: @expr ref
+);
+
+asm_dir_specs(
+ unique int id: @asm_dir_spec
+);
+
+@asm_operand =
+ @asm_const
+| @asm_label
+| @asm_reg_operand
+| @asm_sym
+;
+
+asm_operand_exprs(
+ unique int id: @asm_operand_expr
+);
+
+#keyset[id]
+asm_operand_expr_in_exprs(
+ int id: @asm_operand_expr ref,
+ int in_expr: @expr ref
+);
+
+#keyset[id]
+asm_operand_expr_out_exprs(
+ int id: @asm_operand_expr ref,
+ int out_expr: @expr ref
+);
+
+asm_options(
+ unique int id: @asm_option
+);
+
+#keyset[id]
+asm_option_is_raw(
+ int id: @asm_option ref
+);
+
+@asm_piece =
+ @asm_clobber_abi
+| @asm_operand_named
+| @asm_options_list
+;
+
+asm_reg_specs(
+ unique int id: @asm_reg_spec
+);
+
+#keyset[id]
+asm_reg_spec_identifiers(
+ int id: @asm_reg_spec ref,
+ int identifier: @name_ref ref
+);
+
+@assoc_item =
+ @const
+| @function
+| @macro_call
+| @type_alias
+;
+
+assoc_item_lists(
+ unique int id: @assoc_item_list
+);
+
+#keyset[id, index]
+assoc_item_list_assoc_items(
+ int id: @assoc_item_list ref,
+ int index: int ref,
+ int assoc_item: @assoc_item ref
+);
+
+#keyset[id, index]
+assoc_item_list_attrs(
+ int id: @assoc_item_list ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+attrs(
+ unique int id: @attr
+);
+
+#keyset[id]
+attr_meta(
+ int id: @attr ref,
+ int meta: @meta ref
+);
+
+@callable =
+ @closure_expr
+| @function
+;
+
+#keyset[id]
+callable_param_lists(
+ int id: @callable ref,
+ int param_list: @param_list ref
+);
+
+#keyset[id, index]
+callable_attrs(
+ int id: @callable ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+closure_binders(
+ unique int id: @closure_binder
+);
+
+#keyset[id]
+closure_binder_generic_param_lists(
+ int id: @closure_binder ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+@expr =
+ @array_expr_internal
+| @asm_expr
+| @await_expr
+| @become_expr
+| @binary_expr
+| @break_expr
+| @call_expr_base
+| @cast_expr
+| @closure_expr
+| @continue_expr
+| @field_expr
+| @format_args_expr
+| @if_expr
+| @index_expr
+| @labelable_expr
+| @let_expr
+| @literal_expr
+| @macro_expr
+| @match_expr
+| @offset_of_expr
+| @paren_expr
+| @path_expr_base
+| @prefix_expr
+| @range_expr
+| @ref_expr
+| @return_expr
+| @struct_expr
+| @try_expr
+| @tuple_expr
+| @underscore_expr
+| @yeet_expr
+| @yield_expr
+;
+
+@extern_item =
+ @function
+| @macro_call
+| @static
+| @type_alias
+;
+
+extern_item_lists(
+ unique int id: @extern_item_list
+);
+
+#keyset[id, index]
+extern_item_list_attrs(
+ int id: @extern_item_list ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+extern_item_list_extern_items(
+ int id: @extern_item_list ref,
+ int index: int ref,
+ int extern_item: @extern_item ref
+);
+
+@field_list =
+ @struct_field_list
+| @tuple_field_list
+;
+
+format_args_args(
+ unique int id: @format_args_arg
+);
+
+#keyset[id]
+format_args_arg_exprs(
+ int id: @format_args_arg ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+format_args_arg_names(
+ int id: @format_args_arg ref,
+ int name: @name ref
+);
+
+@generic_arg =
+ @assoc_type_arg
+| @const_arg
+| @lifetime_arg
+| @type_arg
+;
+
+generic_arg_lists(
+ unique int id: @generic_arg_list
+);
+
+#keyset[id, index]
+generic_arg_list_generic_args(
+ int id: @generic_arg_list ref,
+ int index: int ref,
+ int generic_arg: @generic_arg ref
+);
+
+@generic_param =
+ @const_param
+| @lifetime_param
+| @type_param
+;
+
+generic_param_lists(
+ unique int id: @generic_param_list
+);
+
+#keyset[id, index]
+generic_param_list_generic_params(
+ int id: @generic_param_list ref,
+ int index: int ref,
+ int generic_param: @generic_param ref
+);
+
+item_lists(
+ unique int id: @item_list
+);
+
+#keyset[id, index]
+item_list_attrs(
+ int id: @item_list ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+item_list_items(
+ int id: @item_list ref,
+ int index: int ref,
+ int item: @item ref
+);
+
+labels(
+ unique int id: @label
+);
+
+#keyset[id]
+label_lifetimes(
+ int id: @label ref,
+ int lifetime: @lifetime ref
+);
+
+let_elses(
+ unique int id: @let_else
+);
+
+#keyset[id]
+let_else_block_exprs(
+ int id: @let_else ref,
+ int block_expr: @block_expr ref
+);
+
+macro_items(
+ unique int id: @macro_items
+);
+
+#keyset[id, index]
+macro_items_items(
+ int id: @macro_items ref,
+ int index: int ref,
+ int item: @item ref
+);
+
+macro_stmts(
+ unique int id: @macro_stmts
+);
+
+#keyset[id]
+macro_stmts_exprs(
+ int id: @macro_stmts ref,
+ int expr: @expr ref
+);
+
+#keyset[id, index]
+macro_stmts_statements(
+ int id: @macro_stmts ref,
+ int index: int ref,
+ int statement: @stmt ref
+);
+
+match_arms(
+ unique int id: @match_arm
+);
+
+#keyset[id, index]
+match_arm_attrs(
+ int id: @match_arm ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+match_arm_exprs(
+ int id: @match_arm ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+match_arm_guards(
+ int id: @match_arm ref,
+ int guard: @match_guard ref
+);
+
+#keyset[id]
+match_arm_pats(
+ int id: @match_arm ref,
+ int pat: @pat ref
+);
+
+match_arm_lists(
+ unique int id: @match_arm_list
+);
+
+#keyset[id, index]
+match_arm_list_arms(
+ int id: @match_arm_list ref,
+ int index: int ref,
+ int arm: @match_arm ref
+);
+
+#keyset[id, index]
+match_arm_list_attrs(
+ int id: @match_arm_list ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+match_guards(
+ unique int id: @match_guard
+);
+
+#keyset[id]
+match_guard_conditions(
+ int id: @match_guard ref,
+ int condition: @expr ref
+);
+
+meta(
+ unique int id: @meta
+);
+
+#keyset[id]
+meta_exprs(
+ int id: @meta ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+meta_is_unsafe(
+ int id: @meta ref
+);
+
+#keyset[id]
+meta_paths(
+ int id: @meta ref,
+ int path: @path ref
+);
+
+#keyset[id]
+meta_token_trees(
+ int id: @meta ref,
+ int token_tree: @token_tree ref
+);
+
+names(
+ unique int id: @name
+);
+
+#keyset[id]
+name_texts(
+ int id: @name ref,
+ string text: string ref
+);
+
+@param_base =
+ @param
+| @self_param
+;
+
+#keyset[id, index]
+param_base_attrs(
+ int id: @param_base ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+param_base_type_reprs(
+ int id: @param_base ref,
+ int type_repr: @type_repr ref
+);
+
+param_lists(
+ unique int id: @param_list
+);
+
+#keyset[id, index]
+param_list_params(
+ int id: @param_list ref,
+ int index: int ref,
+ int param: @param ref
+);
+
+#keyset[id]
+param_list_self_params(
+ int id: @param_list ref,
+ int self_param: @self_param ref
+);
+
+parenthesized_arg_lists(
+ unique int id: @parenthesized_arg_list
+);
+
+#keyset[id, index]
+parenthesized_arg_list_type_args(
+ int id: @parenthesized_arg_list ref,
+ int index: int ref,
+ int type_arg: @type_arg ref
+);
+
+@pat =
+ @box_pat
+| @const_block_pat
+| @ident_pat
+| @literal_pat
+| @macro_pat
+| @or_pat
+| @paren_pat
+| @path_pat
+| @range_pat
+| @ref_pat
+| @rest_pat
+| @slice_pat
+| @struct_pat
+| @tuple_pat
+| @tuple_struct_pat
+| @wildcard_pat
+;
+
+paths(
+ unique int id: @path
+);
+
+#keyset[id]
+path_qualifiers(
+ int id: @path ref,
+ int qualifier: @path ref
+);
+
+#keyset[id]
+path_segments_(
+ int id: @path ref,
+ int segment: @path_segment ref
+);
+
+path_segments(
+ unique int id: @path_segment
+);
+
+#keyset[id]
+path_segment_generic_arg_lists(
+ int id: @path_segment ref,
+ int generic_arg_list: @generic_arg_list ref
+);
+
+#keyset[id]
+path_segment_identifiers(
+ int id: @path_segment ref,
+ int identifier: @name_ref ref
+);
+
+#keyset[id]
+path_segment_parenthesized_arg_lists(
+ int id: @path_segment ref,
+ int parenthesized_arg_list: @parenthesized_arg_list ref
+);
+
+#keyset[id]
+path_segment_ret_types(
+ int id: @path_segment ref,
+ int ret_type: @ret_type_repr ref
+);
+
+#keyset[id]
+path_segment_return_type_syntaxes(
+ int id: @path_segment ref,
+ int return_type_syntax: @return_type_syntax ref
+);
+
+#keyset[id]
+path_segment_type_reprs(
+ int id: @path_segment ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+path_segment_trait_type_reprs(
+ int id: @path_segment ref,
+ int trait_type_repr: @path_type_repr ref
+);
+
+renames(
+ unique int id: @rename
+);
+
+#keyset[id]
+rename_names(
+ int id: @rename ref,
+ int name: @name ref
+);
+
+@resolvable =
+ @method_call_expr
+| @path_ast_node
+;
+
+#keyset[id]
+resolvable_resolved_paths(
+ int id: @resolvable ref,
+ string resolved_path: string ref
+);
+
+#keyset[id]
+resolvable_resolved_crate_origins(
+ int id: @resolvable ref,
+ string resolved_crate_origin: string ref
+);
+
+ret_type_reprs(
+ unique int id: @ret_type_repr
+);
+
+#keyset[id]
+ret_type_repr_type_reprs(
+ int id: @ret_type_repr ref,
+ int type_repr: @type_repr ref
+);
+
+return_type_syntaxes(
+ unique int id: @return_type_syntax
+);
+
+source_files(
+ unique int id: @source_file
+);
+
+#keyset[id, index]
+source_file_attrs(
+ int id: @source_file ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+source_file_items(
+ int id: @source_file ref,
+ int index: int ref,
+ int item: @item ref
+);
+
+@stmt =
+ @expr_stmt
+| @item
+| @let_stmt
+;
+
+stmt_lists(
+ unique int id: @stmt_list
+);
+
+#keyset[id, index]
+stmt_list_attrs(
+ int id: @stmt_list ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+stmt_list_statements(
+ int id: @stmt_list ref,
+ int index: int ref,
+ int statement: @stmt ref
+);
+
+#keyset[id]
+stmt_list_tail_exprs(
+ int id: @stmt_list ref,
+ int tail_expr: @expr ref
+);
+
+struct_expr_fields(
+ unique int id: @struct_expr_field
+);
+
+#keyset[id, index]
+struct_expr_field_attrs(
+ int id: @struct_expr_field ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+struct_expr_field_exprs(
+ int id: @struct_expr_field ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+struct_expr_field_identifiers(
+ int id: @struct_expr_field ref,
+ int identifier: @name_ref ref
+);
+
+struct_expr_field_lists(
+ unique int id: @struct_expr_field_list
+);
+
+#keyset[id, index]
+struct_expr_field_list_attrs(
+ int id: @struct_expr_field_list ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+struct_expr_field_list_fields(
+ int id: @struct_expr_field_list ref,
+ int index: int ref,
+ int field: @struct_expr_field ref
+);
+
+#keyset[id]
+struct_expr_field_list_spreads(
+ int id: @struct_expr_field_list ref,
+ int spread: @expr ref
+);
+
+struct_fields(
+ unique int id: @struct_field
+);
+
+#keyset[id, index]
+struct_field_attrs(
+ int id: @struct_field ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+struct_field_defaults(
+ int id: @struct_field ref,
+ int default: @expr ref
+);
+
+#keyset[id]
+struct_field_names(
+ int id: @struct_field ref,
+ int name: @name ref
+);
+
+#keyset[id]
+struct_field_type_reprs(
+ int id: @struct_field ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+struct_field_visibilities(
+ int id: @struct_field ref,
+ int visibility: @visibility ref
+);
+
+struct_pat_fields(
+ unique int id: @struct_pat_field
+);
+
+#keyset[id, index]
+struct_pat_field_attrs(
+ int id: @struct_pat_field ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+struct_pat_field_identifiers(
+ int id: @struct_pat_field ref,
+ int identifier: @name_ref ref
+);
+
+#keyset[id]
+struct_pat_field_pats(
+ int id: @struct_pat_field ref,
+ int pat: @pat ref
+);
+
+struct_pat_field_lists(
+ unique int id: @struct_pat_field_list
+);
+
+#keyset[id, index]
+struct_pat_field_list_fields(
+ int id: @struct_pat_field_list ref,
+ int index: int ref,
+ int field: @struct_pat_field ref
+);
+
+#keyset[id]
+struct_pat_field_list_rest_pats(
+ int id: @struct_pat_field_list ref,
+ int rest_pat: @rest_pat ref
+);
+
+@token =
+ @comment
+;
+
+token_trees(
+ unique int id: @token_tree
+);
+
+tuple_fields(
+ unique int id: @tuple_field
+);
+
+#keyset[id, index]
+tuple_field_attrs(
+ int id: @tuple_field ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+tuple_field_type_reprs(
+ int id: @tuple_field ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+tuple_field_visibilities(
+ int id: @tuple_field ref,
+ int visibility: @visibility ref
+);
+
+type_bounds(
+ unique int id: @type_bound
+);
+
+#keyset[id]
+type_bound_is_async(
+ int id: @type_bound ref
+);
+
+#keyset[id]
+type_bound_is_const(
+ int id: @type_bound ref
+);
+
+#keyset[id]
+type_bound_lifetimes(
+ int id: @type_bound ref,
+ int lifetime: @lifetime ref
+);
+
+#keyset[id]
+type_bound_type_reprs(
+ int id: @type_bound ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+type_bound_use_bound_generic_args(
+ int id: @type_bound ref,
+ int use_bound_generic_args: @use_bound_generic_args ref
+);
+
+type_bound_lists(
+ unique int id: @type_bound_list
+);
+
+#keyset[id, index]
+type_bound_list_bounds(
+ int id: @type_bound_list ref,
+ int index: int ref,
+ int bound: @type_bound ref
+);
+
+@type_repr =
+ @array_type_repr
+| @dyn_trait_type_repr
+| @fn_ptr_type_repr
+| @for_type_repr
+| @impl_trait_type_repr
+| @infer_type_repr
+| @macro_type_repr
+| @never_type_repr
+| @paren_type_repr
+| @path_type_repr
+| @ptr_type_repr
+| @ref_type_repr
+| @slice_type_repr
+| @tuple_type_repr
+;
+
+@use_bound_generic_arg =
+ @lifetime
+| @name_ref
+;
+
+use_bound_generic_args(
+ unique int id: @use_bound_generic_args
+);
+
+#keyset[id, index]
+use_bound_generic_args_use_bound_generic_args(
+ int id: @use_bound_generic_args ref,
+ int index: int ref,
+ int use_bound_generic_arg: @use_bound_generic_arg ref
+);
+
+use_trees(
+ unique int id: @use_tree
+);
+
+#keyset[id]
+use_tree_is_glob(
+ int id: @use_tree ref
+);
+
+#keyset[id]
+use_tree_paths(
+ int id: @use_tree ref,
+ int path: @path ref
+);
+
+#keyset[id]
+use_tree_renames(
+ int id: @use_tree ref,
+ int rename: @rename ref
+);
+
+#keyset[id]
+use_tree_use_tree_lists(
+ int id: @use_tree ref,
+ int use_tree_list: @use_tree_list ref
+);
+
+use_tree_lists(
+ unique int id: @use_tree_list
+);
+
+#keyset[id, index]
+use_tree_list_use_trees(
+ int id: @use_tree_list ref,
+ int index: int ref,
+ int use_tree: @use_tree ref
+);
+
+@variant_def =
+ @struct
+| @union
+| @variant
+;
+
+variant_lists(
+ unique int id: @variant_list
+);
+
+#keyset[id, index]
+variant_list_variants(
+ int id: @variant_list ref,
+ int index: int ref,
+ int variant: @variant ref
+);
+
+visibilities(
+ unique int id: @visibility
+);
+
+#keyset[id]
+visibility_paths(
+ int id: @visibility ref,
+ int path: @path ref
+);
+
+where_clauses(
+ unique int id: @where_clause
+);
+
+#keyset[id, index]
+where_clause_predicates(
+ int id: @where_clause ref,
+ int index: int ref,
+ int predicate: @where_pred ref
+);
+
+where_preds(
+ unique int id: @where_pred
+);
+
+#keyset[id]
+where_pred_generic_param_lists(
+ int id: @where_pred ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+where_pred_lifetimes(
+ int id: @where_pred ref,
+ int lifetime: @lifetime ref
+);
+
+#keyset[id]
+where_pred_type_reprs(
+ int id: @where_pred ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+where_pred_type_bound_lists(
+ int id: @where_pred ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+array_expr_internals(
+ unique int id: @array_expr_internal
+);
+
+#keyset[id, index]
+array_expr_internal_attrs(
+ int id: @array_expr_internal ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+array_expr_internal_exprs(
+ int id: @array_expr_internal ref,
+ int index: int ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+array_expr_internal_is_semicolon(
+ int id: @array_expr_internal ref
+);
+
+array_type_reprs(
+ unique int id: @array_type_repr
+);
+
+#keyset[id]
+array_type_repr_const_args(
+ int id: @array_type_repr ref,
+ int const_arg: @const_arg ref
+);
+
+#keyset[id]
+array_type_repr_element_type_reprs(
+ int id: @array_type_repr ref,
+ int element_type_repr: @type_repr ref
+);
+
+asm_clobber_abis(
+ unique int id: @asm_clobber_abi
+);
+
+asm_consts(
+ unique int id: @asm_const
+);
+
+#keyset[id]
+asm_const_exprs(
+ int id: @asm_const ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+asm_const_is_const(
+ int id: @asm_const ref
+);
+
+asm_exprs(
+ unique int id: @asm_expr
+);
+
+#keyset[id, index]
+asm_expr_asm_pieces(
+ int id: @asm_expr ref,
+ int index: int ref,
+ int asm_piece: @asm_piece ref
+);
+
+#keyset[id, index]
+asm_expr_attrs(
+ int id: @asm_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+asm_expr_templates(
+ int id: @asm_expr ref,
+ int index: int ref,
+ int template: @expr ref
+);
+
+asm_labels(
+ unique int id: @asm_label
+);
+
+#keyset[id]
+asm_label_block_exprs(
+ int id: @asm_label ref,
+ int block_expr: @block_expr ref
+);
+
+asm_operand_nameds(
+ unique int id: @asm_operand_named
+);
+
+#keyset[id]
+asm_operand_named_asm_operands(
+ int id: @asm_operand_named ref,
+ int asm_operand: @asm_operand ref
+);
+
+#keyset[id]
+asm_operand_named_names(
+ int id: @asm_operand_named ref,
+ int name: @name ref
+);
+
+asm_options_lists(
+ unique int id: @asm_options_list
+);
+
+#keyset[id, index]
+asm_options_list_asm_options(
+ int id: @asm_options_list ref,
+ int index: int ref,
+ int asm_option: @asm_option ref
+);
+
+asm_reg_operands(
+ unique int id: @asm_reg_operand
+);
+
+#keyset[id]
+asm_reg_operand_asm_dir_specs(
+ int id: @asm_reg_operand ref,
+ int asm_dir_spec: @asm_dir_spec ref
+);
+
+#keyset[id]
+asm_reg_operand_asm_operand_exprs(
+ int id: @asm_reg_operand ref,
+ int asm_operand_expr: @asm_operand_expr ref
+);
+
+#keyset[id]
+asm_reg_operand_asm_reg_specs(
+ int id: @asm_reg_operand ref,
+ int asm_reg_spec: @asm_reg_spec ref
+);
+
+asm_syms(
+ unique int id: @asm_sym
+);
+
+#keyset[id]
+asm_sym_paths(
+ int id: @asm_sym ref,
+ int path: @path ref
+);
+
+assoc_type_args(
+ unique int id: @assoc_type_arg
+);
+
+#keyset[id]
+assoc_type_arg_const_args(
+ int id: @assoc_type_arg ref,
+ int const_arg: @const_arg ref
+);
+
+#keyset[id]
+assoc_type_arg_generic_arg_lists(
+ int id: @assoc_type_arg ref,
+ int generic_arg_list: @generic_arg_list ref
+);
+
+#keyset[id]
+assoc_type_arg_identifiers(
+ int id: @assoc_type_arg ref,
+ int identifier: @name_ref ref
+);
+
+#keyset[id]
+assoc_type_arg_param_lists(
+ int id: @assoc_type_arg ref,
+ int param_list: @param_list ref
+);
+
+#keyset[id]
+assoc_type_arg_ret_types(
+ int id: @assoc_type_arg ref,
+ int ret_type: @ret_type_repr ref
+);
+
+#keyset[id]
+assoc_type_arg_return_type_syntaxes(
+ int id: @assoc_type_arg ref,
+ int return_type_syntax: @return_type_syntax ref
+);
+
+#keyset[id]
+assoc_type_arg_type_reprs(
+ int id: @assoc_type_arg ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+assoc_type_arg_type_bound_lists(
+ int id: @assoc_type_arg ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+await_exprs(
+ unique int id: @await_expr
+);
+
+#keyset[id, index]
+await_expr_attrs(
+ int id: @await_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+await_expr_exprs(
+ int id: @await_expr ref,
+ int expr: @expr ref
+);
+
+become_exprs(
+ unique int id: @become_expr
+);
+
+#keyset[id, index]
+become_expr_attrs(
+ int id: @become_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+become_expr_exprs(
+ int id: @become_expr ref,
+ int expr: @expr ref
+);
+
+binary_exprs(
+ unique int id: @binary_expr
+);
+
+#keyset[id, index]
+binary_expr_attrs(
+ int id: @binary_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+binary_expr_lhs(
+ int id: @binary_expr ref,
+ int lhs: @expr ref
+);
+
+#keyset[id]
+binary_expr_operator_names(
+ int id: @binary_expr ref,
+ string operator_name: string ref
+);
+
+#keyset[id]
+binary_expr_rhs(
+ int id: @binary_expr ref,
+ int rhs: @expr ref
+);
+
+box_pats(
+ unique int id: @box_pat
+);
+
+#keyset[id]
+box_pat_pats(
+ int id: @box_pat ref,
+ int pat: @pat ref
+);
+
+break_exprs(
+ unique int id: @break_expr
+);
+
+#keyset[id, index]
+break_expr_attrs(
+ int id: @break_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+break_expr_exprs(
+ int id: @break_expr ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+break_expr_lifetimes(
+ int id: @break_expr ref,
+ int lifetime: @lifetime ref
+);
+
+@call_expr_base =
+ @call_expr
+| @method_call_expr
+;
+
+#keyset[id]
+call_expr_base_arg_lists(
+ int id: @call_expr_base ref,
+ int arg_list: @arg_list ref
+);
+
+#keyset[id, index]
+call_expr_base_attrs(
+ int id: @call_expr_base ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+cast_exprs(
+ unique int id: @cast_expr
+);
+
+#keyset[id, index]
+cast_expr_attrs(
+ int id: @cast_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+cast_expr_exprs(
+ int id: @cast_expr ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+cast_expr_type_reprs(
+ int id: @cast_expr ref,
+ int type_repr: @type_repr ref
+);
+
+closure_exprs(
+ unique int id: @closure_expr
+);
+
+#keyset[id]
+closure_expr_bodies(
+ int id: @closure_expr ref,
+ int body: @expr ref
+);
+
+#keyset[id]
+closure_expr_closure_binders(
+ int id: @closure_expr ref,
+ int closure_binder: @closure_binder ref
+);
+
+#keyset[id]
+closure_expr_is_async(
+ int id: @closure_expr ref
+);
+
+#keyset[id]
+closure_expr_is_const(
+ int id: @closure_expr ref
+);
+
+#keyset[id]
+closure_expr_is_gen(
+ int id: @closure_expr ref
+);
+
+#keyset[id]
+closure_expr_is_move(
+ int id: @closure_expr ref
+);
+
+#keyset[id]
+closure_expr_is_static(
+ int id: @closure_expr ref
+);
+
+#keyset[id]
+closure_expr_ret_types(
+ int id: @closure_expr ref,
+ int ret_type: @ret_type_repr ref
+);
+
+comments(
+ unique int id: @comment,
+ int parent: @ast_node ref,
+ string text: string ref
+);
+
+const_args(
+ unique int id: @const_arg
+);
+
+#keyset[id]
+const_arg_exprs(
+ int id: @const_arg ref,
+ int expr: @expr ref
+);
+
+const_block_pats(
+ unique int id: @const_block_pat
+);
+
+#keyset[id]
+const_block_pat_block_exprs(
+ int id: @const_block_pat ref,
+ int block_expr: @block_expr ref
+);
+
+#keyset[id]
+const_block_pat_is_const(
+ int id: @const_block_pat ref
+);
+
+const_params(
+ unique int id: @const_param
+);
+
+#keyset[id, index]
+const_param_attrs(
+ int id: @const_param ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+const_param_default_vals(
+ int id: @const_param ref,
+ int default_val: @const_arg ref
+);
+
+#keyset[id]
+const_param_is_const(
+ int id: @const_param ref
+);
+
+#keyset[id]
+const_param_names(
+ int id: @const_param ref,
+ int name: @name ref
+);
+
+#keyset[id]
+const_param_type_reprs(
+ int id: @const_param ref,
+ int type_repr: @type_repr ref
+);
+
+continue_exprs(
+ unique int id: @continue_expr
+);
+
+#keyset[id, index]
+continue_expr_attrs(
+ int id: @continue_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+continue_expr_lifetimes(
+ int id: @continue_expr ref,
+ int lifetime: @lifetime ref
+);
+
+dyn_trait_type_reprs(
+ unique int id: @dyn_trait_type_repr
+);
+
+#keyset[id]
+dyn_trait_type_repr_type_bound_lists(
+ int id: @dyn_trait_type_repr ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+expr_stmts(
+ unique int id: @expr_stmt
+);
+
+#keyset[id]
+expr_stmt_exprs(
+ int id: @expr_stmt ref,
+ int expr: @expr ref
+);
+
+field_exprs(
+ unique int id: @field_expr
+);
+
+#keyset[id, index]
+field_expr_attrs(
+ int id: @field_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+field_expr_containers(
+ int id: @field_expr ref,
+ int container: @expr ref
+);
+
+#keyset[id]
+field_expr_identifiers(
+ int id: @field_expr ref,
+ int identifier: @name_ref ref
+);
+
+fn_ptr_type_reprs(
+ unique int id: @fn_ptr_type_repr
+);
+
+#keyset[id]
+fn_ptr_type_repr_abis(
+ int id: @fn_ptr_type_repr ref,
+ int abi: @abi ref
+);
+
+#keyset[id]
+fn_ptr_type_repr_is_async(
+ int id: @fn_ptr_type_repr ref
+);
+
+#keyset[id]
+fn_ptr_type_repr_is_const(
+ int id: @fn_ptr_type_repr ref
+);
+
+#keyset[id]
+fn_ptr_type_repr_is_unsafe(
+ int id: @fn_ptr_type_repr ref
+);
+
+#keyset[id]
+fn_ptr_type_repr_param_lists(
+ int id: @fn_ptr_type_repr ref,
+ int param_list: @param_list ref
+);
+
+#keyset[id]
+fn_ptr_type_repr_ret_types(
+ int id: @fn_ptr_type_repr ref,
+ int ret_type: @ret_type_repr ref
+);
+
+for_type_reprs(
+ unique int id: @for_type_repr
+);
+
+#keyset[id]
+for_type_repr_generic_param_lists(
+ int id: @for_type_repr ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+for_type_repr_type_reprs(
+ int id: @for_type_repr ref,
+ int type_repr: @type_repr ref
+);
+
+format_args_exprs(
+ unique int id: @format_args_expr
+);
+
+#keyset[id, index]
+format_args_expr_args(
+ int id: @format_args_expr ref,
+ int index: int ref,
+ int arg: @format_args_arg ref
+);
+
+#keyset[id, index]
+format_args_expr_attrs(
+ int id: @format_args_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+format_args_expr_templates(
+ int id: @format_args_expr ref,
+ int template: @expr ref
+);
+
+ident_pats(
+ unique int id: @ident_pat
+);
+
+#keyset[id, index]
+ident_pat_attrs(
+ int id: @ident_pat ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+ident_pat_is_mut(
+ int id: @ident_pat ref
+);
+
+#keyset[id]
+ident_pat_is_ref(
+ int id: @ident_pat ref
+);
+
+#keyset[id]
+ident_pat_names(
+ int id: @ident_pat ref,
+ int name: @name ref
+);
+
+#keyset[id]
+ident_pat_pats(
+ int id: @ident_pat ref,
+ int pat: @pat ref
+);
+
+if_exprs(
+ unique int id: @if_expr
+);
+
+#keyset[id, index]
+if_expr_attrs(
+ int id: @if_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+if_expr_conditions(
+ int id: @if_expr ref,
+ int condition: @expr ref
+);
+
+#keyset[id]
+if_expr_elses(
+ int id: @if_expr ref,
+ int else: @expr ref
+);
+
+#keyset[id]
+if_expr_thens(
+ int id: @if_expr ref,
+ int then: @block_expr ref
+);
+
+impl_trait_type_reprs(
+ unique int id: @impl_trait_type_repr
+);
+
+#keyset[id]
+impl_trait_type_repr_type_bound_lists(
+ int id: @impl_trait_type_repr ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+index_exprs(
+ unique int id: @index_expr
+);
+
+#keyset[id, index]
+index_expr_attrs(
+ int id: @index_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+index_expr_bases(
+ int id: @index_expr ref,
+ int base: @expr ref
+);
+
+#keyset[id]
+index_expr_indices(
+ int id: @index_expr ref,
+ int index: @expr ref
+);
+
+infer_type_reprs(
+ unique int id: @infer_type_repr
+);
+
+@item =
+ @const
+| @enum
+| @extern_block
+| @extern_crate
+| @function
+| @impl
+| @macro_call
+| @macro_def
+| @macro_rules
+| @module
+| @static
+| @struct
+| @trait
+| @trait_alias
+| @type_alias
+| @union
+| @use
+;
+
+@labelable_expr =
+ @block_expr
+| @looping_expr
+;
+
+#keyset[id]
+labelable_expr_labels(
+ int id: @labelable_expr ref,
+ int label: @label ref
+);
+
+let_exprs(
+ unique int id: @let_expr
+);
+
+#keyset[id, index]
+let_expr_attrs(
+ int id: @let_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+let_expr_scrutinees(
+ int id: @let_expr ref,
+ int scrutinee: @expr ref
+);
+
+#keyset[id]
+let_expr_pats(
+ int id: @let_expr ref,
+ int pat: @pat ref
+);
+
+let_stmts(
+ unique int id: @let_stmt
+);
+
+#keyset[id, index]
+let_stmt_attrs(
+ int id: @let_stmt ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+let_stmt_initializers(
+ int id: @let_stmt ref,
+ int initializer: @expr ref
+);
+
+#keyset[id]
+let_stmt_let_elses(
+ int id: @let_stmt ref,
+ int let_else: @let_else ref
+);
+
+#keyset[id]
+let_stmt_pats(
+ int id: @let_stmt ref,
+ int pat: @pat ref
+);
+
+#keyset[id]
+let_stmt_type_reprs(
+ int id: @let_stmt ref,
+ int type_repr: @type_repr ref
+);
+
+lifetimes(
+ unique int id: @lifetime
+);
+
+#keyset[id]
+lifetime_texts(
+ int id: @lifetime ref,
+ string text: string ref
+);
+
+lifetime_args(
+ unique int id: @lifetime_arg
+);
+
+#keyset[id]
+lifetime_arg_lifetimes(
+ int id: @lifetime_arg ref,
+ int lifetime: @lifetime ref
+);
+
+lifetime_params(
+ unique int id: @lifetime_param
+);
+
+#keyset[id, index]
+lifetime_param_attrs(
+ int id: @lifetime_param ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+lifetime_param_lifetimes(
+ int id: @lifetime_param ref,
+ int lifetime: @lifetime ref
+);
+
+#keyset[id]
+lifetime_param_type_bound_lists(
+ int id: @lifetime_param ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+literal_exprs(
+ unique int id: @literal_expr
+);
+
+#keyset[id, index]
+literal_expr_attrs(
+ int id: @literal_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+literal_expr_text_values(
+ int id: @literal_expr ref,
+ string text_value: string ref
+);
+
+literal_pats(
+ unique int id: @literal_pat
+);
+
+#keyset[id]
+literal_pat_literals(
+ int id: @literal_pat ref,
+ int literal: @literal_expr ref
+);
+
+macro_exprs(
+ unique int id: @macro_expr
+);
+
+#keyset[id]
+macro_expr_macro_calls(
+ int id: @macro_expr ref,
+ int macro_call: @macro_call ref
+);
+
+macro_pats(
+ unique int id: @macro_pat
+);
+
+#keyset[id]
+macro_pat_macro_calls(
+ int id: @macro_pat ref,
+ int macro_call: @macro_call ref
+);
+
+macro_type_reprs(
+ unique int id: @macro_type_repr
+);
+
+#keyset[id]
+macro_type_repr_macro_calls(
+ int id: @macro_type_repr ref,
+ int macro_call: @macro_call ref
+);
+
+match_exprs(
+ unique int id: @match_expr
+);
+
+#keyset[id, index]
+match_expr_attrs(
+ int id: @match_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+match_expr_scrutinees(
+ int id: @match_expr ref,
+ int scrutinee: @expr ref
+);
+
+#keyset[id]
+match_expr_match_arm_lists(
+ int id: @match_expr ref,
+ int match_arm_list: @match_arm_list ref
+);
+
+name_refs(
+ unique int id: @name_ref
+);
+
+#keyset[id]
+name_ref_texts(
+ int id: @name_ref ref,
+ string text: string ref
+);
+
+never_type_reprs(
+ unique int id: @never_type_repr
+);
+
+offset_of_exprs(
+ unique int id: @offset_of_expr
+);
+
+#keyset[id, index]
+offset_of_expr_attrs(
+ int id: @offset_of_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+offset_of_expr_fields(
+ int id: @offset_of_expr ref,
+ int index: int ref,
+ int field: @name_ref ref
+);
+
+#keyset[id]
+offset_of_expr_type_reprs(
+ int id: @offset_of_expr ref,
+ int type_repr: @type_repr ref
+);
+
+or_pats(
+ unique int id: @or_pat
+);
+
+#keyset[id, index]
+or_pat_pats(
+ int id: @or_pat ref,
+ int index: int ref,
+ int pat: @pat ref
+);
+
+params(
+ unique int id: @param
+);
+
+#keyset[id]
+param_pats(
+ int id: @param ref,
+ int pat: @pat ref
+);
+
+paren_exprs(
+ unique int id: @paren_expr
+);
+
+#keyset[id, index]
+paren_expr_attrs(
+ int id: @paren_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+paren_expr_exprs(
+ int id: @paren_expr ref,
+ int expr: @expr ref
+);
+
+paren_pats(
+ unique int id: @paren_pat
+);
+
+#keyset[id]
+paren_pat_pats(
+ int id: @paren_pat ref,
+ int pat: @pat ref
+);
+
+paren_type_reprs(
+ unique int id: @paren_type_repr
+);
+
+#keyset[id]
+paren_type_repr_type_reprs(
+ int id: @paren_type_repr ref,
+ int type_repr: @type_repr ref
+);
+
+@path_ast_node =
+ @path_expr
+| @path_pat
+| @struct_expr
+| @struct_pat
+| @tuple_struct_pat
+;
+
+#keyset[id]
+path_ast_node_paths(
+ int id: @path_ast_node ref,
+ int path: @path ref
+);
+
+@path_expr_base =
+ @path_expr
+;
+
+path_type_reprs(
+ unique int id: @path_type_repr
+);
+
+#keyset[id]
+path_type_repr_paths(
+ int id: @path_type_repr ref,
+ int path: @path ref
+);
+
+prefix_exprs(
+ unique int id: @prefix_expr
+);
+
+#keyset[id, index]
+prefix_expr_attrs(
+ int id: @prefix_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+prefix_expr_exprs(
+ int id: @prefix_expr ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+prefix_expr_operator_names(
+ int id: @prefix_expr ref,
+ string operator_name: string ref
+);
+
+ptr_type_reprs(
+ unique int id: @ptr_type_repr
+);
+
+#keyset[id]
+ptr_type_repr_is_const(
+ int id: @ptr_type_repr ref
+);
+
+#keyset[id]
+ptr_type_repr_is_mut(
+ int id: @ptr_type_repr ref
+);
+
+#keyset[id]
+ptr_type_repr_type_reprs(
+ int id: @ptr_type_repr ref,
+ int type_repr: @type_repr ref
+);
+
+range_exprs(
+ unique int id: @range_expr
+);
+
+#keyset[id, index]
+range_expr_attrs(
+ int id: @range_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+range_expr_ends(
+ int id: @range_expr ref,
+ int end: @expr ref
+);
+
+#keyset[id]
+range_expr_operator_names(
+ int id: @range_expr ref,
+ string operator_name: string ref
+);
+
+#keyset[id]
+range_expr_starts(
+ int id: @range_expr ref,
+ int start: @expr ref
+);
+
+range_pats(
+ unique int id: @range_pat
+);
+
+#keyset[id]
+range_pat_ends(
+ int id: @range_pat ref,
+ int end: @pat ref
+);
+
+#keyset[id]
+range_pat_operator_names(
+ int id: @range_pat ref,
+ string operator_name: string ref
+);
+
+#keyset[id]
+range_pat_starts(
+ int id: @range_pat ref,
+ int start: @pat ref
+);
+
+ref_exprs(
+ unique int id: @ref_expr
+);
+
+#keyset[id, index]
+ref_expr_attrs(
+ int id: @ref_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+ref_expr_exprs(
+ int id: @ref_expr ref,
+ int expr: @expr ref
+);
+
+#keyset[id]
+ref_expr_is_const(
+ int id: @ref_expr ref
+);
+
+#keyset[id]
+ref_expr_is_mut(
+ int id: @ref_expr ref
+);
+
+#keyset[id]
+ref_expr_is_raw(
+ int id: @ref_expr ref
+);
+
+ref_pats(
+ unique int id: @ref_pat
+);
+
+#keyset[id]
+ref_pat_is_mut(
+ int id: @ref_pat ref
+);
+
+#keyset[id]
+ref_pat_pats(
+ int id: @ref_pat ref,
+ int pat: @pat ref
+);
+
+ref_type_reprs(
+ unique int id: @ref_type_repr
+);
+
+#keyset[id]
+ref_type_repr_is_mut(
+ int id: @ref_type_repr ref
+);
+
+#keyset[id]
+ref_type_repr_lifetimes(
+ int id: @ref_type_repr ref,
+ int lifetime: @lifetime ref
+);
+
+#keyset[id]
+ref_type_repr_type_reprs(
+ int id: @ref_type_repr ref,
+ int type_repr: @type_repr ref
+);
+
+rest_pats(
+ unique int id: @rest_pat
+);
+
+#keyset[id, index]
+rest_pat_attrs(
+ int id: @rest_pat ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+return_exprs(
+ unique int id: @return_expr
+);
+
+#keyset[id, index]
+return_expr_attrs(
+ int id: @return_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+return_expr_exprs(
+ int id: @return_expr ref,
+ int expr: @expr ref
+);
+
+self_params(
+ unique int id: @self_param
+);
+
+#keyset[id]
+self_param_is_ref(
+ int id: @self_param ref
+);
+
+#keyset[id]
+self_param_is_mut(
+ int id: @self_param ref
+);
+
+#keyset[id]
+self_param_lifetimes(
+ int id: @self_param ref,
+ int lifetime: @lifetime ref
+);
+
+#keyset[id]
+self_param_names(
+ int id: @self_param ref,
+ int name: @name ref
+);
+
+slice_pats(
+ unique int id: @slice_pat
+);
+
+#keyset[id, index]
+slice_pat_pats(
+ int id: @slice_pat ref,
+ int index: int ref,
+ int pat: @pat ref
+);
+
+slice_type_reprs(
+ unique int id: @slice_type_repr
+);
+
+#keyset[id]
+slice_type_repr_type_reprs(
+ int id: @slice_type_repr ref,
+ int type_repr: @type_repr ref
+);
+
+struct_field_lists(
+ unique int id: @struct_field_list
+);
+
+#keyset[id, index]
+struct_field_list_fields(
+ int id: @struct_field_list ref,
+ int index: int ref,
+ int field: @struct_field ref
+);
+
+try_exprs(
+ unique int id: @try_expr
+);
+
+#keyset[id, index]
+try_expr_attrs(
+ int id: @try_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+try_expr_exprs(
+ int id: @try_expr ref,
+ int expr: @expr ref
+);
+
+tuple_exprs(
+ unique int id: @tuple_expr
+);
+
+#keyset[id, index]
+tuple_expr_attrs(
+ int id: @tuple_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id, index]
+tuple_expr_fields(
+ int id: @tuple_expr ref,
+ int index: int ref,
+ int field: @expr ref
+);
+
+tuple_field_lists(
+ unique int id: @tuple_field_list
+);
+
+#keyset[id, index]
+tuple_field_list_fields(
+ int id: @tuple_field_list ref,
+ int index: int ref,
+ int field: @tuple_field ref
+);
+
+tuple_pats(
+ unique int id: @tuple_pat
+);
+
+#keyset[id, index]
+tuple_pat_fields(
+ int id: @tuple_pat ref,
+ int index: int ref,
+ int field: @pat ref
+);
+
+tuple_type_reprs(
+ unique int id: @tuple_type_repr
+);
+
+#keyset[id, index]
+tuple_type_repr_fields(
+ int id: @tuple_type_repr ref,
+ int index: int ref,
+ int field: @type_repr ref
+);
+
+type_args(
+ unique int id: @type_arg
+);
+
+#keyset[id]
+type_arg_type_reprs(
+ int id: @type_arg ref,
+ int type_repr: @type_repr ref
+);
+
+type_params(
+ unique int id: @type_param
+);
+
+#keyset[id, index]
+type_param_attrs(
+ int id: @type_param ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+type_param_default_types(
+ int id: @type_param ref,
+ int default_type: @type_repr ref
+);
+
+#keyset[id]
+type_param_names(
+ int id: @type_param ref,
+ int name: @name ref
+);
+
+#keyset[id]
+type_param_type_bound_lists(
+ int id: @type_param ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+underscore_exprs(
+ unique int id: @underscore_expr
+);
+
+#keyset[id, index]
+underscore_expr_attrs(
+ int id: @underscore_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+variants(
+ unique int id: @variant
+);
+
+#keyset[id, index]
+variant_attrs(
+ int id: @variant ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+variant_discriminants(
+ int id: @variant ref,
+ int discriminant: @expr ref
+);
+
+#keyset[id]
+variant_field_lists(
+ int id: @variant ref,
+ int field_list: @field_list ref
+);
+
+#keyset[id]
+variant_names(
+ int id: @variant ref,
+ int name: @name ref
+);
+
+#keyset[id]
+variant_visibilities(
+ int id: @variant ref,
+ int visibility: @visibility ref
+);
+
+wildcard_pats(
+ unique int id: @wildcard_pat
+);
+
+yeet_exprs(
+ unique int id: @yeet_expr
+);
+
+#keyset[id, index]
+yeet_expr_attrs(
+ int id: @yeet_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+yeet_expr_exprs(
+ int id: @yeet_expr ref,
+ int expr: @expr ref
+);
+
+yield_exprs(
+ unique int id: @yield_expr
+);
+
+#keyset[id, index]
+yield_expr_attrs(
+ int id: @yield_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+yield_expr_exprs(
+ int id: @yield_expr ref,
+ int expr: @expr ref
+);
+
+block_exprs(
+ unique int id: @block_expr
+);
+
+#keyset[id, index]
+block_expr_attrs(
+ int id: @block_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+block_expr_is_async(
+ int id: @block_expr ref
+);
+
+#keyset[id]
+block_expr_is_const(
+ int id: @block_expr ref
+);
+
+#keyset[id]
+block_expr_is_gen(
+ int id: @block_expr ref
+);
+
+#keyset[id]
+block_expr_is_move(
+ int id: @block_expr ref
+);
+
+#keyset[id]
+block_expr_is_try(
+ int id: @block_expr ref
+);
+
+#keyset[id]
+block_expr_is_unsafe(
+ int id: @block_expr ref
+);
+
+#keyset[id]
+block_expr_stmt_lists(
+ int id: @block_expr ref,
+ int stmt_list: @stmt_list ref
+);
+
+call_exprs(
+ unique int id: @call_expr
+);
+
+#keyset[id]
+call_expr_functions(
+ int id: @call_expr ref,
+ int function: @expr ref
+);
+
+consts(
+ unique int id: @const
+);
+
+#keyset[id, index]
+const_attrs(
+ int id: @const ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+const_bodies(
+ int id: @const ref,
+ int body: @expr ref
+);
+
+#keyset[id]
+const_is_const(
+ int id: @const ref
+);
+
+#keyset[id]
+const_is_default(
+ int id: @const ref
+);
+
+#keyset[id]
+const_names(
+ int id: @const ref,
+ int name: @name ref
+);
+
+#keyset[id]
+const_type_reprs(
+ int id: @const ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+const_visibilities(
+ int id: @const ref,
+ int visibility: @visibility ref
+);
+
+enums(
+ unique int id: @enum
+);
+
+#keyset[id, index]
+enum_attrs(
+ int id: @enum ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+enum_generic_param_lists(
+ int id: @enum ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+enum_names(
+ int id: @enum ref,
+ int name: @name ref
+);
+
+#keyset[id]
+enum_variant_lists(
+ int id: @enum ref,
+ int variant_list: @variant_list ref
+);
+
+#keyset[id]
+enum_visibilities(
+ int id: @enum ref,
+ int visibility: @visibility ref
+);
+
+#keyset[id]
+enum_where_clauses(
+ int id: @enum ref,
+ int where_clause: @where_clause ref
+);
+
+extern_blocks(
+ unique int id: @extern_block
+);
+
+#keyset[id]
+extern_block_abis(
+ int id: @extern_block ref,
+ int abi: @abi ref
+);
+
+#keyset[id, index]
+extern_block_attrs(
+ int id: @extern_block ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+extern_block_extern_item_lists(
+ int id: @extern_block ref,
+ int extern_item_list: @extern_item_list ref
+);
+
+#keyset[id]
+extern_block_is_unsafe(
+ int id: @extern_block ref
+);
+
+extern_crates(
+ unique int id: @extern_crate
+);
+
+#keyset[id, index]
+extern_crate_attrs(
+ int id: @extern_crate ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+extern_crate_identifiers(
+ int id: @extern_crate ref,
+ int identifier: @name_ref ref
+);
+
+#keyset[id]
+extern_crate_renames(
+ int id: @extern_crate ref,
+ int rename: @rename ref
+);
+
+#keyset[id]
+extern_crate_visibilities(
+ int id: @extern_crate ref,
+ int visibility: @visibility ref
+);
+
+functions(
+ unique int id: @function
+);
+
+#keyset[id]
+function_abis(
+ int id: @function ref,
+ int abi: @abi ref
+);
+
+#keyset[id]
+function_bodies(
+ int id: @function ref,
+ int body: @block_expr ref
+);
+
+#keyset[id]
+function_generic_param_lists(
+ int id: @function ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+function_is_async(
+ int id: @function ref
+);
+
+#keyset[id]
+function_is_const(
+ int id: @function ref
+);
+
+#keyset[id]
+function_is_default(
+ int id: @function ref
+);
+
+#keyset[id]
+function_is_gen(
+ int id: @function ref
+);
+
+#keyset[id]
+function_is_unsafe(
+ int id: @function ref
+);
+
+#keyset[id]
+function_names(
+ int id: @function ref,
+ int name: @name ref
+);
+
+#keyset[id]
+function_ret_types(
+ int id: @function ref,
+ int ret_type: @ret_type_repr ref
+);
+
+#keyset[id]
+function_visibilities(
+ int id: @function ref,
+ int visibility: @visibility ref
+);
+
+#keyset[id]
+function_where_clauses(
+ int id: @function ref,
+ int where_clause: @where_clause ref
+);
+
+impls(
+ unique int id: @impl
+);
+
+#keyset[id]
+impl_assoc_item_lists(
+ int id: @impl ref,
+ int assoc_item_list: @assoc_item_list ref
+);
+
+#keyset[id, index]
+impl_attrs(
+ int id: @impl ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+impl_generic_param_lists(
+ int id: @impl ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+impl_is_const(
+ int id: @impl ref
+);
+
+#keyset[id]
+impl_is_default(
+ int id: @impl ref
+);
+
+#keyset[id]
+impl_is_unsafe(
+ int id: @impl ref
+);
+
+#keyset[id]
+impl_self_ties(
+ int id: @impl ref,
+ int self_ty: @type_repr ref
+);
+
+#keyset[id]
+impl_traits(
+ int id: @impl ref,
+ int trait: @type_repr ref
+);
+
+#keyset[id]
+impl_visibilities(
+ int id: @impl ref,
+ int visibility: @visibility ref
+);
+
+#keyset[id]
+impl_where_clauses(
+ int id: @impl ref,
+ int where_clause: @where_clause ref
+);
+
+@looping_expr =
+ @for_expr
+| @loop_expr
+| @while_expr
+;
+
+#keyset[id]
+looping_expr_loop_bodies(
+ int id: @looping_expr ref,
+ int loop_body: @block_expr ref
+);
+
+macro_calls(
+ unique int id: @macro_call
+);
+
+#keyset[id, index]
+macro_call_attrs(
+ int id: @macro_call ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+macro_call_paths(
+ int id: @macro_call ref,
+ int path: @path ref
+);
+
+#keyset[id]
+macro_call_token_trees(
+ int id: @macro_call ref,
+ int token_tree: @token_tree ref
+);
+
+#keyset[id]
+macro_call_expandeds(
+ int id: @macro_call ref,
+ int expanded: @ast_node ref
+);
+
+macro_defs(
+ unique int id: @macro_def
+);
+
+#keyset[id]
+macro_def_args(
+ int id: @macro_def ref,
+ int args: @token_tree ref
+);
+
+#keyset[id, index]
+macro_def_attrs(
+ int id: @macro_def ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+macro_def_bodies(
+ int id: @macro_def ref,
+ int body: @token_tree ref
+);
+
+#keyset[id]
+macro_def_names(
+ int id: @macro_def ref,
+ int name: @name ref
+);
+
+#keyset[id]
+macro_def_visibilities(
+ int id: @macro_def ref,
+ int visibility: @visibility ref
+);
+
+macro_rules(
+ unique int id: @macro_rules
+);
+
+#keyset[id, index]
+macro_rules_attrs(
+ int id: @macro_rules ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+macro_rules_names(
+ int id: @macro_rules ref,
+ int name: @name ref
+);
+
+#keyset[id]
+macro_rules_token_trees(
+ int id: @macro_rules ref,
+ int token_tree: @token_tree ref
+);
+
+#keyset[id]
+macro_rules_visibilities(
+ int id: @macro_rules ref,
+ int visibility: @visibility ref
+);
+
+method_call_exprs(
+ unique int id: @method_call_expr
+);
+
+#keyset[id]
+method_call_expr_generic_arg_lists(
+ int id: @method_call_expr ref,
+ int generic_arg_list: @generic_arg_list ref
+);
+
+#keyset[id]
+method_call_expr_identifiers(
+ int id: @method_call_expr ref,
+ int identifier: @name_ref ref
+);
+
+#keyset[id]
+method_call_expr_receivers(
+ int id: @method_call_expr ref,
+ int receiver: @expr ref
+);
+
+modules(
+ unique int id: @module
+);
+
+#keyset[id, index]
+module_attrs(
+ int id: @module ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+module_item_lists(
+ int id: @module ref,
+ int item_list: @item_list ref
+);
+
+#keyset[id]
+module_names(
+ int id: @module ref,
+ int name: @name ref
+);
+
+#keyset[id]
+module_visibilities(
+ int id: @module ref,
+ int visibility: @visibility ref
+);
+
+path_exprs(
+ unique int id: @path_expr
+);
+
+#keyset[id, index]
+path_expr_attrs(
+ int id: @path_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+path_pats(
+ unique int id: @path_pat
+);
+
+statics(
+ unique int id: @static
+);
+
+#keyset[id, index]
+static_attrs(
+ int id: @static ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+static_bodies(
+ int id: @static ref,
+ int body: @expr ref
+);
+
+#keyset[id]
+static_is_mut(
+ int id: @static ref
+);
+
+#keyset[id]
+static_is_static(
+ int id: @static ref
+);
+
+#keyset[id]
+static_is_unsafe(
+ int id: @static ref
+);
+
+#keyset[id]
+static_names(
+ int id: @static ref,
+ int name: @name ref
+);
+
+#keyset[id]
+static_type_reprs(
+ int id: @static ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+static_visibilities(
+ int id: @static ref,
+ int visibility: @visibility ref
+);
+
+structs(
+ unique int id: @struct
+);
+
+#keyset[id, index]
+struct_attrs(
+ int id: @struct ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+struct_field_lists_(
+ int id: @struct ref,
+ int field_list: @field_list ref
+);
+
+#keyset[id]
+struct_generic_param_lists(
+ int id: @struct ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+struct_names(
+ int id: @struct ref,
+ int name: @name ref
+);
+
+#keyset[id]
+struct_visibilities(
+ int id: @struct ref,
+ int visibility: @visibility ref
+);
+
+#keyset[id]
+struct_where_clauses(
+ int id: @struct ref,
+ int where_clause: @where_clause ref
+);
+
+struct_exprs(
+ unique int id: @struct_expr
+);
+
+#keyset[id]
+struct_expr_struct_expr_field_lists(
+ int id: @struct_expr ref,
+ int struct_expr_field_list: @struct_expr_field_list ref
+);
+
+struct_pats(
+ unique int id: @struct_pat
+);
+
+#keyset[id]
+struct_pat_struct_pat_field_lists(
+ int id: @struct_pat ref,
+ int struct_pat_field_list: @struct_pat_field_list ref
+);
+
+traits(
+ unique int id: @trait
+);
+
+#keyset[id]
+trait_assoc_item_lists(
+ int id: @trait ref,
+ int assoc_item_list: @assoc_item_list ref
+);
+
+#keyset[id, index]
+trait_attrs(
+ int id: @trait ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+trait_generic_param_lists(
+ int id: @trait ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+trait_is_auto(
+ int id: @trait ref
+);
+
+#keyset[id]
+trait_is_unsafe(
+ int id: @trait ref
+);
+
+#keyset[id]
+trait_names(
+ int id: @trait ref,
+ int name: @name ref
+);
+
+#keyset[id]
+trait_type_bound_lists(
+ int id: @trait ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+#keyset[id]
+trait_visibilities(
+ int id: @trait ref,
+ int visibility: @visibility ref
+);
+
+#keyset[id]
+trait_where_clauses(
+ int id: @trait ref,
+ int where_clause: @where_clause ref
+);
+
+trait_aliases(
+ unique int id: @trait_alias
+);
+
+#keyset[id, index]
+trait_alias_attrs(
+ int id: @trait_alias ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+trait_alias_generic_param_lists(
+ int id: @trait_alias ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+trait_alias_names(
+ int id: @trait_alias ref,
+ int name: @name ref
+);
+
+#keyset[id]
+trait_alias_type_bound_lists(
+ int id: @trait_alias ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+#keyset[id]
+trait_alias_visibilities(
+ int id: @trait_alias ref,
+ int visibility: @visibility ref
+);
+
+#keyset[id]
+trait_alias_where_clauses(
+ int id: @trait_alias ref,
+ int where_clause: @where_clause ref
+);
+
+tuple_struct_pats(
+ unique int id: @tuple_struct_pat
+);
+
+#keyset[id, index]
+tuple_struct_pat_fields(
+ int id: @tuple_struct_pat ref,
+ int index: int ref,
+ int field: @pat ref
+);
+
+type_aliases(
+ unique int id: @type_alias
+);
+
+#keyset[id, index]
+type_alias_attrs(
+ int id: @type_alias ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+type_alias_generic_param_lists(
+ int id: @type_alias ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+type_alias_is_default(
+ int id: @type_alias ref
+);
+
+#keyset[id]
+type_alias_names(
+ int id: @type_alias ref,
+ int name: @name ref
+);
+
+#keyset[id]
+type_alias_type_reprs(
+ int id: @type_alias ref,
+ int type_repr: @type_repr ref
+);
+
+#keyset[id]
+type_alias_type_bound_lists(
+ int id: @type_alias ref,
+ int type_bound_list: @type_bound_list ref
+);
+
+#keyset[id]
+type_alias_visibilities(
+ int id: @type_alias ref,
+ int visibility: @visibility ref
+);
+
+#keyset[id]
+type_alias_where_clauses(
+ int id: @type_alias ref,
+ int where_clause: @where_clause ref
+);
+
+unions(
+ unique int id: @union
+);
+
+#keyset[id, index]
+union_attrs(
+ int id: @union ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+union_generic_param_lists(
+ int id: @union ref,
+ int generic_param_list: @generic_param_list ref
+);
+
+#keyset[id]
+union_names(
+ int id: @union ref,
+ int name: @name ref
+);
+
+#keyset[id]
+union_struct_field_lists(
+ int id: @union ref,
+ int struct_field_list: @struct_field_list ref
+);
+
+#keyset[id]
+union_visibilities(
+ int id: @union ref,
+ int visibility: @visibility ref
+);
+
+#keyset[id]
+union_where_clauses(
+ int id: @union ref,
+ int where_clause: @where_clause ref
+);
+
+uses(
+ unique int id: @use
+);
+
+#keyset[id, index]
+use_attrs(
+ int id: @use ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+use_use_trees(
+ int id: @use ref,
+ int use_tree: @use_tree ref
+);
+
+#keyset[id]
+use_visibilities(
+ int id: @use ref,
+ int visibility: @visibility ref
+);
+
+for_exprs(
+ unique int id: @for_expr
+);
+
+#keyset[id, index]
+for_expr_attrs(
+ int id: @for_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+for_expr_iterables(
+ int id: @for_expr ref,
+ int iterable: @expr ref
+);
+
+#keyset[id]
+for_expr_pats(
+ int id: @for_expr ref,
+ int pat: @pat ref
+);
+
+loop_exprs(
+ unique int id: @loop_expr
+);
+
+#keyset[id, index]
+loop_expr_attrs(
+ int id: @loop_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+while_exprs(
+ unique int id: @while_expr
+);
+
+#keyset[id, index]
+while_expr_attrs(
+ int id: @while_expr ref,
+ int index: int ref,
+ int attr: @attr ref
+);
+
+#keyset[id]
+while_expr_conditions(
+ int id: @while_expr ref,
+ int condition: @expr ref
+);
From f83f14bab2b81fa262e1896f62c84d85a5a4fb12 Mon Sep 17 00:00:00 2001
From: idrissrio
Date: Fri, 28 Mar 2025 16:31:01 +0100
Subject: [PATCH 078/409] C++: add calling convention specifier class
---
cpp/ql/lib/semmle/code/cpp/Specifier.qll | 12 ++++++++++++
.../calling-convention/calling-convention.ql | 5 +++++
2 files changed, 17 insertions(+)
create mode 100644 cpp/ql/test/library-tests/calling-convention/calling-convention.ql
diff --git a/cpp/ql/lib/semmle/code/cpp/Specifier.qll b/cpp/ql/lib/semmle/code/cpp/Specifier.qll
index 2f1976d220c4..28ba21956561 100644
--- a/cpp/ql/lib/semmle/code/cpp/Specifier.qll
+++ b/cpp/ql/lib/semmle/code/cpp/Specifier.qll
@@ -97,6 +97,18 @@ class AccessSpecifier extends Specifier {
override string getAPrimaryQlClass() { result = "AccessSpecifier" }
}
+/**
+ * A C/C++ calling convention specifier: `cdecl`, `fastcall`, `stdcall`, `thiscall`,
+ * `vectorcall`, or `clrcall`.
+ */
+class CallingConventionSpecifier extends Specifier {
+ CallingConventionSpecifier() {
+ this.hasName(["cdecl", "fastcall", "stdcall", "thiscall", "vectorcall", "clrcall"])
+ }
+
+ override string getAPrimaryQlClass() { result = "CallingConventionSpecifier" }
+}
+
/**
* An attribute introduced by GNU's `__attribute__((name))` syntax,
* Microsoft's `__declspec(name)` syntax, Microsoft's `[name]` syntax, the
diff --git a/cpp/ql/test/library-tests/calling-convention/calling-convention.ql b/cpp/ql/test/library-tests/calling-convention/calling-convention.ql
new file mode 100644
index 000000000000..02e3b3af5ce0
--- /dev/null
+++ b/cpp/ql/test/library-tests/calling-convention/calling-convention.ql
@@ -0,0 +1,5 @@
+import cpp
+
+from FunctionDeclarationEntry func, CallingConventionSpecifier ccs
+where ccs.hasName(func.getASpecifier())
+select func, func.getASpecifier()
From 9ec7f3c9a5587398a5796dd530f7fca2f1c79ed8 Mon Sep 17 00:00:00 2001
From: idrissrio
Date: Mon, 31 Mar 2025 11:57:32 +0200
Subject: [PATCH 079/409] C++: add test for calling conventions
---
.../calling-convention.expected | 7 +++++++
.../library-tests/calling-convention/test.cpp | 16 ++++++++++++++++
2 files changed, 23 insertions(+)
create mode 100644 cpp/ql/test/library-tests/calling-convention/calling-convention.expected
create mode 100644 cpp/ql/test/library-tests/calling-convention/test.cpp
diff --git a/cpp/ql/test/library-tests/calling-convention/calling-convention.expected b/cpp/ql/test/library-tests/calling-convention/calling-convention.expected
new file mode 100644
index 000000000000..a2dd41066169
--- /dev/null
+++ b/cpp/ql/test/library-tests/calling-convention/calling-convention.expected
@@ -0,0 +1,7 @@
+| test.cpp:4:21:4:35 | definition of thiscall_method | thiscall |
+| test.cpp:7:14:7:23 | definition of func_cdecl | cdecl |
+| test.cpp:9:16:9:27 | definition of func_stdcall | stdcall |
+| test.cpp:11:17:11:29 | definition of func_fastcall | fastcall |
+| test.cpp:13:20:13:34 | definition of func_vectorcall | vectorcall |
+| test.cpp:15:13:15:25 | definition of func_overload | cdecl |
+| test.cpp:16:15:16:27 | definition of func_overload | stdcall |
diff --git a/cpp/ql/test/library-tests/calling-convention/test.cpp b/cpp/ql/test/library-tests/calling-convention/test.cpp
new file mode 100644
index 000000000000..982c3c0caea9
--- /dev/null
+++ b/cpp/ql/test/library-tests/calling-convention/test.cpp
@@ -0,0 +1,16 @@
+// semmle-extractor-options: --microsoft
+
+struct call_conventions {
+ void __thiscall thiscall_method() {}
+};
+
+void __cdecl func_cdecl() {}
+
+void __stdcall func_stdcall() {}
+
+void __fastcall func_fastcall() {}
+
+void __vectorcall func_vectorcall() {}
+
+int __cdecl func_overload() {}
+int __stdcall func_overload(int x) {}
From ae555f2f2e3ac85dc7f2c2bff1330a8b016789ae Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 5 Feb 2025 17:23:49 +0000
Subject: [PATCH 080/409] Rust: Add a test for uncontrolled allocation size.
---
.../UncontrolledAllocationSize.expected | 0
.../CWE-770/UncontrolledAllocationSize.qlref | 4 +
.../test/query-tests/security/CWE-770/main.rs | 223 ++++++++++++++++++
.../query-tests/security/CWE-770/options.yml | 3 +
.../security/CWE-770/rust-toolchain.toml | 2 +
5 files changed, 232 insertions(+)
create mode 100644 rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
create mode 100644 rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.qlref
create mode 100644 rust/ql/test/query-tests/security/CWE-770/main.rs
create mode 100644 rust/ql/test/query-tests/security/CWE-770/options.yml
create mode 100644 rust/ql/test/query-tests/security/CWE-770/rust-toolchain.toml
diff --git a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.qlref b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.qlref
new file mode 100644
index 000000000000..2e30becb92cd
--- /dev/null
+++ b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.qlref
@@ -0,0 +1,4 @@
+query: queries/security/CWE-770/UncontrolledAllocationSize.ql
+postprocess:
+ - utils/test/InlineExpectationsTestQuery.ql
+ - utils/test/PrettyPrintModels.ql
diff --git a/rust/ql/test/query-tests/security/CWE-770/main.rs b/rust/ql/test/query-tests/security/CWE-770/main.rs
new file mode 100644
index 000000000000..c2a1eb111c33
--- /dev/null
+++ b/rust/ql/test/query-tests/security/CWE-770/main.rs
@@ -0,0 +1,223 @@
+#![feature(alloc_layout_extra)]
+#![feature(allocator_api)]
+#![feature(try_with_capacity)]
+#![feature(box_vec_non_null)]
+#![feature(non_null_from_ref)]
+
+struct MyStruct {
+ _a: usize,
+ _b: i64,
+}
+
+unsafe fn test_std_alloc_from_size(v: usize) {
+ let l1 = std::alloc::Layout::from_size_align(16, 1).unwrap();
+ let m1 = std::alloc::alloc(l1);
+ let _ = std::alloc::alloc(l1.align_to(8).unwrap());
+ let _ = std::alloc::alloc(l1.align_to(8).unwrap().pad_to_align());
+ let _ = std::alloc::alloc_zeroed(l1);
+ let _ = std::alloc::realloc(m1, l1, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let l2 = std::alloc::Layout::from_size_align(v, 1).unwrap();
+ let _ = std::alloc::alloc(l2); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l2.align_to(8).unwrap()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l2.align_to(8).unwrap().pad_to_align()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc_zeroed(l2); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let l3 = std::alloc::Layout::from_size_align(1, v).unwrap(); // not obviously dangerous?
+ let _ = std::alloc::alloc(l3);
+
+ let l4 = std::alloc::Layout::from_size_align_unchecked(v, 1);
+ let _ = std::alloc::alloc(l4); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let l5 = std::alloc::Layout::from_size_align_unchecked(v * std::mem::size_of::(), std::mem::size_of::());
+ let _ = std::alloc::alloc(l5); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let s6 = (std::mem::size_of::() * v) + 1;
+ let l6 = std::alloc::Layout::from_size_align_unchecked(s6, 4);
+ let _ = std::alloc::alloc(l6); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let l7 = std::alloc::Layout::from_size_align_unchecked(l6.size(), 8);
+ let _ = std::alloc::alloc(l7); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+}
+
+unsafe fn test_std_alloc_new_repeat_extend(v: usize) {
+ let l1 = std::alloc::Layout::new::<[u8; 10]>();
+ let _ = std::alloc::alloc(l1);
+
+ let l2 = std::alloc::Layout::new::();
+ let _ = std::alloc::alloc(l2);
+ let _ = std::alloc::alloc(l2.repeat(10).unwrap().0);
+ let _ = std::alloc::alloc(l2.repeat(v).unwrap().0); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l2.repeat(v + 1).unwrap().0); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l2.repeat_packed(10).unwrap());
+ let _ = std::alloc::alloc(l2.repeat_packed(v).unwrap()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l2.repeat_packed(v * 10).unwrap()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let l3 = std::alloc::Layout::array::(10).unwrap();
+ let _ = std::alloc::alloc(l3);
+ let (k1, _offs1) = l3.repeat(v).expect("arithmetic overflow?");
+ let _ = std::alloc::alloc(k1); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let (k2, _offs2) = l3.extend(k1).unwrap();
+ let _ = std::alloc::alloc(k2); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let (k3, _offs3) = k1.extend(l3).unwrap();
+ let _ = std::alloc::alloc(k3); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l3.extend_packed(k1).unwrap()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(k1.extend_packed(l3).unwrap()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let l4 = std::alloc::Layout::array::(v).unwrap();
+ let _ = std::alloc::alloc(l4); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+}
+
+fn clamp(v: T, min: T, max: T) -> T {
+ if v < min {
+ return min;
+ } else if v > max {
+ return max;
+ } else {
+ return v;
+ }
+}
+
+unsafe fn test_std_alloc_with_bounds(v: usize) {
+ let l1 = std::alloc::Layout::array::(v).unwrap();
+
+ if v < 100 {
+ let _ = std::alloc::alloc(l1);
+ } else {
+ let _ = std::alloc::alloc(l1); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ }
+
+ if v == 100 {
+ let _ = std::alloc::alloc(l1);
+ } else {
+ let _ = std::alloc::alloc(l1); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ }
+
+ {
+ let mut v_mut = v;
+
+ if v_mut > 100 {
+ v_mut = 100;
+ }
+
+ let l2 = std::alloc::Layout::array::(v_mut).unwrap();
+ let _ = std::alloc::alloc(l2);
+
+ let l3 = std::alloc::Layout::array::(v).unwrap();
+ let _ = std::alloc::alloc(l3); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ }
+
+ let l4 = std::alloc::Layout::array::(std::cmp::min(v, 100)).unwrap();
+ let _ = std::alloc::alloc(l4);
+
+ let l5 = std::alloc::Layout::array::(std::cmp::max(v, 100)).unwrap();
+ let _ = std::alloc::alloc(l5); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let l6 = std::alloc::Layout::array::(clamp(v, 1, 100)).unwrap();
+ let _ = std::alloc::alloc(l6);
+
+ let _ = std::alloc::alloc(l1); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ if v > 100 {
+ return;
+ }
+ let _ = std::alloc::alloc(l1);
+}
+
+use std::alloc::{GlobalAlloc, Allocator};
+
+unsafe fn test_system_alloc(v: usize) {
+ let l1 = std::alloc::Layout::array::(10).unwrap();
+ let _ = std::alloc::System.alloc(l1);
+ let _ = std::alloc::System.alloc_zeroed(l1);
+ let _ = std::alloc::System.allocate(l1).unwrap();
+ let _ = std::alloc::System.allocate_zeroed(l1).unwrap();
+ let _ = std::alloc::Global.allocate(l1).unwrap();
+ let _ = std::alloc::Global.allocate_zeroed(l1).unwrap();
+
+ let l2 = std::alloc::Layout::array::(v).unwrap();
+ let _ = std::alloc::System.alloc(l2); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::System.alloc_zeroed(l2); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::System.allocate(l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::System.allocate_zeroed(l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::Global.allocate(l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::Global.allocate_zeroed(l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let l3 = std::alloc::Layout::array::(10).unwrap();
+ let m3 = std::alloc::System.alloc(l3);
+ let _ = std::alloc::System.realloc(m3, l3, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let l4 = std::alloc::Layout::array::(10).unwrap();
+ let m4 = std::ptr::NonNull::::new(std::alloc::alloc(l4)).unwrap();
+ if v > 10 {
+ if v % 2 == 0 {
+ let _ = std::alloc::System.grow(m4, l4, l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ } else {
+ let _ = std::alloc::System.grow_zeroed(m4, l4, l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ }
+ } else {
+ let _ = std::alloc::System.shrink(m4, l4, l2).unwrap();
+ }
+}
+
+unsafe fn test_libc_alloc(v: usize) {
+ let m1 = libc::malloc(256);
+ let _ = libc::malloc(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = libc::aligned_alloc(8, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = libc::aligned_alloc(v, 8);
+ let _ = libc::calloc(64, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = libc::calloc(v, std::mem::size_of::()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = libc::realloc(m1, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+}
+
+unsafe fn test_vectors(v: usize) {
+ let _ = Vec::::try_with_capacity(v).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = Vec::::with_capacity(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = Vec::::try_with_capacity_in(v, std::alloc::Global).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = Vec::::with_capacity_in(v, std::alloc::Global); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let mut v1 = Vec::::with_capacity(100);
+ v1.reserve(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ v1.reserve_exact(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = v1.try_reserve(v).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = v1.try_reserve_exact(v).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ v1.resize(v, 1); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ v1.set_len(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let l2 = std::alloc::Layout::new::<[u64; 200]>();
+ let m2 = std::ptr::NonNull::::new(std::alloc::alloc(l2).cast::()).unwrap();
+ let _ = Vec::::from_parts(m2, v, 200); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let m3 = std::ptr::NonNull::::new(std::alloc::alloc(l2).cast::()).unwrap();
+ let _ = Vec::::from_parts(m3, 100, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let m4 = std::ptr::NonNull::::new(std::alloc::alloc(l2).cast::()).unwrap();
+ let _ = Vec::::from_parts_in(m4, 100, v, std::alloc::Global); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let m5 = std::alloc::alloc(l2).cast::();
+ let _ = Vec::::from_raw_parts(m5, v, 200); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let m6 = std::alloc::alloc(l2).cast::();
+ let _ = Vec::::from_raw_parts(m6, 100, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+
+ let m7 = std::alloc::alloc(l2).cast::();
+ let _ = Vec::::from_raw_parts_in(m7, 100, v, std::alloc::Global); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+}
+
+// --- main ---
+
+fn main() {
+ println!("--- begin ---");
+
+ let v = std::env::args().nth(1).unwrap_or("1024".to_string()).parse::().unwrap(); // $ Source=arg1
+
+ unsafe {
+ test_std_alloc_from_size(v);
+ test_std_alloc_new_repeat_extend(v);
+ test_std_alloc_with_bounds(v);
+ test_system_alloc(v);
+ test_libc_alloc(v);
+ test_vectors(v);
+ }
+
+ println!("--- end ---");
+}
diff --git a/rust/ql/test/query-tests/security/CWE-770/options.yml b/rust/ql/test/query-tests/security/CWE-770/options.yml
new file mode 100644
index 000000000000..95a17a53b431
--- /dev/null
+++ b/rust/ql/test/query-tests/security/CWE-770/options.yml
@@ -0,0 +1,3 @@
+qltest_cargo_check: true
+qltest_dependencies:
+ - libc = { version = "0.2.11" }
diff --git a/rust/ql/test/query-tests/security/CWE-770/rust-toolchain.toml b/rust/ql/test/query-tests/security/CWE-770/rust-toolchain.toml
new file mode 100644
index 000000000000..afeb59293258
--- /dev/null
+++ b/rust/ql/test/query-tests/security/CWE-770/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel = "nightly-2025-03-17"
From 9409cd6ed7d0f9ee2fb3d863dda9df48831837f0 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 5 Feb 2025 18:32:43 +0000
Subject: [PATCH 081/409] Rust: Prototype query.
---
.../UncontrolledAllocationSizeExtensions.qll | 34 ++++++++++++++
.../CWE-770/UncontrolledAllocationSize.ql | 44 +++++++++++++++++++
.../UncontrolledAllocationSize.expected | 4 ++
3 files changed, 82 insertions(+)
create mode 100644 rust/ql/lib/codeql/rust/security/UncontrolledAllocationSizeExtensions.qll
create mode 100644 rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql
diff --git a/rust/ql/lib/codeql/rust/security/UncontrolledAllocationSizeExtensions.qll b/rust/ql/lib/codeql/rust/security/UncontrolledAllocationSizeExtensions.qll
new file mode 100644
index 000000000000..bb0ffbb4e3c1
--- /dev/null
+++ b/rust/ql/lib/codeql/rust/security/UncontrolledAllocationSizeExtensions.qll
@@ -0,0 +1,34 @@
+/**
+ * Provides classes and predicates for reasoning about uncontrolled allocation
+ * size vulnerabilities.
+ */
+
+import rust
+private import codeql.rust.Concepts
+private import codeql.rust.dataflow.DataFlow
+private import codeql.rust.dataflow.FlowSink
+
+/**
+ * Provides default sources, sinks and barriers for detecting uncontrolled
+ * allocation size vulnerabilities, as well as extension points for adding your own.
+ */
+module UncontrolledAllocationSize {
+ /**
+ * A data flow sink for uncontrolled allocation size vulnerabilities.
+ */
+ abstract class Sink extends QuerySink::Range {
+ override string getSinkType() { result = "UncontrolledAllocationSize" }
+ }
+
+ /**
+ * A barrier for uncontrolled allocation size vulnerabilities.
+ */
+ abstract class Barrier extends DataFlow::Node { }
+
+ /**
+ * sink for uncontrolled allocation size from model data.
+ */
+ private class ModelsAsDataSink extends Sink {
+ ModelsAsDataSink() { sinkNode(this, ["alloc-size", "alloc-layout"]) }
+ }
+}
diff --git a/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql
new file mode 100644
index 000000000000..bbaaaf06a027
--- /dev/null
+++ b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.ql
@@ -0,0 +1,44 @@
+/**
+ * @name Uncontrolled allocation size
+ * @description Allocating memory with a size controlled by an external user can result in
+ * arbitrary amounts of memory being allocated.
+ * @kind path-problem
+ * @problem.severity recommendation
+ * @security-severity 7.5
+ * @precision high
+ * @id rust/uncontrolled-allocation-size
+ * @tags reliability
+ * security
+ * external/cwe/cwe-770
+ * external/cwe/cwe-789
+ */
+
+import rust
+import codeql.rust.Concepts
+import codeql.rust.dataflow.DataFlow
+import codeql.rust.dataflow.TaintTracking
+import codeql.rust.dataflow.internal.DataFlowImpl
+import codeql.rust.security.UncontrolledAllocationSizeExtensions
+
+/**
+ * A taint-tracking configuration for uncontrolled allocation size vulnerabilities.
+ */
+module UncontrolledAllocationConfig implements DataFlow::ConfigSig {
+ import UncontrolledAllocationSize
+
+ predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource }
+
+ predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
+
+ predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier }
+}
+
+module UncontrolledAllocationFlow = TaintTracking::Global;
+
+import UncontrolledAllocationFlow::PathGraph
+
+from UncontrolledAllocationFlow::PathNode source, UncontrolledAllocationFlow::PathNode sink
+where UncontrolledAllocationFlow::flowPath(source, sink)
+select sink.getNode(), source, sink,
+ "This allocation size is derived from a $@ and could allocate arbitrary amounts of memory.",
+ source.getNode(), "user-provided value"
diff --git a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
index e69de29bb2d1..58f42bec0c84 100644
--- a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
+++ b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
@@ -0,0 +1,4 @@
+#select
+edges
+nodes
+subpaths
From 03f94de3cb70178c7c5da4c1ba9b2d300a316390 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 5 Feb 2025 17:49:03 +0000
Subject: [PATCH 082/409] Rust: Add models.
---
.../lib/codeql/rust/frameworks/libc.model.yml | 9 +
.../frameworks/stdlib/lang-alloc.model.yml | 25 +
.../frameworks/stdlib/lang-core.model.yml | 14 +-
.../diagnostics/SummaryStats.expected | 2 +-
.../UncontrolledAllocationSize.expected | 443 ++++++++++++++++++
.../test/query-tests/security/CWE-770/main.rs | 80 ++--
6 files changed, 531 insertions(+), 42 deletions(-)
create mode 100644 rust/ql/lib/codeql/rust/frameworks/libc.model.yml
create mode 100644 rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml
diff --git a/rust/ql/lib/codeql/rust/frameworks/libc.model.yml b/rust/ql/lib/codeql/rust/frameworks/libc.model.yml
new file mode 100644
index 000000000000..f952656a21e5
--- /dev/null
+++ b/rust/ql/lib/codeql/rust/frameworks/libc.model.yml
@@ -0,0 +1,9 @@
+extensions:
+ - addsTo:
+ pack: codeql/rust-all
+ extensible: sinkModel
+ data:
+ - ["repo:https://github.com/rust-lang/libc:libc", "::malloc", "Argument[0]", "alloc-size", "manual"]
+ - ["repo:https://github.com/rust-lang/libc:libc", "::aligned_alloc", "Argument[1]", "alloc-size", "manual"]
+ - ["repo:https://github.com/rust-lang/libc:libc", "::calloc", "Argument[0,1]", "alloc-size", "manual"]
+ - ["repo:https://github.com/rust-lang/libc:libc", "::realloc", "Argument[1]", "alloc-size", "manual"]
diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml
new file mode 100644
index 000000000000..85cd97fb4629
--- /dev/null
+++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-alloc.model.yml
@@ -0,0 +1,25 @@
+extensions:
+ - addsTo:
+ pack: codeql/rust-all
+ extensible: sinkModel
+ data:
+ # Alloc
+ - ["lang:alloc", "crate::alloc::alloc", "Argument[0]", "alloc-layout", "manual"]
+ - ["lang:alloc", "crate::alloc::alloc_zeroed", "Argument[0]", "alloc-layout", "manual"]
+ - ["lang:alloc", "crate::alloc::realloc", "Argument[2]", "alloc-size", "manual"]
+ - ["lang:std", "::alloc", "Argument[0]", "alloc-layout", "manual"]
+ - ["lang:std", "::alloc_zeroed", "Argument[0]", "alloc-layout", "manual"]
+ - ["lang:std", "::allocate", "Argument[0]", "alloc-layout", "manual"]
+ - ["lang:std", "::allocate_zeroed", "Argument[0]", "alloc-layout", "manual"]
+ - ["lang:std", "::grow", "Argument[2]", "alloc-layout", "manual"]
+ - ["lang:std", "::grow_zeroed", "Argument[2]", "alloc-layout", "manual"]
+ - ["lang:alloc", "::alloc", "Argument[0]", "alloc-layout", "manual"]
+ - ["lang:alloc", "::alloc_zeroed", "Argument[0]", "alloc-layout", "manual"]
+ - ["lang:alloc", "::allocate", "Argument[0]", "alloc-layout", "manual"]
+ - ["lang:alloc", "::allocate_zeroed", "Argument[0]", "alloc-layout", "manual"]
+ - ["lang:alloc", "::grow", "Argument[2]", "alloc-layout", "manual"]
+ - ["lang:alloc", "::grow_zeroed", "Argument[2]", "alloc-layout", "manual"]
+ - ["repo:https://github.com/rust-lang/libc:libc", "::malloc", "Argument[0]", "alloc-size", "manual"]
+ - ["repo:https://github.com/rust-lang/libc:libc", "::aligned_alloc", "Argument[1]", "alloc-size", "manual"]
+ - ["repo:https://github.com/rust-lang/libc:libc", "::calloc", "Argument[0,1]", "alloc-size", "manual"]
+ - ["repo:https://github.com/rust-lang/libc:libc", "::realloc", "Argument[1]", "alloc-size", "manual"]
diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
index a2f6b15ab2cc..710949b07e0d 100644
--- a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
+++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
@@ -19,7 +19,19 @@ extensions:
- ["lang:core", "::collect", "Argument[self].Element", "ReturnValue.Element", "value", "manual"]
- ["lang:core", "::map", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"]
- ["lang:core", "::for_each", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"]
- # ptr
+ # Layout
+ - ["lang:core", "::from_size_align", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
+ - ["lang:core", "::from_size_align_unchecked", "Argument[0]", "ReturnValue", "taint", "manual"]
+ - ["lang:core", "::array", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
+ - ["lang:core", "::repeat", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]", "taint", "manual"]
+ - ["lang:core", "::repeat", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]", "taint", "manual"]
+ - ["lang:core", "::repeat_packed", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
+ - ["lang:core", "::repeat_packed", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
+ - ["lang:core", "::extend", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]", "taint", "manual"]
+ - ["lang:core", "::extend", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]", "taint", "manual"]
+ - ["lang:core", "::extend_packed", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
+ - ["lang:core", "::extend_packed", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
+ # Ptr
- ["lang:core", "crate::ptr::read", "Argument[0].Reference", "ReturnValue", "value", "manual"]
- ["lang:core", "crate::ptr::read_unaligned", "Argument[0].Reference", "ReturnValue", "value", "manual"]
- ["lang:core", "crate::ptr::read_volatile", "Argument[0].Reference", "ReturnValue", "value", "manual"]
diff --git a/rust/ql/test/query-tests/diagnostics/SummaryStats.expected b/rust/ql/test/query-tests/diagnostics/SummaryStats.expected
index d34cd849069b..a8833f626807 100644
--- a/rust/ql/test/query-tests/diagnostics/SummaryStats.expected
+++ b/rust/ql/test/query-tests/diagnostics/SummaryStats.expected
@@ -15,7 +15,7 @@
| Macro calls - resolved | 8 |
| Macro calls - total | 9 |
| Macro calls - unresolved | 1 |
-| Taint edges - number of edges | 1674 |
+| Taint edges - number of edges | 1675 |
| Taint reach - nodes tainted | 0 |
| Taint reach - per million nodes | 0 |
| Taint sinks - cryptographic operations | 0 |
diff --git a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
index 58f42bec0c84..4dcc0f1b5583 100644
--- a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
+++ b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
@@ -1,4 +1,447 @@
#select
+| main.rs:18:13:18:31 | ...::realloc | main.rs:211:13:211:26 | ...::args | main.rs:18:13:18:31 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:21:13:21:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:21:13:21:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:24:13:24:36 | ...::alloc_zeroed | main.rs:211:13:211:26 | ...::args | main.rs:24:13:24:36 | ...::alloc_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:30:13:30:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:30:13:30:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:33:13:33:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:33:13:33:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:37:13:37:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:37:13:37:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:50:13:50:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:50:13:50:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:51:13:51:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:51:13:51:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:53:13:53:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:53:13:53:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:54:13:54:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:54:13:54:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:59:13:59:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:59:13:59:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:61:13:61:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:61:13:61:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:63:13:63:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:63:13:63:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:64:13:64:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:64:13:64:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:65:13:65:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:65:13:65:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:68:13:68:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:68:13:68:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:85:17:85:33 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:85:17:85:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:87:17:87:33 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:87:17:87:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:91:17:91:33 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:91:17:91:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:93:17:93:33 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:93:17:93:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:104:17:104:33 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:104:17:104:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:107:17:107:33 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:107:17:107:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:111:13:111:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:111:13:111:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:114:13:114:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:114:13:114:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:117:13:117:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:117:13:117:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:119:13:119:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:119:13:119:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:123:13:123:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:123:13:123:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:138:32:138:36 | alloc | main.rs:211:13:211:26 | ...::args | main.rs:138:32:138:36 | alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:139:32:139:43 | alloc_zeroed | main.rs:211:13:211:26 | ...::args | main.rs:139:32:139:43 | alloc_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:140:32:140:39 | allocate | main.rs:211:13:211:26 | ...::args | main.rs:140:32:140:39 | allocate | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:141:32:141:46 | allocate_zeroed | main.rs:211:13:211:26 | ...::args | main.rs:141:32:141:46 | allocate_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:142:32:142:39 | allocate | main.rs:211:13:211:26 | ...::args | main.rs:142:32:142:39 | allocate | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:143:32:143:46 | allocate_zeroed | main.rs:211:13:211:26 | ...::args | main.rs:143:32:143:46 | allocate_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:153:40:153:43 | grow | main.rs:211:13:211:26 | ...::args | main.rs:153:40:153:43 | grow | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:155:40:155:50 | grow_zeroed | main.rs:211:13:211:26 | ...::args | main.rs:155:40:155:50 | grow_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:164:13:164:24 | ...::malloc | main.rs:211:13:211:26 | ...::args | main.rs:164:13:164:24 | ...::malloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:164:13:164:24 | ...::malloc | main.rs:211:13:211:26 | ...::args | main.rs:164:13:164:24 | ...::malloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:165:13:165:31 | ...::aligned_alloc | main.rs:211:13:211:26 | ...::args | main.rs:165:13:165:31 | ...::aligned_alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:165:13:165:31 | ...::aligned_alloc | main.rs:211:13:211:26 | ...::args | main.rs:165:13:165:31 | ...::aligned_alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:167:13:167:24 | ...::calloc | main.rs:211:13:211:26 | ...::args | main.rs:167:13:167:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:167:13:167:24 | ...::calloc | main.rs:211:13:211:26 | ...::args | main.rs:167:13:167:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:168:13:168:24 | ...::calloc | main.rs:211:13:211:26 | ...::args | main.rs:168:13:168:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:168:13:168:24 | ...::calloc | main.rs:211:13:211:26 | ...::args | main.rs:168:13:168:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:169:13:169:25 | ...::realloc | main.rs:211:13:211:26 | ...::args | main.rs:169:13:169:25 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:169:13:169:25 | ...::realloc | main.rs:211:13:211:26 | ...::args | main.rs:169:13:169:25 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
edges
+| main.rs:12:36:12:43 | ...: usize | main.rs:18:41:18:41 | v | provenance | |
+| main.rs:18:41:18:41 | v | main.rs:18:13:18:31 | ...::realloc | provenance | MaD:5 Sink:MaD:5 |
+| main.rs:18:41:18:41 | v | main.rs:20:50:20:50 | v | provenance | |
+| main.rs:18:41:18:41 | v | main.rs:29:60:29:60 | v | provenance | |
+| main.rs:18:41:18:41 | v | main.rs:32:60:32:89 | ... * ... | provenance | |
+| main.rs:18:41:18:41 | v | main.rs:35:9:35:10 | s6 | provenance | |
+| main.rs:20:9:20:10 | l2 | main.rs:21:31:21:32 | l2 | provenance | |
+| main.rs:20:14:20:54 | ...::from_size_align(...) [Ok] | main.rs:20:14:20:63 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:20:14:20:63 | ... .unwrap(...) | main.rs:20:9:20:10 | l2 | provenance | |
+| main.rs:20:50:20:50 | v | main.rs:20:14:20:54 | ...::from_size_align(...) [Ok] | provenance | MaD:22 |
+| main.rs:21:31:21:32 | l2 | main.rs:21:13:21:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:21:31:21:32 | l2 | main.rs:24:38:24:39 | l2 | provenance | |
+| main.rs:24:38:24:39 | l2 | main.rs:24:13:24:36 | ...::alloc_zeroed | provenance | MaD:4 Sink:MaD:4 |
+| main.rs:29:9:29:10 | l4 | main.rs:30:31:30:32 | l4 | provenance | |
+| main.rs:29:14:29:64 | ...::from_size_align_unchecked(...) | main.rs:29:9:29:10 | l4 | provenance | |
+| main.rs:29:60:29:60 | v | main.rs:29:14:29:64 | ...::from_size_align_unchecked(...) | provenance | MaD:23 |
+| main.rs:30:31:30:32 | l4 | main.rs:30:13:30:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:32:9:32:10 | l5 | main.rs:33:31:33:32 | l5 | provenance | |
+| main.rs:32:14:32:118 | ...::from_size_align_unchecked(...) | main.rs:32:9:32:10 | l5 | provenance | |
+| main.rs:32:60:32:89 | ... * ... | main.rs:32:14:32:118 | ...::from_size_align_unchecked(...) | provenance | MaD:23 |
+| main.rs:33:31:33:32 | l5 | main.rs:33:13:33:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:35:9:35:10 | s6 | main.rs:36:60:36:61 | s6 | provenance | |
+| main.rs:36:9:36:10 | l6 | main.rs:37:31:37:32 | l6 | provenance | |
+| main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | main.rs:36:9:36:10 | l6 | provenance | |
+| main.rs:36:60:36:61 | s6 | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | provenance | MaD:23 |
+| main.rs:37:31:37:32 | l6 | main.rs:37:13:37:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:43:44:43:51 | ...: usize | main.rs:50:41:50:41 | v | provenance | |
+| main.rs:43:44:43:51 | ...: usize | main.rs:51:41:51:45 | ... + ... | provenance | |
+| main.rs:43:44:43:51 | ...: usize | main.rs:53:48:53:48 | v | provenance | |
+| main.rs:43:44:43:51 | ...: usize | main.rs:54:48:54:53 | ... * ... | provenance | |
+| main.rs:43:44:43:51 | ...: usize | main.rs:58:34:58:34 | v | provenance | |
+| main.rs:43:44:43:51 | ...: usize | main.rs:67:46:67:46 | v | provenance | |
+| main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | main.rs:50:31:50:51 | ... .unwrap(...) [tuple.0] | provenance | MaD:28 |
+| main.rs:50:31:50:51 | ... .unwrap(...) [tuple.0] | main.rs:50:31:50:53 | ... .0 | provenance | |
+| main.rs:50:31:50:53 | ... .0 | main.rs:50:13:50:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:50:41:50:41 | v | main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:24 |
+| main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | main.rs:51:31:51:55 | ... .unwrap(...) [tuple.0] | provenance | MaD:28 |
+| main.rs:51:31:51:55 | ... .unwrap(...) [tuple.0] | main.rs:51:31:51:57 | ... .0 | provenance | |
+| main.rs:51:31:51:57 | ... .0 | main.rs:51:13:51:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:51:41:51:45 | ... + ... | main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:24 |
+| main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | main.rs:53:31:53:58 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:53:31:53:58 | ... .unwrap(...) | main.rs:53:13:53:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:53:48:53:48 | v | main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | provenance | MaD:25 |
+| main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | main.rs:54:31:54:63 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:54:31:54:63 | ... .unwrap(...) | main.rs:54:13:54:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:54:48:54:53 | ... * ... | main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | provenance | MaD:25 |
+| main.rs:58:9:58:20 | TuplePat [tuple.0] | main.rs:58:10:58:11 | k1 | provenance | |
+| main.rs:58:10:58:11 | k1 | main.rs:59:31:59:32 | k1 | provenance | |
+| main.rs:58:24:58:35 | l3.repeat(...) [Ok, tuple.0] | main.rs:58:24:58:66 | ... .expect(...) [tuple.0] | provenance | MaD:27 |
+| main.rs:58:24:58:66 | ... .expect(...) [tuple.0] | main.rs:58:9:58:20 | TuplePat [tuple.0] | provenance | |
+| main.rs:58:34:58:34 | v | main.rs:58:24:58:35 | l3.repeat(...) [Ok, tuple.0] | provenance | MaD:24 |
+| main.rs:59:31:59:32 | k1 | main.rs:59:13:59:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:59:31:59:32 | k1 | main.rs:60:34:60:35 | k1 | provenance | |
+| main.rs:59:31:59:32 | k1 | main.rs:62:24:62:36 | k1.extend(...) [Ok, tuple.0] | provenance | MaD:19 |
+| main.rs:59:31:59:32 | k1 | main.rs:64:48:64:49 | k1 | provenance | |
+| main.rs:59:31:59:32 | k1 | main.rs:65:31:65:50 | k1.extend_packed(...) [Ok] | provenance | MaD:21 |
+| main.rs:60:9:60:20 | TuplePat [tuple.0] | main.rs:60:10:60:11 | k2 | provenance | |
+| main.rs:60:10:60:11 | k2 | main.rs:61:31:61:32 | k2 | provenance | |
+| main.rs:60:24:60:36 | l3.extend(...) [Ok, tuple.0] | main.rs:60:24:60:45 | ... .unwrap(...) [tuple.0] | provenance | MaD:28 |
+| main.rs:60:24:60:45 | ... .unwrap(...) [tuple.0] | main.rs:60:9:60:20 | TuplePat [tuple.0] | provenance | |
+| main.rs:60:34:60:35 | k1 | main.rs:60:24:60:36 | l3.extend(...) [Ok, tuple.0] | provenance | MaD:18 |
+| main.rs:61:31:61:32 | k2 | main.rs:61:13:61:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:62:9:62:20 | TuplePat [tuple.0] | main.rs:62:10:62:11 | k3 | provenance | |
+| main.rs:62:10:62:11 | k3 | main.rs:63:31:63:32 | k3 | provenance | |
+| main.rs:62:24:62:36 | k1.extend(...) [Ok, tuple.0] | main.rs:62:24:62:45 | ... .unwrap(...) [tuple.0] | provenance | MaD:28 |
+| main.rs:62:24:62:45 | ... .unwrap(...) [tuple.0] | main.rs:62:9:62:20 | TuplePat [tuple.0] | provenance | |
+| main.rs:63:31:63:32 | k3 | main.rs:63:13:63:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | main.rs:64:31:64:59 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:64:31:64:59 | ... .unwrap(...) | main.rs:64:13:64:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:64:48:64:49 | k1 | main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | provenance | MaD:20 |
+| main.rs:65:31:65:50 | k1.extend_packed(...) [Ok] | main.rs:65:31:65:59 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:65:31:65:59 | ... .unwrap(...) | main.rs:65:13:65:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:67:9:67:10 | l4 | main.rs:68:31:68:32 | l4 | provenance | |
+| main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | main.rs:67:14:67:56 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:67:14:67:56 | ... .unwrap(...) | main.rs:67:9:67:10 | l4 | provenance | |
+| main.rs:67:46:67:46 | v | main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | provenance | MaD:17 |
+| main.rs:68:31:68:32 | l4 | main.rs:68:13:68:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:71:35:71:38 | ...: T | main.rs:77:9:77:16 | return v | provenance | |
+| main.rs:81:38:81:45 | ...: usize | main.rs:82:47:82:47 | v | provenance | |
+| main.rs:81:38:81:45 | ...: usize | main.rs:97:13:97:21 | mut v_mut | provenance | |
+| main.rs:81:38:81:45 | ...: usize | main.rs:106:51:106:51 | v | provenance | |
+| main.rs:81:38:81:45 | ...: usize | main.rs:110:61:110:61 | v | provenance | |
+| main.rs:81:38:81:45 | ...: usize | main.rs:113:61:113:61 | v | provenance | |
+| main.rs:81:38:81:45 | ...: usize | main.rs:116:53:116:53 | v | provenance | |
+| main.rs:82:9:82:10 | l1 | main.rs:85:35:85:36 | l1 | provenance | |
+| main.rs:82:9:82:10 | l1 | main.rs:87:35:87:36 | l1 | provenance | |
+| main.rs:82:14:82:48 | ...::array::<...>(...) [Ok] | main.rs:82:14:82:57 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:82:14:82:57 | ... .unwrap(...) | main.rs:82:9:82:10 | l1 | provenance | |
+| main.rs:82:47:82:47 | v | main.rs:82:14:82:48 | ...::array::<...>(...) [Ok] | provenance | MaD:17 |
+| main.rs:85:35:85:36 | l1 | main.rs:85:17:85:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:85:35:85:36 | l1 | main.rs:91:35:91:36 | l1 | provenance | |
+| main.rs:85:35:85:36 | l1 | main.rs:93:35:93:36 | l1 | provenance | |
+| main.rs:87:35:87:36 | l1 | main.rs:87:17:87:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:87:35:87:36 | l1 | main.rs:91:35:91:36 | l1 | provenance | |
+| main.rs:87:35:87:36 | l1 | main.rs:93:35:93:36 | l1 | provenance | |
+| main.rs:91:35:91:36 | l1 | main.rs:91:17:91:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:91:35:91:36 | l1 | main.rs:119:31:119:32 | l1 | provenance | |
+| main.rs:93:35:93:36 | l1 | main.rs:93:17:93:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:93:35:93:36 | l1 | main.rs:119:31:119:32 | l1 | provenance | |
+| main.rs:97:13:97:21 | mut v_mut | main.rs:103:51:103:55 | v_mut | provenance | |
+| main.rs:103:13:103:14 | l2 | main.rs:104:35:104:36 | l2 | provenance | |
+| main.rs:103:18:103:56 | ...::array::<...>(...) [Ok] | main.rs:103:18:103:65 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:103:18:103:65 | ... .unwrap(...) | main.rs:103:13:103:14 | l2 | provenance | |
+| main.rs:103:51:103:55 | v_mut | main.rs:103:18:103:56 | ...::array::<...>(...) [Ok] | provenance | MaD:17 |
+| main.rs:104:35:104:36 | l2 | main.rs:104:17:104:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:106:13:106:14 | l3 | main.rs:107:35:107:36 | l3 | provenance | |
+| main.rs:106:18:106:52 | ...::array::<...>(...) [Ok] | main.rs:106:18:106:61 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:106:18:106:61 | ... .unwrap(...) | main.rs:106:13:106:14 | l3 | provenance | |
+| main.rs:106:51:106:51 | v | main.rs:106:18:106:52 | ...::array::<...>(...) [Ok] | provenance | MaD:17 |
+| main.rs:107:35:107:36 | l3 | main.rs:107:17:107:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:110:9:110:10 | l4 | main.rs:111:31:111:32 | l4 | provenance | |
+| main.rs:110:14:110:68 | ...::array::<...>(...) [Ok] | main.rs:110:14:110:77 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:110:14:110:77 | ... .unwrap(...) | main.rs:110:9:110:10 | l4 | provenance | |
+| main.rs:110:47:110:67 | ...::min(...) | main.rs:110:14:110:68 | ...::array::<...>(...) [Ok] | provenance | MaD:17 |
+| main.rs:110:61:110:61 | v | main.rs:110:47:110:67 | ...::min(...) | provenance | MaD:31 |
+| main.rs:111:31:111:32 | l4 | main.rs:111:13:111:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:113:9:113:10 | l5 | main.rs:114:31:114:32 | l5 | provenance | |
+| main.rs:113:14:113:68 | ...::array::<...>(...) [Ok] | main.rs:113:14:113:77 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:113:14:113:77 | ... .unwrap(...) | main.rs:113:9:113:10 | l5 | provenance | |
+| main.rs:113:47:113:67 | ...::max(...) | main.rs:113:14:113:68 | ...::array::<...>(...) [Ok] | provenance | MaD:17 |
+| main.rs:113:61:113:61 | v | main.rs:113:47:113:67 | ...::max(...) | provenance | MaD:30 |
+| main.rs:114:31:114:32 | l5 | main.rs:114:13:114:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:116:9:116:10 | l6 | main.rs:117:31:117:32 | l6 | provenance | |
+| main.rs:116:14:116:63 | ...::array::<...>(...) [Ok] | main.rs:116:14:116:72 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:116:14:116:72 | ... .unwrap(...) | main.rs:116:9:116:10 | l6 | provenance | |
+| main.rs:116:47:116:62 | clamp(...) | main.rs:116:14:116:63 | ...::array::<...>(...) [Ok] | provenance | MaD:17 |
+| main.rs:116:53:116:53 | v | main.rs:71:35:71:38 | ...: T | provenance | |
+| main.rs:116:53:116:53 | v | main.rs:116:47:116:62 | clamp(...) | provenance | |
+| main.rs:117:31:117:32 | l6 | main.rs:117:13:117:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:119:31:119:32 | l1 | main.rs:119:13:119:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:119:31:119:32 | l1 | main.rs:123:31:123:32 | l1 | provenance | |
+| main.rs:123:31:123:32 | l1 | main.rs:123:13:123:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:128:29:128:36 | ...: usize | main.rs:137:46:137:46 | v | provenance | |
+| main.rs:137:9:137:10 | l2 | main.rs:138:38:138:39 | l2 | provenance | |
+| main.rs:137:14:137:47 | ...::array::<...>(...) [Ok] | main.rs:137:14:137:56 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:137:14:137:56 | ... .unwrap(...) | main.rs:137:9:137:10 | l2 | provenance | |
+| main.rs:137:46:137:46 | v | main.rs:137:14:137:47 | ...::array::<...>(...) [Ok] | provenance | MaD:17 |
+| main.rs:138:38:138:39 | l2 | main.rs:138:32:138:36 | alloc | provenance | MaD:10 Sink:MaD:10 |
+| main.rs:138:38:138:39 | l2 | main.rs:139:45:139:46 | l2 | provenance | |
+| main.rs:139:45:139:46 | l2 | main.rs:139:32:139:43 | alloc_zeroed | provenance | MaD:11 Sink:MaD:11 |
+| main.rs:139:45:139:46 | l2 | main.rs:140:41:140:42 | l2 | provenance | |
+| main.rs:140:41:140:42 | l2 | main.rs:140:32:140:39 | allocate | provenance | MaD:6 Sink:MaD:6 |
+| main.rs:140:41:140:42 | l2 | main.rs:141:48:141:49 | l2 | provenance | |
+| main.rs:141:48:141:49 | l2 | main.rs:141:32:141:46 | allocate_zeroed | provenance | MaD:7 Sink:MaD:7 |
+| main.rs:141:48:141:49 | l2 | main.rs:142:41:142:42 | l2 | provenance | |
+| main.rs:142:41:142:42 | l2 | main.rs:142:32:142:39 | allocate | provenance | MaD:1 Sink:MaD:1 |
+| main.rs:142:41:142:42 | l2 | main.rs:143:48:143:49 | l2 | provenance | |
+| main.rs:143:48:143:49 | l2 | main.rs:143:32:143:46 | allocate_zeroed | provenance | MaD:2 Sink:MaD:2 |
+| main.rs:143:48:143:49 | l2 | main.rs:153:53:153:54 | l2 | provenance | |
+| main.rs:143:48:143:49 | l2 | main.rs:155:60:155:61 | l2 | provenance | |
+| main.rs:153:53:153:54 | l2 | main.rs:153:40:153:43 | grow | provenance | MaD:8 Sink:MaD:8 |
+| main.rs:155:60:155:61 | l2 | main.rs:155:40:155:50 | grow_zeroed | provenance | MaD:9 Sink:MaD:9 |
+| main.rs:162:27:162:34 | ...: usize | main.rs:164:26:164:26 | v | provenance | |
+| main.rs:164:26:164:26 | v | main.rs:164:13:164:24 | ...::malloc | provenance | MaD:14 Sink:MaD:14 |
+| main.rs:164:26:164:26 | v | main.rs:164:13:164:24 | ...::malloc | provenance | MaD:14 Sink:MaD:14 |
+| main.rs:164:26:164:26 | v | main.rs:165:36:165:36 | v | provenance | |
+| main.rs:165:36:165:36 | v | main.rs:165:13:165:31 | ...::aligned_alloc | provenance | MaD:12 Sink:MaD:12 |
+| main.rs:165:36:165:36 | v | main.rs:165:13:165:31 | ...::aligned_alloc | provenance | MaD:12 Sink:MaD:12 |
+| main.rs:165:36:165:36 | v | main.rs:167:30:167:30 | v | provenance | |
+| main.rs:167:30:167:30 | v | main.rs:167:13:167:24 | ...::calloc | provenance | MaD:13 Sink:MaD:13 |
+| main.rs:167:30:167:30 | v | main.rs:167:13:167:24 | ...::calloc | provenance | MaD:13 Sink:MaD:13 |
+| main.rs:167:30:167:30 | v | main.rs:168:26:168:26 | v | provenance | |
+| main.rs:168:26:168:26 | v | main.rs:168:13:168:24 | ...::calloc | provenance | MaD:13 Sink:MaD:13 |
+| main.rs:168:26:168:26 | v | main.rs:168:13:168:24 | ...::calloc | provenance | MaD:13 Sink:MaD:13 |
+| main.rs:168:26:168:26 | v | main.rs:169:31:169:31 | v | provenance | |
+| main.rs:169:31:169:31 | v | main.rs:169:13:169:25 | ...::realloc | provenance | MaD:15 Sink:MaD:15 |
+| main.rs:169:31:169:31 | v | main.rs:169:13:169:25 | ...::realloc | provenance | MaD:15 Sink:MaD:15 |
+| main.rs:211:9:211:9 | v | main.rs:214:34:214:34 | v | provenance | |
+| main.rs:211:9:211:9 | v | main.rs:215:42:215:42 | v | provenance | |
+| main.rs:211:9:211:9 | v | main.rs:216:36:216:36 | v | provenance | |
+| main.rs:211:9:211:9 | v | main.rs:217:27:217:27 | v | provenance | |
+| main.rs:211:9:211:9 | v | main.rs:218:25:218:25 | v | provenance | |
+| main.rs:211:13:211:26 | ...::args | main.rs:211:13:211:28 | ...::args(...) [element] | provenance | Src:MaD:16 |
+| main.rs:211:13:211:28 | ...::args(...) [element] | main.rs:211:13:211:35 | ... .nth(...) [Some] | provenance | MaD:32 |
+| main.rs:211:13:211:35 | ... .nth(...) [Some] | main.rs:211:13:211:65 | ... .unwrap_or(...) | provenance | MaD:26 |
+| main.rs:211:13:211:65 | ... .unwrap_or(...) | main.rs:211:13:211:82 | ... .parse(...) [Ok] | provenance | MaD:29 |
+| main.rs:211:13:211:82 | ... .parse(...) [Ok] | main.rs:211:13:211:91 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:211:13:211:91 | ... .unwrap(...) | main.rs:211:9:211:9 | v | provenance | |
+| main.rs:214:34:214:34 | v | main.rs:12:36:12:43 | ...: usize | provenance | |
+| main.rs:215:42:215:42 | v | main.rs:43:44:43:51 | ...: usize | provenance | |
+| main.rs:216:36:216:36 | v | main.rs:81:38:81:45 | ...: usize | provenance | |
+| main.rs:217:27:217:27 | v | main.rs:128:29:128:36 | ...: usize | provenance | |
+| main.rs:218:25:218:25 | v | main.rs:162:27:162:34 | ...: usize | provenance | |
+models
+| 1 | Sink: lang:alloc; ::allocate; alloc-layout; Argument[0] |
+| 2 | Sink: lang:alloc; ::allocate_zeroed; alloc-layout; Argument[0] |
+| 3 | Sink: lang:alloc; crate::alloc::alloc; alloc-layout; Argument[0] |
+| 4 | Sink: lang:alloc; crate::alloc::alloc_zeroed; alloc-layout; Argument[0] |
+| 5 | Sink: lang:alloc; crate::alloc::realloc; alloc-size; Argument[2] |
+| 6 | Sink: lang:std; ::allocate; alloc-layout; Argument[0] |
+| 7 | Sink: lang:std; ::allocate_zeroed; alloc-layout; Argument[0] |
+| 8 | Sink: lang:std; ::grow; alloc-layout; Argument[2] |
+| 9 | Sink: lang:std; ::grow_zeroed; alloc-layout; Argument[2] |
+| 10 | Sink: lang:std; ::alloc; alloc-layout; Argument[0] |
+| 11 | Sink: lang:std; ::alloc_zeroed; alloc-layout; Argument[0] |
+| 12 | Sink: repo:https://github.com/rust-lang/libc:libc; ::aligned_alloc; alloc-size; Argument[1] |
+| 13 | Sink: repo:https://github.com/rust-lang/libc:libc; ::calloc; alloc-size; Argument[0,1] |
+| 14 | Sink: repo:https://github.com/rust-lang/libc:libc; ::malloc; alloc-size; Argument[0] |
+| 15 | Sink: repo:https://github.com/rust-lang/libc:libc; ::realloc; alloc-size; Argument[1] |
+| 16 | Source: lang:std; crate::env::args; command-line-source; ReturnValue.Element |
+| 17 | Summary: lang:core; ::array; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
+| 18 | Summary: lang:core; ::extend; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]; taint |
+| 19 | Summary: lang:core; ::extend; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]; taint |
+| 20 | Summary: lang:core; ::extend_packed; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
+| 21 | Summary: lang:core; ::extend_packed; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
+| 22 | Summary: lang:core; ::from_size_align; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
+| 23 | Summary: lang:core; ::from_size_align_unchecked; Argument[0]; ReturnValue; taint |
+| 24 | Summary: lang:core; ::repeat; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]; taint |
+| 25 | Summary: lang:core; ::repeat_packed; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
+| 26 | Summary: lang:core; ::unwrap_or; Argument[self].Field[crate::option::Option::Some(0)]; ReturnValue; value |
+| 27 | Summary: lang:core; ::expect; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value |
+| 28 | Summary: lang:core; ::unwrap; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value |
+| 29 | Summary: lang:core; ::parse; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
+| 30 | Summary: lang:core; crate::cmp::max; Argument[0]; ReturnValue; value |
+| 31 | Summary: lang:core; crate::cmp::min; Argument[0]; ReturnValue; value |
+| 32 | Summary: lang:core; crate::iter::traits::iterator::Iterator::nth; Argument[self].Element; ReturnValue.Field[crate::option::Option::Some(0)]; value |
nodes
+| main.rs:12:36:12:43 | ...: usize | semmle.label | ...: usize |
+| main.rs:18:13:18:31 | ...::realloc | semmle.label | ...::realloc |
+| main.rs:18:41:18:41 | v | semmle.label | v |
+| main.rs:20:9:20:10 | l2 | semmle.label | l2 |
+| main.rs:20:14:20:54 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
+| main.rs:20:14:20:63 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:20:50:20:50 | v | semmle.label | v |
+| main.rs:21:13:21:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:21:31:21:32 | l2 | semmle.label | l2 |
+| main.rs:24:13:24:36 | ...::alloc_zeroed | semmle.label | ...::alloc_zeroed |
+| main.rs:24:38:24:39 | l2 | semmle.label | l2 |
+| main.rs:29:9:29:10 | l4 | semmle.label | l4 |
+| main.rs:29:14:29:64 | ...::from_size_align_unchecked(...) | semmle.label | ...::from_size_align_unchecked(...) |
+| main.rs:29:60:29:60 | v | semmle.label | v |
+| main.rs:30:13:30:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:30:31:30:32 | l4 | semmle.label | l4 |
+| main.rs:32:9:32:10 | l5 | semmle.label | l5 |
+| main.rs:32:14:32:118 | ...::from_size_align_unchecked(...) | semmle.label | ...::from_size_align_unchecked(...) |
+| main.rs:32:60:32:89 | ... * ... | semmle.label | ... * ... |
+| main.rs:33:13:33:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:33:31:33:32 | l5 | semmle.label | l5 |
+| main.rs:35:9:35:10 | s6 | semmle.label | s6 |
+| main.rs:36:9:36:10 | l6 | semmle.label | l6 |
+| main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | semmle.label | ...::from_size_align_unchecked(...) |
+| main.rs:36:60:36:61 | s6 | semmle.label | s6 |
+| main.rs:37:13:37:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:37:31:37:32 | l6 | semmle.label | l6 |
+| main.rs:43:44:43:51 | ...: usize | semmle.label | ...: usize |
+| main.rs:50:13:50:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | semmle.label | l2.repeat(...) [Ok, tuple.0] |
+| main.rs:50:31:50:51 | ... .unwrap(...) [tuple.0] | semmle.label | ... .unwrap(...) [tuple.0] |
+| main.rs:50:31:50:53 | ... .0 | semmle.label | ... .0 |
+| main.rs:50:41:50:41 | v | semmle.label | v |
+| main.rs:51:13:51:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | semmle.label | l2.repeat(...) [Ok, tuple.0] |
+| main.rs:51:31:51:55 | ... .unwrap(...) [tuple.0] | semmle.label | ... .unwrap(...) [tuple.0] |
+| main.rs:51:31:51:57 | ... .0 | semmle.label | ... .0 |
+| main.rs:51:41:51:45 | ... + ... | semmle.label | ... + ... |
+| main.rs:53:13:53:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | semmle.label | l2.repeat_packed(...) [Ok] |
+| main.rs:53:31:53:58 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:53:48:53:48 | v | semmle.label | v |
+| main.rs:54:13:54:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | semmle.label | l2.repeat_packed(...) [Ok] |
+| main.rs:54:31:54:63 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:54:48:54:53 | ... * ... | semmle.label | ... * ... |
+| main.rs:58:9:58:20 | TuplePat [tuple.0] | semmle.label | TuplePat [tuple.0] |
+| main.rs:58:10:58:11 | k1 | semmle.label | k1 |
+| main.rs:58:24:58:35 | l3.repeat(...) [Ok, tuple.0] | semmle.label | l3.repeat(...) [Ok, tuple.0] |
+| main.rs:58:24:58:66 | ... .expect(...) [tuple.0] | semmle.label | ... .expect(...) [tuple.0] |
+| main.rs:58:34:58:34 | v | semmle.label | v |
+| main.rs:59:13:59:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:59:31:59:32 | k1 | semmle.label | k1 |
+| main.rs:60:9:60:20 | TuplePat [tuple.0] | semmle.label | TuplePat [tuple.0] |
+| main.rs:60:10:60:11 | k2 | semmle.label | k2 |
+| main.rs:60:24:60:36 | l3.extend(...) [Ok, tuple.0] | semmle.label | l3.extend(...) [Ok, tuple.0] |
+| main.rs:60:24:60:45 | ... .unwrap(...) [tuple.0] | semmle.label | ... .unwrap(...) [tuple.0] |
+| main.rs:60:34:60:35 | k1 | semmle.label | k1 |
+| main.rs:61:13:61:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:61:31:61:32 | k2 | semmle.label | k2 |
+| main.rs:62:9:62:20 | TuplePat [tuple.0] | semmle.label | TuplePat [tuple.0] |
+| main.rs:62:10:62:11 | k3 | semmle.label | k3 |
+| main.rs:62:24:62:36 | k1.extend(...) [Ok, tuple.0] | semmle.label | k1.extend(...) [Ok, tuple.0] |
+| main.rs:62:24:62:45 | ... .unwrap(...) [tuple.0] | semmle.label | ... .unwrap(...) [tuple.0] |
+| main.rs:63:13:63:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:63:31:63:32 | k3 | semmle.label | k3 |
+| main.rs:64:13:64:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | semmle.label | l3.extend_packed(...) [Ok] |
+| main.rs:64:31:64:59 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:64:48:64:49 | k1 | semmle.label | k1 |
+| main.rs:65:13:65:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:65:31:65:50 | k1.extend_packed(...) [Ok] | semmle.label | k1.extend_packed(...) [Ok] |
+| main.rs:65:31:65:59 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:67:9:67:10 | l4 | semmle.label | l4 |
+| main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:67:14:67:56 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:67:46:67:46 | v | semmle.label | v |
+| main.rs:68:13:68:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:68:31:68:32 | l4 | semmle.label | l4 |
+| main.rs:71:35:71:38 | ...: T | semmle.label | ...: T |
+| main.rs:77:9:77:16 | return v | semmle.label | return v |
+| main.rs:81:38:81:45 | ...: usize | semmle.label | ...: usize |
+| main.rs:82:9:82:10 | l1 | semmle.label | l1 |
+| main.rs:82:14:82:48 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:82:14:82:57 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:82:47:82:47 | v | semmle.label | v |
+| main.rs:85:17:85:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:85:35:85:36 | l1 | semmle.label | l1 |
+| main.rs:87:17:87:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:87:35:87:36 | l1 | semmle.label | l1 |
+| main.rs:91:17:91:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:91:35:91:36 | l1 | semmle.label | l1 |
+| main.rs:93:17:93:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:93:35:93:36 | l1 | semmle.label | l1 |
+| main.rs:97:13:97:21 | mut v_mut | semmle.label | mut v_mut |
+| main.rs:103:13:103:14 | l2 | semmle.label | l2 |
+| main.rs:103:18:103:56 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:103:18:103:65 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:103:51:103:55 | v_mut | semmle.label | v_mut |
+| main.rs:104:17:104:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:104:35:104:36 | l2 | semmle.label | l2 |
+| main.rs:106:13:106:14 | l3 | semmle.label | l3 |
+| main.rs:106:18:106:52 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:106:18:106:61 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:106:51:106:51 | v | semmle.label | v |
+| main.rs:107:17:107:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:107:35:107:36 | l3 | semmle.label | l3 |
+| main.rs:110:9:110:10 | l4 | semmle.label | l4 |
+| main.rs:110:14:110:68 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:110:14:110:77 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:110:47:110:67 | ...::min(...) | semmle.label | ...::min(...) |
+| main.rs:110:61:110:61 | v | semmle.label | v |
+| main.rs:111:13:111:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:111:31:111:32 | l4 | semmle.label | l4 |
+| main.rs:113:9:113:10 | l5 | semmle.label | l5 |
+| main.rs:113:14:113:68 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:113:14:113:77 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:113:47:113:67 | ...::max(...) | semmle.label | ...::max(...) |
+| main.rs:113:61:113:61 | v | semmle.label | v |
+| main.rs:114:13:114:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:114:31:114:32 | l5 | semmle.label | l5 |
+| main.rs:116:9:116:10 | l6 | semmle.label | l6 |
+| main.rs:116:14:116:63 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:116:14:116:72 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:116:47:116:62 | clamp(...) | semmle.label | clamp(...) |
+| main.rs:116:53:116:53 | v | semmle.label | v |
+| main.rs:117:13:117:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:117:31:117:32 | l6 | semmle.label | l6 |
+| main.rs:119:13:119:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:119:31:119:32 | l1 | semmle.label | l1 |
+| main.rs:123:13:123:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:123:31:123:32 | l1 | semmle.label | l1 |
+| main.rs:128:29:128:36 | ...: usize | semmle.label | ...: usize |
+| main.rs:137:9:137:10 | l2 | semmle.label | l2 |
+| main.rs:137:14:137:47 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:137:14:137:56 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:137:46:137:46 | v | semmle.label | v |
+| main.rs:138:32:138:36 | alloc | semmle.label | alloc |
+| main.rs:138:38:138:39 | l2 | semmle.label | l2 |
+| main.rs:139:32:139:43 | alloc_zeroed | semmle.label | alloc_zeroed |
+| main.rs:139:45:139:46 | l2 | semmle.label | l2 |
+| main.rs:140:32:140:39 | allocate | semmle.label | allocate |
+| main.rs:140:41:140:42 | l2 | semmle.label | l2 |
+| main.rs:141:32:141:46 | allocate_zeroed | semmle.label | allocate_zeroed |
+| main.rs:141:48:141:49 | l2 | semmle.label | l2 |
+| main.rs:142:32:142:39 | allocate | semmle.label | allocate |
+| main.rs:142:41:142:42 | l2 | semmle.label | l2 |
+| main.rs:143:32:143:46 | allocate_zeroed | semmle.label | allocate_zeroed |
+| main.rs:143:48:143:49 | l2 | semmle.label | l2 |
+| main.rs:153:40:153:43 | grow | semmle.label | grow |
+| main.rs:153:53:153:54 | l2 | semmle.label | l2 |
+| main.rs:155:40:155:50 | grow_zeroed | semmle.label | grow_zeroed |
+| main.rs:155:60:155:61 | l2 | semmle.label | l2 |
+| main.rs:162:27:162:34 | ...: usize | semmle.label | ...: usize |
+| main.rs:164:13:164:24 | ...::malloc | semmle.label | ...::malloc |
+| main.rs:164:13:164:24 | ...::malloc | semmle.label | ...::malloc |
+| main.rs:164:26:164:26 | v | semmle.label | v |
+| main.rs:165:13:165:31 | ...::aligned_alloc | semmle.label | ...::aligned_alloc |
+| main.rs:165:13:165:31 | ...::aligned_alloc | semmle.label | ...::aligned_alloc |
+| main.rs:165:36:165:36 | v | semmle.label | v |
+| main.rs:167:13:167:24 | ...::calloc | semmle.label | ...::calloc |
+| main.rs:167:13:167:24 | ...::calloc | semmle.label | ...::calloc |
+| main.rs:167:30:167:30 | v | semmle.label | v |
+| main.rs:168:13:168:24 | ...::calloc | semmle.label | ...::calloc |
+| main.rs:168:13:168:24 | ...::calloc | semmle.label | ...::calloc |
+| main.rs:168:26:168:26 | v | semmle.label | v |
+| main.rs:169:13:169:25 | ...::realloc | semmle.label | ...::realloc |
+| main.rs:169:13:169:25 | ...::realloc | semmle.label | ...::realloc |
+| main.rs:169:31:169:31 | v | semmle.label | v |
+| main.rs:211:9:211:9 | v | semmle.label | v |
+| main.rs:211:13:211:26 | ...::args | semmle.label | ...::args |
+| main.rs:211:13:211:28 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
+| main.rs:211:13:211:35 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
+| main.rs:211:13:211:65 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
+| main.rs:211:13:211:82 | ... .parse(...) [Ok] | semmle.label | ... .parse(...) [Ok] |
+| main.rs:211:13:211:91 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:214:34:214:34 | v | semmle.label | v |
+| main.rs:215:42:215:42 | v | semmle.label | v |
+| main.rs:216:36:216:36 | v | semmle.label | v |
+| main.rs:217:27:217:27 | v | semmle.label | v |
+| main.rs:218:25:218:25 | v | semmle.label | v |
subpaths
+| main.rs:116:53:116:53 | v | main.rs:71:35:71:38 | ...: T | main.rs:77:9:77:16 | return v | main.rs:116:47:116:62 | clamp(...) |
diff --git a/rust/ql/test/query-tests/security/CWE-770/main.rs b/rust/ql/test/query-tests/security/CWE-770/main.rs
index c2a1eb111c33..0af7d0eb5360 100644
--- a/rust/ql/test/query-tests/security/CWE-770/main.rs
+++ b/rust/ql/test/query-tests/security/CWE-770/main.rs
@@ -15,26 +15,26 @@ unsafe fn test_std_alloc_from_size(v: usize) {
let _ = std::alloc::alloc(l1.align_to(8).unwrap());
let _ = std::alloc::alloc(l1.align_to(8).unwrap().pad_to_align());
let _ = std::alloc::alloc_zeroed(l1);
- let _ = std::alloc::realloc(m1, l1, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::realloc(m1, l1, v); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l2 = std::alloc::Layout::from_size_align(v, 1).unwrap();
- let _ = std::alloc::alloc(l2); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l2); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::alloc(l2.align_to(8).unwrap()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
let _ = std::alloc::alloc(l2.align_to(8).unwrap().pad_to_align()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
- let _ = std::alloc::alloc_zeroed(l2); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc_zeroed(l2); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l3 = std::alloc::Layout::from_size_align(1, v).unwrap(); // not obviously dangerous?
let _ = std::alloc::alloc(l3);
let l4 = std::alloc::Layout::from_size_align_unchecked(v, 1);
- let _ = std::alloc::alloc(l4); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l4); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l5 = std::alloc::Layout::from_size_align_unchecked(v * std::mem::size_of::(), std::mem::size_of::());
- let _ = std::alloc::alloc(l5); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l5); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let s6 = (std::mem::size_of::() * v) + 1;
let l6 = std::alloc::Layout::from_size_align_unchecked(s6, 4);
- let _ = std::alloc::alloc(l6); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l6); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l7 = std::alloc::Layout::from_size_align_unchecked(l6.size(), 8);
let _ = std::alloc::alloc(l7); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
@@ -47,25 +47,25 @@ unsafe fn test_std_alloc_new_repeat_extend(v: usize) {
let l2 = std::alloc::Layout::new::();
let _ = std::alloc::alloc(l2);
let _ = std::alloc::alloc(l2.repeat(10).unwrap().0);
- let _ = std::alloc::alloc(l2.repeat(v).unwrap().0); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
- let _ = std::alloc::alloc(l2.repeat(v + 1).unwrap().0); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l2.repeat(v).unwrap().0); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(l2.repeat(v + 1).unwrap().0); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::alloc(l2.repeat_packed(10).unwrap());
- let _ = std::alloc::alloc(l2.repeat_packed(v).unwrap()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
- let _ = std::alloc::alloc(l2.repeat_packed(v * 10).unwrap()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l2.repeat_packed(v).unwrap()); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(l2.repeat_packed(v * 10).unwrap()); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l3 = std::alloc::Layout::array::(10).unwrap();
let _ = std::alloc::alloc(l3);
let (k1, _offs1) = l3.repeat(v).expect("arithmetic overflow?");
- let _ = std::alloc::alloc(k1); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(k1); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let (k2, _offs2) = l3.extend(k1).unwrap();
- let _ = std::alloc::alloc(k2); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(k2); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let (k3, _offs3) = k1.extend(l3).unwrap();
- let _ = std::alloc::alloc(k3); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
- let _ = std::alloc::alloc(l3.extend_packed(k1).unwrap()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
- let _ = std::alloc::alloc(k1.extend_packed(l3).unwrap()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(k3); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(l3.extend_packed(k1).unwrap()); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(k1.extend_packed(l3).unwrap()); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l4 = std::alloc::Layout::array::(v).unwrap();
- let _ = std::alloc::alloc(l4); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l4); // $ Alert[rust/uncontrolled-allocation-size]=arg1
}
fn clamp(v: T, min: T, max: T) -> T {
@@ -82,15 +82,15 @@ unsafe fn test_std_alloc_with_bounds(v: usize) {
let l1 = std::alloc::Layout::array::(v).unwrap();
if v < 100 {
- let _ = std::alloc::alloc(l1);
+ let _ = std::alloc::alloc(l1); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
} else {
- let _ = std::alloc::alloc(l1); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l1); // $ Alert[rust/uncontrolled-allocation-size]=arg1
}
if v == 100 {
- let _ = std::alloc::alloc(l1);
+ let _ = std::alloc::alloc(l1); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
} else {
- let _ = std::alloc::alloc(l1); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l1); // $ Alert[rust/uncontrolled-allocation-size]=arg1
}
{
@@ -101,26 +101,26 @@ unsafe fn test_std_alloc_with_bounds(v: usize) {
}
let l2 = std::alloc::Layout::array::(v_mut).unwrap();
- let _ = std::alloc::alloc(l2);
+ let _ = std::alloc::alloc(l2); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
let l3 = std::alloc::Layout::array::(v).unwrap();
- let _ = std::alloc::alloc(l3); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l3); // $ Alert[rust/uncontrolled-allocation-size]=arg1
}
let l4 = std::alloc::Layout::array::(std::cmp::min(v, 100)).unwrap();
- let _ = std::alloc::alloc(l4);
+ let _ = std::alloc::alloc(l4); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
let l5 = std::alloc::Layout::array::(std::cmp::max(v, 100)).unwrap();
- let _ = std::alloc::alloc(l5); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l5); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l6 = std::alloc::Layout::array::(clamp(v, 1, 100)).unwrap();
- let _ = std::alloc::alloc(l6);
+ let _ = std::alloc::alloc(l6); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
- let _ = std::alloc::alloc(l1); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l1); // $ Alert[rust/uncontrolled-allocation-size]=arg1
if v > 100 {
return;
}
- let _ = std::alloc::alloc(l1);
+ let _ = std::alloc::alloc(l1); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
}
use std::alloc::{GlobalAlloc, Allocator};
@@ -135,12 +135,12 @@ unsafe fn test_system_alloc(v: usize) {
let _ = std::alloc::Global.allocate_zeroed(l1).unwrap();
let l2 = std::alloc::Layout::array::(v).unwrap();
- let _ = std::alloc::System.alloc(l2); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
- let _ = std::alloc::System.alloc_zeroed(l2); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
- let _ = std::alloc::System.allocate(l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
- let _ = std::alloc::System.allocate_zeroed(l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
- let _ = std::alloc::Global.allocate(l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
- let _ = std::alloc::Global.allocate_zeroed(l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::System.alloc(l2); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::System.alloc_zeroed(l2); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::System.allocate(l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::System.allocate_zeroed(l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::Global.allocate(l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::Global.allocate_zeroed(l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l3 = std::alloc::Layout::array::(10).unwrap();
let m3 = std::alloc::System.alloc(l3);
@@ -150,9 +150,9 @@ unsafe fn test_system_alloc(v: usize) {
let m4 = std::ptr::NonNull::::new(std::alloc::alloc(l4)).unwrap();
if v > 10 {
if v % 2 == 0 {
- let _ = std::alloc::System.grow(m4, l4, l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::System.grow(m4, l4, l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1
} else {
- let _ = std::alloc::System.grow_zeroed(m4, l4, l2).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::System.grow_zeroed(m4, l4, l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1
}
} else {
let _ = std::alloc::System.shrink(m4, l4, l2).unwrap();
@@ -161,12 +161,12 @@ unsafe fn test_system_alloc(v: usize) {
unsafe fn test_libc_alloc(v: usize) {
let m1 = libc::malloc(256);
- let _ = libc::malloc(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
- let _ = libc::aligned_alloc(8, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = libc::malloc(v); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = libc::aligned_alloc(8, v); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = libc::aligned_alloc(v, 8);
- let _ = libc::calloc(64, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
- let _ = libc::calloc(v, std::mem::size_of::()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
- let _ = libc::realloc(m1, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = libc::calloc(64, v); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = libc::calloc(v, std::mem::size_of::()); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = libc::realloc(m1, v); // $ Alert[rust/uncontrolled-allocation-size]=arg1
}
unsafe fn test_vectors(v: usize) {
From e49c1afe72c249e32abd4740fcc0bb43c37648c0 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 31 Mar 2025 10:08:32 +0100
Subject: [PATCH 083/409] Rust: Add a few missing models.
---
.../frameworks/stdlib/lang-core.model.yml | 3 +
.../diagnostics/SummaryStats.expected | 2 +-
.../UncontrolledAllocationSize.expected | 152 +++++++++++-------
.../test/query-tests/security/CWE-770/main.rs | 6 +-
4 files changed, 98 insertions(+), 65 deletions(-)
diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
index 710949b07e0d..1f840626b3f1 100644
--- a/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
+++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/lang-core.model.yml
@@ -31,6 +31,9 @@ extensions:
- ["lang:core", "::extend", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]", "taint", "manual"]
- ["lang:core", "::extend_packed", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
- ["lang:core", "::extend_packed", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
+ - ["lang:core", "::align_to", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
+ - ["lang:core", "::pad_to_align", "Argument[self]", "ReturnValue", "taint", "manual"]
+ - ["lang:core", "::size", "Argument[self]", "ReturnValue", "taint", "manual"]
# Ptr
- ["lang:core", "crate::ptr::read", "Argument[0].Reference", "ReturnValue", "value", "manual"]
- ["lang:core", "crate::ptr::read_unaligned", "Argument[0].Reference", "ReturnValue", "value", "manual"]
diff --git a/rust/ql/test/query-tests/diagnostics/SummaryStats.expected b/rust/ql/test/query-tests/diagnostics/SummaryStats.expected
index a8833f626807..787fc3ddbbea 100644
--- a/rust/ql/test/query-tests/diagnostics/SummaryStats.expected
+++ b/rust/ql/test/query-tests/diagnostics/SummaryStats.expected
@@ -15,7 +15,7 @@
| Macro calls - resolved | 8 |
| Macro calls - total | 9 |
| Macro calls - unresolved | 1 |
-| Taint edges - number of edges | 1675 |
+| Taint edges - number of edges | 1677 |
| Taint reach - nodes tainted | 0 |
| Taint reach - per million nodes | 0 |
| Taint sinks - cryptographic operations | 0 |
diff --git a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
index 4dcc0f1b5583..0d8c10db39fc 100644
--- a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
+++ b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
@@ -1,10 +1,13 @@
#select
| main.rs:18:13:18:31 | ...::realloc | main.rs:211:13:211:26 | ...::args | main.rs:18:13:18:31 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
| main.rs:21:13:21:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:21:13:21:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:22:13:22:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:22:13:22:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:23:13:23:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:23:13:23:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
| main.rs:24:13:24:36 | ...::alloc_zeroed | main.rs:211:13:211:26 | ...::args | main.rs:24:13:24:36 | ...::alloc_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
| main.rs:30:13:30:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:30:13:30:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
| main.rs:33:13:33:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:33:13:33:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
| main.rs:37:13:37:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:37:13:37:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:40:13:40:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:40:13:40:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
| main.rs:50:13:50:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:50:13:50:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
| main.rs:51:13:51:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:51:13:51:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
| main.rs:53:13:53:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:53:13:53:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
@@ -52,75 +55,87 @@ edges
| main.rs:18:41:18:41 | v | main.rs:32:60:32:89 | ... * ... | provenance | |
| main.rs:18:41:18:41 | v | main.rs:35:9:35:10 | s6 | provenance | |
| main.rs:20:9:20:10 | l2 | main.rs:21:31:21:32 | l2 | provenance | |
-| main.rs:20:14:20:54 | ...::from_size_align(...) [Ok] | main.rs:20:14:20:63 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:20:14:20:54 | ...::from_size_align(...) [Ok] | main.rs:20:14:20:63 | ... .unwrap(...) | provenance | MaD:31 |
| main.rs:20:14:20:63 | ... .unwrap(...) | main.rs:20:9:20:10 | l2 | provenance | |
-| main.rs:20:50:20:50 | v | main.rs:20:14:20:54 | ...::from_size_align(...) [Ok] | provenance | MaD:22 |
+| main.rs:20:50:20:50 | v | main.rs:20:14:20:54 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
| main.rs:21:31:21:32 | l2 | main.rs:21:13:21:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:21:31:21:32 | l2 | main.rs:22:31:22:44 | l2.align_to(...) [Ok] | provenance | MaD:17 |
+| main.rs:21:31:21:32 | l2 | main.rs:23:31:23:44 | l2.align_to(...) [Ok] | provenance | MaD:17 |
| main.rs:21:31:21:32 | l2 | main.rs:24:38:24:39 | l2 | provenance | |
+| main.rs:22:31:22:44 | l2.align_to(...) [Ok] | main.rs:22:31:22:53 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:22:31:22:53 | ... .unwrap(...) | main.rs:22:13:22:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:23:31:23:44 | l2.align_to(...) [Ok] | main.rs:23:31:23:53 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:23:31:23:53 | ... .unwrap(...) | main.rs:23:31:23:68 | ... .pad_to_align(...) | provenance | MaD:25 |
+| main.rs:23:31:23:68 | ... .pad_to_align(...) | main.rs:23:13:23:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:24:38:24:39 | l2 | main.rs:24:13:24:36 | ...::alloc_zeroed | provenance | MaD:4 Sink:MaD:4 |
| main.rs:29:9:29:10 | l4 | main.rs:30:31:30:32 | l4 | provenance | |
| main.rs:29:14:29:64 | ...::from_size_align_unchecked(...) | main.rs:29:9:29:10 | l4 | provenance | |
-| main.rs:29:60:29:60 | v | main.rs:29:14:29:64 | ...::from_size_align_unchecked(...) | provenance | MaD:23 |
+| main.rs:29:60:29:60 | v | main.rs:29:14:29:64 | ...::from_size_align_unchecked(...) | provenance | MaD:24 |
| main.rs:30:31:30:32 | l4 | main.rs:30:13:30:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:32:9:32:10 | l5 | main.rs:33:31:33:32 | l5 | provenance | |
| main.rs:32:14:32:118 | ...::from_size_align_unchecked(...) | main.rs:32:9:32:10 | l5 | provenance | |
-| main.rs:32:60:32:89 | ... * ... | main.rs:32:14:32:118 | ...::from_size_align_unchecked(...) | provenance | MaD:23 |
+| main.rs:32:60:32:89 | ... * ... | main.rs:32:14:32:118 | ...::from_size_align_unchecked(...) | provenance | MaD:24 |
| main.rs:33:31:33:32 | l5 | main.rs:33:13:33:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:35:9:35:10 | s6 | main.rs:36:60:36:61 | s6 | provenance | |
| main.rs:36:9:36:10 | l6 | main.rs:37:31:37:32 | l6 | provenance | |
| main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | main.rs:36:9:36:10 | l6 | provenance | |
-| main.rs:36:60:36:61 | s6 | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | provenance | MaD:23 |
+| main.rs:36:60:36:61 | s6 | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | provenance | MaD:24 |
| main.rs:37:31:37:32 | l6 | main.rs:37:13:37:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:37:31:37:32 | l6 | main.rs:39:60:39:68 | l6.size(...) | provenance | MaD:28 |
+| main.rs:39:9:39:10 | l7 | main.rs:40:31:40:32 | l7 | provenance | |
+| main.rs:39:14:39:72 | ...::from_size_align_unchecked(...) | main.rs:39:9:39:10 | l7 | provenance | |
+| main.rs:39:60:39:68 | l6.size(...) | main.rs:39:14:39:72 | ...::from_size_align_unchecked(...) | provenance | MaD:24 |
+| main.rs:40:31:40:32 | l7 | main.rs:40:13:40:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:43:44:43:51 | ...: usize | main.rs:50:41:50:41 | v | provenance | |
| main.rs:43:44:43:51 | ...: usize | main.rs:51:41:51:45 | ... + ... | provenance | |
| main.rs:43:44:43:51 | ...: usize | main.rs:53:48:53:48 | v | provenance | |
| main.rs:43:44:43:51 | ...: usize | main.rs:54:48:54:53 | ... * ... | provenance | |
| main.rs:43:44:43:51 | ...: usize | main.rs:58:34:58:34 | v | provenance | |
| main.rs:43:44:43:51 | ...: usize | main.rs:67:46:67:46 | v | provenance | |
-| main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | main.rs:50:31:50:51 | ... .unwrap(...) [tuple.0] | provenance | MaD:28 |
+| main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | main.rs:50:31:50:51 | ... .unwrap(...) [tuple.0] | provenance | MaD:31 |
| main.rs:50:31:50:51 | ... .unwrap(...) [tuple.0] | main.rs:50:31:50:53 | ... .0 | provenance | |
| main.rs:50:31:50:53 | ... .0 | main.rs:50:13:50:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:50:41:50:41 | v | main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:24 |
-| main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | main.rs:51:31:51:55 | ... .unwrap(...) [tuple.0] | provenance | MaD:28 |
+| main.rs:50:41:50:41 | v | main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:26 |
+| main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | main.rs:51:31:51:55 | ... .unwrap(...) [tuple.0] | provenance | MaD:31 |
| main.rs:51:31:51:55 | ... .unwrap(...) [tuple.0] | main.rs:51:31:51:57 | ... .0 | provenance | |
| main.rs:51:31:51:57 | ... .0 | main.rs:51:13:51:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:51:41:51:45 | ... + ... | main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:24 |
-| main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | main.rs:53:31:53:58 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:51:41:51:45 | ... + ... | main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:26 |
+| main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | main.rs:53:31:53:58 | ... .unwrap(...) | provenance | MaD:31 |
| main.rs:53:31:53:58 | ... .unwrap(...) | main.rs:53:13:53:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:53:48:53:48 | v | main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | provenance | MaD:25 |
-| main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | main.rs:54:31:54:63 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:53:48:53:48 | v | main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | provenance | MaD:27 |
+| main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | main.rs:54:31:54:63 | ... .unwrap(...) | provenance | MaD:31 |
| main.rs:54:31:54:63 | ... .unwrap(...) | main.rs:54:13:54:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:54:48:54:53 | ... * ... | main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | provenance | MaD:25 |
+| main.rs:54:48:54:53 | ... * ... | main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | provenance | MaD:27 |
| main.rs:58:9:58:20 | TuplePat [tuple.0] | main.rs:58:10:58:11 | k1 | provenance | |
| main.rs:58:10:58:11 | k1 | main.rs:59:31:59:32 | k1 | provenance | |
-| main.rs:58:24:58:35 | l3.repeat(...) [Ok, tuple.0] | main.rs:58:24:58:66 | ... .expect(...) [tuple.0] | provenance | MaD:27 |
+| main.rs:58:24:58:35 | l3.repeat(...) [Ok, tuple.0] | main.rs:58:24:58:66 | ... .expect(...) [tuple.0] | provenance | MaD:30 |
| main.rs:58:24:58:66 | ... .expect(...) [tuple.0] | main.rs:58:9:58:20 | TuplePat [tuple.0] | provenance | |
-| main.rs:58:34:58:34 | v | main.rs:58:24:58:35 | l3.repeat(...) [Ok, tuple.0] | provenance | MaD:24 |
+| main.rs:58:34:58:34 | v | main.rs:58:24:58:35 | l3.repeat(...) [Ok, tuple.0] | provenance | MaD:26 |
| main.rs:59:31:59:32 | k1 | main.rs:59:13:59:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:59:31:59:32 | k1 | main.rs:60:34:60:35 | k1 | provenance | |
-| main.rs:59:31:59:32 | k1 | main.rs:62:24:62:36 | k1.extend(...) [Ok, tuple.0] | provenance | MaD:19 |
+| main.rs:59:31:59:32 | k1 | main.rs:62:24:62:36 | k1.extend(...) [Ok, tuple.0] | provenance | MaD:20 |
| main.rs:59:31:59:32 | k1 | main.rs:64:48:64:49 | k1 | provenance | |
-| main.rs:59:31:59:32 | k1 | main.rs:65:31:65:50 | k1.extend_packed(...) [Ok] | provenance | MaD:21 |
+| main.rs:59:31:59:32 | k1 | main.rs:65:31:65:50 | k1.extend_packed(...) [Ok] | provenance | MaD:22 |
| main.rs:60:9:60:20 | TuplePat [tuple.0] | main.rs:60:10:60:11 | k2 | provenance | |
| main.rs:60:10:60:11 | k2 | main.rs:61:31:61:32 | k2 | provenance | |
-| main.rs:60:24:60:36 | l3.extend(...) [Ok, tuple.0] | main.rs:60:24:60:45 | ... .unwrap(...) [tuple.0] | provenance | MaD:28 |
+| main.rs:60:24:60:36 | l3.extend(...) [Ok, tuple.0] | main.rs:60:24:60:45 | ... .unwrap(...) [tuple.0] | provenance | MaD:31 |
| main.rs:60:24:60:45 | ... .unwrap(...) [tuple.0] | main.rs:60:9:60:20 | TuplePat [tuple.0] | provenance | |
-| main.rs:60:34:60:35 | k1 | main.rs:60:24:60:36 | l3.extend(...) [Ok, tuple.0] | provenance | MaD:18 |
+| main.rs:60:34:60:35 | k1 | main.rs:60:24:60:36 | l3.extend(...) [Ok, tuple.0] | provenance | MaD:19 |
| main.rs:61:31:61:32 | k2 | main.rs:61:13:61:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:62:9:62:20 | TuplePat [tuple.0] | main.rs:62:10:62:11 | k3 | provenance | |
| main.rs:62:10:62:11 | k3 | main.rs:63:31:63:32 | k3 | provenance | |
-| main.rs:62:24:62:36 | k1.extend(...) [Ok, tuple.0] | main.rs:62:24:62:45 | ... .unwrap(...) [tuple.0] | provenance | MaD:28 |
+| main.rs:62:24:62:36 | k1.extend(...) [Ok, tuple.0] | main.rs:62:24:62:45 | ... .unwrap(...) [tuple.0] | provenance | MaD:31 |
| main.rs:62:24:62:45 | ... .unwrap(...) [tuple.0] | main.rs:62:9:62:20 | TuplePat [tuple.0] | provenance | |
| main.rs:63:31:63:32 | k3 | main.rs:63:13:63:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | main.rs:64:31:64:59 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | main.rs:64:31:64:59 | ... .unwrap(...) | provenance | MaD:31 |
| main.rs:64:31:64:59 | ... .unwrap(...) | main.rs:64:13:64:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:64:48:64:49 | k1 | main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | provenance | MaD:20 |
-| main.rs:65:31:65:50 | k1.extend_packed(...) [Ok] | main.rs:65:31:65:59 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:64:48:64:49 | k1 | main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | provenance | MaD:21 |
+| main.rs:65:31:65:50 | k1.extend_packed(...) [Ok] | main.rs:65:31:65:59 | ... .unwrap(...) | provenance | MaD:31 |
| main.rs:65:31:65:59 | ... .unwrap(...) | main.rs:65:13:65:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:67:9:67:10 | l4 | main.rs:68:31:68:32 | l4 | provenance | |
-| main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | main.rs:67:14:67:56 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | main.rs:67:14:67:56 | ... .unwrap(...) | provenance | MaD:31 |
| main.rs:67:14:67:56 | ... .unwrap(...) | main.rs:67:9:67:10 | l4 | provenance | |
-| main.rs:67:46:67:46 | v | main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | provenance | MaD:17 |
+| main.rs:67:46:67:46 | v | main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:68:31:68:32 | l4 | main.rs:68:13:68:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:71:35:71:38 | ...: T | main.rs:77:9:77:16 | return v | provenance | |
| main.rs:81:38:81:45 | ...: usize | main.rs:82:47:82:47 | v | provenance | |
@@ -131,9 +146,9 @@ edges
| main.rs:81:38:81:45 | ...: usize | main.rs:116:53:116:53 | v | provenance | |
| main.rs:82:9:82:10 | l1 | main.rs:85:35:85:36 | l1 | provenance | |
| main.rs:82:9:82:10 | l1 | main.rs:87:35:87:36 | l1 | provenance | |
-| main.rs:82:14:82:48 | ...::array::<...>(...) [Ok] | main.rs:82:14:82:57 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:82:14:82:48 | ...::array::<...>(...) [Ok] | main.rs:82:14:82:57 | ... .unwrap(...) | provenance | MaD:31 |
| main.rs:82:14:82:57 | ... .unwrap(...) | main.rs:82:9:82:10 | l1 | provenance | |
-| main.rs:82:47:82:47 | v | main.rs:82:14:82:48 | ...::array::<...>(...) [Ok] | provenance | MaD:17 |
+| main.rs:82:47:82:47 | v | main.rs:82:14:82:48 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:85:35:85:36 | l1 | main.rs:85:17:85:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:85:35:85:36 | l1 | main.rs:91:35:91:36 | l1 | provenance | |
| main.rs:85:35:85:36 | l1 | main.rs:93:35:93:36 | l1 | provenance | |
@@ -146,31 +161,31 @@ edges
| main.rs:93:35:93:36 | l1 | main.rs:119:31:119:32 | l1 | provenance | |
| main.rs:97:13:97:21 | mut v_mut | main.rs:103:51:103:55 | v_mut | provenance | |
| main.rs:103:13:103:14 | l2 | main.rs:104:35:104:36 | l2 | provenance | |
-| main.rs:103:18:103:56 | ...::array::<...>(...) [Ok] | main.rs:103:18:103:65 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:103:18:103:56 | ...::array::<...>(...) [Ok] | main.rs:103:18:103:65 | ... .unwrap(...) | provenance | MaD:31 |
| main.rs:103:18:103:65 | ... .unwrap(...) | main.rs:103:13:103:14 | l2 | provenance | |
-| main.rs:103:51:103:55 | v_mut | main.rs:103:18:103:56 | ...::array::<...>(...) [Ok] | provenance | MaD:17 |
+| main.rs:103:51:103:55 | v_mut | main.rs:103:18:103:56 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:104:35:104:36 | l2 | main.rs:104:17:104:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:106:13:106:14 | l3 | main.rs:107:35:107:36 | l3 | provenance | |
-| main.rs:106:18:106:52 | ...::array::<...>(...) [Ok] | main.rs:106:18:106:61 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:106:18:106:52 | ...::array::<...>(...) [Ok] | main.rs:106:18:106:61 | ... .unwrap(...) | provenance | MaD:31 |
| main.rs:106:18:106:61 | ... .unwrap(...) | main.rs:106:13:106:14 | l3 | provenance | |
-| main.rs:106:51:106:51 | v | main.rs:106:18:106:52 | ...::array::<...>(...) [Ok] | provenance | MaD:17 |
+| main.rs:106:51:106:51 | v | main.rs:106:18:106:52 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:107:35:107:36 | l3 | main.rs:107:17:107:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:110:9:110:10 | l4 | main.rs:111:31:111:32 | l4 | provenance | |
-| main.rs:110:14:110:68 | ...::array::<...>(...) [Ok] | main.rs:110:14:110:77 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:110:14:110:68 | ...::array::<...>(...) [Ok] | main.rs:110:14:110:77 | ... .unwrap(...) | provenance | MaD:31 |
| main.rs:110:14:110:77 | ... .unwrap(...) | main.rs:110:9:110:10 | l4 | provenance | |
-| main.rs:110:47:110:67 | ...::min(...) | main.rs:110:14:110:68 | ...::array::<...>(...) [Ok] | provenance | MaD:17 |
-| main.rs:110:61:110:61 | v | main.rs:110:47:110:67 | ...::min(...) | provenance | MaD:31 |
+| main.rs:110:47:110:67 | ...::min(...) | main.rs:110:14:110:68 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
+| main.rs:110:61:110:61 | v | main.rs:110:47:110:67 | ...::min(...) | provenance | MaD:34 |
| main.rs:111:31:111:32 | l4 | main.rs:111:13:111:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:113:9:113:10 | l5 | main.rs:114:31:114:32 | l5 | provenance | |
-| main.rs:113:14:113:68 | ...::array::<...>(...) [Ok] | main.rs:113:14:113:77 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:113:14:113:68 | ...::array::<...>(...) [Ok] | main.rs:113:14:113:77 | ... .unwrap(...) | provenance | MaD:31 |
| main.rs:113:14:113:77 | ... .unwrap(...) | main.rs:113:9:113:10 | l5 | provenance | |
-| main.rs:113:47:113:67 | ...::max(...) | main.rs:113:14:113:68 | ...::array::<...>(...) [Ok] | provenance | MaD:17 |
-| main.rs:113:61:113:61 | v | main.rs:113:47:113:67 | ...::max(...) | provenance | MaD:30 |
+| main.rs:113:47:113:67 | ...::max(...) | main.rs:113:14:113:68 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
+| main.rs:113:61:113:61 | v | main.rs:113:47:113:67 | ...::max(...) | provenance | MaD:33 |
| main.rs:114:31:114:32 | l5 | main.rs:114:13:114:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:116:9:116:10 | l6 | main.rs:117:31:117:32 | l6 | provenance | |
-| main.rs:116:14:116:63 | ...::array::<...>(...) [Ok] | main.rs:116:14:116:72 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:116:14:116:63 | ...::array::<...>(...) [Ok] | main.rs:116:14:116:72 | ... .unwrap(...) | provenance | MaD:31 |
| main.rs:116:14:116:72 | ... .unwrap(...) | main.rs:116:9:116:10 | l6 | provenance | |
-| main.rs:116:47:116:62 | clamp(...) | main.rs:116:14:116:63 | ...::array::<...>(...) [Ok] | provenance | MaD:17 |
+| main.rs:116:47:116:62 | clamp(...) | main.rs:116:14:116:63 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:116:53:116:53 | v | main.rs:71:35:71:38 | ...: T | provenance | |
| main.rs:116:53:116:53 | v | main.rs:116:47:116:62 | clamp(...) | provenance | |
| main.rs:117:31:117:32 | l6 | main.rs:117:13:117:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
@@ -179,9 +194,9 @@ edges
| main.rs:123:31:123:32 | l1 | main.rs:123:13:123:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:128:29:128:36 | ...: usize | main.rs:137:46:137:46 | v | provenance | |
| main.rs:137:9:137:10 | l2 | main.rs:138:38:138:39 | l2 | provenance | |
-| main.rs:137:14:137:47 | ...::array::<...>(...) [Ok] | main.rs:137:14:137:56 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:137:14:137:47 | ...::array::<...>(...) [Ok] | main.rs:137:14:137:56 | ... .unwrap(...) | provenance | MaD:31 |
| main.rs:137:14:137:56 | ... .unwrap(...) | main.rs:137:9:137:10 | l2 | provenance | |
-| main.rs:137:46:137:46 | v | main.rs:137:14:137:47 | ...::array::<...>(...) [Ok] | provenance | MaD:17 |
+| main.rs:137:46:137:46 | v | main.rs:137:14:137:47 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:138:38:138:39 | l2 | main.rs:138:32:138:36 | alloc | provenance | MaD:10 Sink:MaD:10 |
| main.rs:138:38:138:39 | l2 | main.rs:139:45:139:46 | l2 | provenance | |
| main.rs:139:45:139:46 | l2 | main.rs:139:32:139:43 | alloc_zeroed | provenance | MaD:11 Sink:MaD:11 |
@@ -218,10 +233,10 @@ edges
| main.rs:211:9:211:9 | v | main.rs:217:27:217:27 | v | provenance | |
| main.rs:211:9:211:9 | v | main.rs:218:25:218:25 | v | provenance | |
| main.rs:211:13:211:26 | ...::args | main.rs:211:13:211:28 | ...::args(...) [element] | provenance | Src:MaD:16 |
-| main.rs:211:13:211:28 | ...::args(...) [element] | main.rs:211:13:211:35 | ... .nth(...) [Some] | provenance | MaD:32 |
-| main.rs:211:13:211:35 | ... .nth(...) [Some] | main.rs:211:13:211:65 | ... .unwrap_or(...) | provenance | MaD:26 |
-| main.rs:211:13:211:65 | ... .unwrap_or(...) | main.rs:211:13:211:82 | ... .parse(...) [Ok] | provenance | MaD:29 |
-| main.rs:211:13:211:82 | ... .parse(...) [Ok] | main.rs:211:13:211:91 | ... .unwrap(...) | provenance | MaD:28 |
+| main.rs:211:13:211:28 | ...::args(...) [element] | main.rs:211:13:211:35 | ... .nth(...) [Some] | provenance | MaD:35 |
+| main.rs:211:13:211:35 | ... .nth(...) [Some] | main.rs:211:13:211:65 | ... .unwrap_or(...) | provenance | MaD:29 |
+| main.rs:211:13:211:65 | ... .unwrap_or(...) | main.rs:211:13:211:82 | ... .parse(...) [Ok] | provenance | MaD:32 |
+| main.rs:211:13:211:82 | ... .parse(...) [Ok] | main.rs:211:13:211:91 | ... .unwrap(...) | provenance | MaD:31 |
| main.rs:211:13:211:91 | ... .unwrap(...) | main.rs:211:9:211:9 | v | provenance | |
| main.rs:214:34:214:34 | v | main.rs:12:36:12:43 | ...: usize | provenance | |
| main.rs:215:42:215:42 | v | main.rs:43:44:43:51 | ...: usize | provenance | |
@@ -245,22 +260,25 @@ models
| 14 | Sink: repo:https://github.com/rust-lang/libc:libc; ::malloc; alloc-size; Argument[0] |
| 15 | Sink: repo:https://github.com/rust-lang/libc:libc; ::realloc; alloc-size; Argument[1] |
| 16 | Source: lang:std; crate::env::args; command-line-source; ReturnValue.Element |
-| 17 | Summary: lang:core; ::array; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
-| 18 | Summary: lang:core; ::extend; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]; taint |
-| 19 | Summary: lang:core; ::extend; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]; taint |
-| 20 | Summary: lang:core; ::extend_packed; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
-| 21 | Summary: lang:core; ::extend_packed; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
-| 22 | Summary: lang:core; ::from_size_align; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
-| 23 | Summary: lang:core; ::from_size_align_unchecked; Argument[0]; ReturnValue; taint |
-| 24 | Summary: lang:core; ::repeat; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]; taint |
-| 25 | Summary: lang:core; ::repeat_packed; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
-| 26 | Summary: lang:core; ::unwrap_or; Argument[self].Field[crate::option::Option::Some(0)]; ReturnValue; value |
-| 27 | Summary: lang:core; ::expect; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value |
-| 28 | Summary: lang:core; ::unwrap; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value |
-| 29 | Summary: lang:core; ::parse; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
-| 30 | Summary: lang:core; crate::cmp::max; Argument[0]; ReturnValue; value |
-| 31 | Summary: lang:core; crate::cmp::min; Argument[0]; ReturnValue; value |
-| 32 | Summary: lang:core; crate::iter::traits::iterator::Iterator::nth; Argument[self].Element; ReturnValue.Field[crate::option::Option::Some(0)]; value |
+| 17 | Summary: lang:core; ::align_to; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
+| 18 | Summary: lang:core; ::array; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
+| 19 | Summary: lang:core; ::extend; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]; taint |
+| 20 | Summary: lang:core; ::extend; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]; taint |
+| 21 | Summary: lang:core; ::extend_packed; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
+| 22 | Summary: lang:core; ::extend_packed; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
+| 23 | Summary: lang:core; ::from_size_align; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
+| 24 | Summary: lang:core; ::from_size_align_unchecked; Argument[0]; ReturnValue; taint |
+| 25 | Summary: lang:core; ::pad_to_align; Argument[self]; ReturnValue; taint |
+| 26 | Summary: lang:core; ::repeat; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]; taint |
+| 27 | Summary: lang:core; ::repeat_packed; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
+| 28 | Summary: lang:core; ::size; Argument[self]; ReturnValue; taint |
+| 29 | Summary: lang:core; ::unwrap_or; Argument[self].Field[crate::option::Option::Some(0)]; ReturnValue; value |
+| 30 | Summary: lang:core; ::expect; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value |
+| 31 | Summary: lang:core; ::unwrap; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value |
+| 32 | Summary: lang:core; ::parse; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
+| 33 | Summary: lang:core; crate::cmp::max; Argument[0]; ReturnValue; value |
+| 34 | Summary: lang:core; crate::cmp::min; Argument[0]; ReturnValue; value |
+| 35 | Summary: lang:core; crate::iter::traits::iterator::Iterator::nth; Argument[self].Element; ReturnValue.Field[crate::option::Option::Some(0)]; value |
nodes
| main.rs:12:36:12:43 | ...: usize | semmle.label | ...: usize |
| main.rs:18:13:18:31 | ...::realloc | semmle.label | ...::realloc |
@@ -271,6 +289,13 @@ nodes
| main.rs:20:50:20:50 | v | semmle.label | v |
| main.rs:21:13:21:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:21:31:21:32 | l2 | semmle.label | l2 |
+| main.rs:22:13:22:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:22:31:22:44 | l2.align_to(...) [Ok] | semmle.label | l2.align_to(...) [Ok] |
+| main.rs:22:31:22:53 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:23:13:23:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:23:31:23:44 | l2.align_to(...) [Ok] | semmle.label | l2.align_to(...) [Ok] |
+| main.rs:23:31:23:53 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:23:31:23:68 | ... .pad_to_align(...) | semmle.label | ... .pad_to_align(...) |
| main.rs:24:13:24:36 | ...::alloc_zeroed | semmle.label | ...::alloc_zeroed |
| main.rs:24:38:24:39 | l2 | semmle.label | l2 |
| main.rs:29:9:29:10 | l4 | semmle.label | l4 |
@@ -289,6 +314,11 @@ nodes
| main.rs:36:60:36:61 | s6 | semmle.label | s6 |
| main.rs:37:13:37:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:37:31:37:32 | l6 | semmle.label | l6 |
+| main.rs:39:9:39:10 | l7 | semmle.label | l7 |
+| main.rs:39:14:39:72 | ...::from_size_align_unchecked(...) | semmle.label | ...::from_size_align_unchecked(...) |
+| main.rs:39:60:39:68 | l6.size(...) | semmle.label | l6.size(...) |
+| main.rs:40:13:40:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:40:31:40:32 | l7 | semmle.label | l7 |
| main.rs:43:44:43:51 | ...: usize | semmle.label | ...: usize |
| main.rs:50:13:50:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | semmle.label | l2.repeat(...) [Ok, tuple.0] |
diff --git a/rust/ql/test/query-tests/security/CWE-770/main.rs b/rust/ql/test/query-tests/security/CWE-770/main.rs
index 0af7d0eb5360..d2b5c109fa77 100644
--- a/rust/ql/test/query-tests/security/CWE-770/main.rs
+++ b/rust/ql/test/query-tests/security/CWE-770/main.rs
@@ -19,8 +19,8 @@ unsafe fn test_std_alloc_from_size(v: usize) {
let l2 = std::alloc::Layout::from_size_align(v, 1).unwrap();
let _ = std::alloc::alloc(l2); // $ Alert[rust/uncontrolled-allocation-size]=arg1
- let _ = std::alloc::alloc(l2.align_to(8).unwrap()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
- let _ = std::alloc::alloc(l2.align_to(8).unwrap().pad_to_align()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l2.align_to(8).unwrap()); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(l2.align_to(8).unwrap().pad_to_align()); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::alloc_zeroed(l2); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l3 = std::alloc::Layout::from_size_align(1, v).unwrap(); // not obviously dangerous?
@@ -37,7 +37,7 @@ unsafe fn test_std_alloc_from_size(v: usize) {
let _ = std::alloc::alloc(l6); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l7 = std::alloc::Layout::from_size_align_unchecked(l6.size(), 8);
- let _ = std::alloc::alloc(l7); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
+ let _ = std::alloc::alloc(l7); // $ Alert[rust/uncontrolled-allocation-size]=arg1
}
unsafe fn test_std_alloc_new_repeat_extend(v: usize) {
From 64aa4e8bae685efee1f4751c6bea20173dadb756 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 25 Mar 2025 09:38:16 +0000
Subject: [PATCH 084/409] Rust: Ensure that the sinks for this query appear in
metrics.
---
rust/ql/src/queries/summary/Stats.qll | 1 +
1 file changed, 1 insertion(+)
diff --git a/rust/ql/src/queries/summary/Stats.qll b/rust/ql/src/queries/summary/Stats.qll
index a2220398b415..119a53d7d722 100644
--- a/rust/ql/src/queries/summary/Stats.qll
+++ b/rust/ql/src/queries/summary/Stats.qll
@@ -15,6 +15,7 @@ private import codeql.rust.Concepts
private import codeql.rust.security.CleartextLoggingExtensions
private import codeql.rust.security.SqlInjectionExtensions
private import codeql.rust.security.WeakSensitiveDataHashingExtensions
+private import codeql.rust.security.UncontrolledAllocationSizeExtensions
private import codeql.rust.security.regex.RegexInjectionExtensions
/**
From addc1d34d86860b220e674557ead9135dd60403c Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 25 Mar 2025 16:05:35 +0000
Subject: [PATCH 085/409] Rust: Add qhelp, examples, and tests of examples.
---
.../CWE-770/UncontrolledAllocationSize.qhelp | 41 ++++
.../CWE-770/UncontrolledAllocationSizeBad.rs | 11 +
.../CWE-770/UncontrolledAllocationSizeGood.rs | 17 ++
.../UncontrolledAllocationSize.expected | 210 +++++++++++-------
.../test/query-tests/security/CWE-770/main.rs | 52 +++++
5 files changed, 255 insertions(+), 76 deletions(-)
create mode 100644 rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.qhelp
create mode 100644 rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSizeBad.rs
create mode 100644 rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSizeGood.rs
diff --git a/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.qhelp b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.qhelp
new file mode 100644
index 000000000000..936c27619764
--- /dev/null
+++ b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSize.qhelp
@@ -0,0 +1,41 @@
+
+
+
+
+Allocating memory with a size based on user input may allow arbitrary amounts of memory to be
+allocated, leading to a crash or denial of service incident.
+
+If the user input is multiplied by a constant, such as the size of a type, the result may
+overflow. In a build with the --release flag Rust performs two's complement wrapping,
+with the result that less memory may be allocated than expected. This can lead to buffer overflow
+incidents.
+
+
+
+
+Implement a guard to limit the amount of memory that is allocated, and reject the request if
+the guard is not met. Ensure that any multiplications in the calculation cannot overflow, either
+by guarding their inputs, or using a multiplication routine such as checked_mul that
+does not wrap around.
+
+
+
+
+In the following example, an arbitrary amount of memory is allocated based on user input. In
+addition, due to the multiplication operation the result may overflow if a very large value is
+provided, leading to less memory being allocated than other parts of the program expect.
+
+
+In the fixed example, the user input is checked against a maximum value. If the check fails an
+error is returned, and both the multiplication and alloaction do not take place.
+
+
+
+
+
+The Rust Programming Language: Data Types - Integer Overflow.
+
+
+
diff --git a/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSizeBad.rs b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSizeBad.rs
new file mode 100644
index 000000000000..40794494f3bf
--- /dev/null
+++ b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSizeBad.rs
@@ -0,0 +1,11 @@
+
+fn allocate_buffer(user_input: String) -> Result<*mut u8, Error> {
+ let num_bytes = user_input.parse::()? * std::mem::size_of::();
+
+ let layout = std::alloc::Layout::from_size_align(num_bytes, 1).unwrap();
+ unsafe {
+ let buffer = std::alloc::alloc(layout); // BAD: uncontrolled allocation size
+
+ Ok(buffer)
+ }
+}
diff --git a/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSizeGood.rs b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSizeGood.rs
new file mode 100644
index 000000000000..c07584312890
--- /dev/null
+++ b/rust/ql/src/queries/security/CWE-770/UncontrolledAllocationSizeGood.rs
@@ -0,0 +1,17 @@
+
+const BUFFER_LIMIT: usize = 10 * 1024;
+
+fn allocate_buffer(user_input: String) -> Result<*mut u8, Error> {
+ let size = user_input.parse::()?;
+ if (size > BUFFER_LIMIT) {
+ return Err("Size exceeds limit".into());
+ }
+ let num_bytes = size * std::mem::size_of::();
+
+ let layout = std::alloc::Layout::from_size_align(num_bytes, 1).unwrap();
+ unsafe {
+ let buffer = std::alloc::alloc(layout); // GOOD
+
+ Ok(buffer)
+ }
+}
diff --git a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
index 0d8c10db39fc..7ef8327b64ed 100644
--- a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
+++ b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
@@ -1,52 +1,54 @@
#select
-| main.rs:18:13:18:31 | ...::realloc | main.rs:211:13:211:26 | ...::args | main.rs:18:13:18:31 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:21:13:21:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:21:13:21:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:22:13:22:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:22:13:22:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:23:13:23:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:23:13:23:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:24:13:24:36 | ...::alloc_zeroed | main.rs:211:13:211:26 | ...::args | main.rs:24:13:24:36 | ...::alloc_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:30:13:30:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:30:13:30:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:33:13:33:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:33:13:33:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:37:13:37:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:37:13:37:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:40:13:40:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:40:13:40:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:50:13:50:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:50:13:50:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:51:13:51:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:51:13:51:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:53:13:53:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:53:13:53:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:54:13:54:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:54:13:54:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:59:13:59:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:59:13:59:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:61:13:61:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:61:13:61:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:63:13:63:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:63:13:63:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:64:13:64:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:64:13:64:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:65:13:65:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:65:13:65:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:68:13:68:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:68:13:68:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:85:17:85:33 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:85:17:85:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:87:17:87:33 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:87:17:87:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:91:17:91:33 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:91:17:91:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:93:17:93:33 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:93:17:93:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:104:17:104:33 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:104:17:104:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:107:17:107:33 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:107:17:107:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:111:13:111:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:111:13:111:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:114:13:114:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:114:13:114:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:117:13:117:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:117:13:117:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:119:13:119:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:119:13:119:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:123:13:123:29 | ...::alloc | main.rs:211:13:211:26 | ...::args | main.rs:123:13:123:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:138:32:138:36 | alloc | main.rs:211:13:211:26 | ...::args | main.rs:138:32:138:36 | alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:139:32:139:43 | alloc_zeroed | main.rs:211:13:211:26 | ...::args | main.rs:139:32:139:43 | alloc_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:140:32:140:39 | allocate | main.rs:211:13:211:26 | ...::args | main.rs:140:32:140:39 | allocate | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:141:32:141:46 | allocate_zeroed | main.rs:211:13:211:26 | ...::args | main.rs:141:32:141:46 | allocate_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:142:32:142:39 | allocate | main.rs:211:13:211:26 | ...::args | main.rs:142:32:142:39 | allocate | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:143:32:143:46 | allocate_zeroed | main.rs:211:13:211:26 | ...::args | main.rs:143:32:143:46 | allocate_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:153:40:153:43 | grow | main.rs:211:13:211:26 | ...::args | main.rs:153:40:153:43 | grow | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:155:40:155:50 | grow_zeroed | main.rs:211:13:211:26 | ...::args | main.rs:155:40:155:50 | grow_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:164:13:164:24 | ...::malloc | main.rs:211:13:211:26 | ...::args | main.rs:164:13:164:24 | ...::malloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:164:13:164:24 | ...::malloc | main.rs:211:13:211:26 | ...::args | main.rs:164:13:164:24 | ...::malloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:165:13:165:31 | ...::aligned_alloc | main.rs:211:13:211:26 | ...::args | main.rs:165:13:165:31 | ...::aligned_alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:165:13:165:31 | ...::aligned_alloc | main.rs:211:13:211:26 | ...::args | main.rs:165:13:165:31 | ...::aligned_alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:167:13:167:24 | ...::calloc | main.rs:211:13:211:26 | ...::args | main.rs:167:13:167:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:167:13:167:24 | ...::calloc | main.rs:211:13:211:26 | ...::args | main.rs:167:13:167:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:168:13:168:24 | ...::calloc | main.rs:211:13:211:26 | ...::args | main.rs:168:13:168:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:168:13:168:24 | ...::calloc | main.rs:211:13:211:26 | ...::args | main.rs:168:13:168:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:169:13:169:25 | ...::realloc | main.rs:211:13:211:26 | ...::args | main.rs:169:13:169:25 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
-| main.rs:169:13:169:25 | ...::realloc | main.rs:211:13:211:26 | ...::args | main.rs:169:13:169:25 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:211:13:211:26 | ...::args | user-provided value |
+| main.rs:18:13:18:31 | ...::realloc | main.rs:262:13:262:26 | ...::args | main.rs:18:13:18:31 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:21:13:21:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:21:13:21:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:22:13:22:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:22:13:22:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:23:13:23:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:23:13:23:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:24:13:24:36 | ...::alloc_zeroed | main.rs:262:13:262:26 | ...::args | main.rs:24:13:24:36 | ...::alloc_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:30:13:30:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:30:13:30:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:33:13:33:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:33:13:33:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:37:13:37:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:37:13:37:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:40:13:40:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:40:13:40:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:50:13:50:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:50:13:50:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:51:13:51:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:51:13:51:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:53:13:53:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:53:13:53:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:54:13:54:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:54:13:54:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:59:13:59:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:59:13:59:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:61:13:61:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:61:13:61:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:63:13:63:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:63:13:63:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:64:13:64:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:64:13:64:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:65:13:65:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:65:13:65:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:68:13:68:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:68:13:68:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:85:17:85:33 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:85:17:85:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:87:17:87:33 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:87:17:87:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:91:17:91:33 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:91:17:91:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:93:17:93:33 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:93:17:93:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:104:17:104:33 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:104:17:104:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:107:17:107:33 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:107:17:107:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:111:13:111:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:111:13:111:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:114:13:114:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:114:13:114:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:117:13:117:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:117:13:117:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:119:13:119:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:119:13:119:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:123:13:123:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:123:13:123:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:138:32:138:36 | alloc | main.rs:262:13:262:26 | ...::args | main.rs:138:32:138:36 | alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:139:32:139:43 | alloc_zeroed | main.rs:262:13:262:26 | ...::args | main.rs:139:32:139:43 | alloc_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:140:32:140:39 | allocate | main.rs:262:13:262:26 | ...::args | main.rs:140:32:140:39 | allocate | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:141:32:141:46 | allocate_zeroed | main.rs:262:13:262:26 | ...::args | main.rs:141:32:141:46 | allocate_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:142:32:142:39 | allocate | main.rs:262:13:262:26 | ...::args | main.rs:142:32:142:39 | allocate | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:143:32:143:46 | allocate_zeroed | main.rs:262:13:262:26 | ...::args | main.rs:143:32:143:46 | allocate_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:153:40:153:43 | grow | main.rs:262:13:262:26 | ...::args | main.rs:153:40:153:43 | grow | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:155:40:155:50 | grow_zeroed | main.rs:262:13:262:26 | ...::args | main.rs:155:40:155:50 | grow_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:164:13:164:24 | ...::malloc | main.rs:262:13:262:26 | ...::args | main.rs:164:13:164:24 | ...::malloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:164:13:164:24 | ...::malloc | main.rs:262:13:262:26 | ...::args | main.rs:164:13:164:24 | ...::malloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:165:13:165:31 | ...::aligned_alloc | main.rs:262:13:262:26 | ...::args | main.rs:165:13:165:31 | ...::aligned_alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:165:13:165:31 | ...::aligned_alloc | main.rs:262:13:262:26 | ...::args | main.rs:165:13:165:31 | ...::aligned_alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:167:13:167:24 | ...::calloc | main.rs:262:13:262:26 | ...::args | main.rs:167:13:167:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:167:13:167:24 | ...::calloc | main.rs:262:13:262:26 | ...::args | main.rs:167:13:167:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:168:13:168:24 | ...::calloc | main.rs:262:13:262:26 | ...::args | main.rs:168:13:168:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:168:13:168:24 | ...::calloc | main.rs:262:13:262:26 | ...::args | main.rs:168:13:168:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:169:13:169:25 | ...::realloc | main.rs:262:13:262:26 | ...::args | main.rs:169:13:169:25 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:169:13:169:25 | ...::realloc | main.rs:262:13:262:26 | ...::args | main.rs:169:13:169:25 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
+| main.rs:229:22:229:38 | ...::alloc | main.rs:253:25:253:38 | ...::args | main.rs:229:22:229:38 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:253:25:253:38 | ...::args | user-provided value |
+| main.rs:246:22:246:38 | ...::alloc | main.rs:254:26:254:39 | ...::args | main.rs:246:22:246:38 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:254:26:254:39 | ...::args | user-provided value |
edges
| main.rs:12:36:12:43 | ...: usize | main.rs:18:41:18:41 | v | provenance | |
| main.rs:18:41:18:41 | v | main.rs:18:13:18:31 | ...::realloc | provenance | MaD:5 Sink:MaD:5 |
@@ -227,22 +229,49 @@ edges
| main.rs:168:26:168:26 | v | main.rs:169:31:169:31 | v | provenance | |
| main.rs:169:31:169:31 | v | main.rs:169:13:169:25 | ...::realloc | provenance | MaD:15 Sink:MaD:15 |
| main.rs:169:31:169:31 | v | main.rs:169:13:169:25 | ...::realloc | provenance | MaD:15 Sink:MaD:15 |
-| main.rs:211:9:211:9 | v | main.rs:214:34:214:34 | v | provenance | |
-| main.rs:211:9:211:9 | v | main.rs:215:42:215:42 | v | provenance | |
-| main.rs:211:9:211:9 | v | main.rs:216:36:216:36 | v | provenance | |
-| main.rs:211:9:211:9 | v | main.rs:217:27:217:27 | v | provenance | |
-| main.rs:211:9:211:9 | v | main.rs:218:25:218:25 | v | provenance | |
-| main.rs:211:13:211:26 | ...::args | main.rs:211:13:211:28 | ...::args(...) [element] | provenance | Src:MaD:16 |
-| main.rs:211:13:211:28 | ...::args(...) [element] | main.rs:211:13:211:35 | ... .nth(...) [Some] | provenance | MaD:35 |
-| main.rs:211:13:211:35 | ... .nth(...) [Some] | main.rs:211:13:211:65 | ... .unwrap_or(...) | provenance | MaD:29 |
-| main.rs:211:13:211:65 | ... .unwrap_or(...) | main.rs:211:13:211:82 | ... .parse(...) [Ok] | provenance | MaD:32 |
-| main.rs:211:13:211:82 | ... .parse(...) [Ok] | main.rs:211:13:211:91 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:211:13:211:91 | ... .unwrap(...) | main.rs:211:9:211:9 | v | provenance | |
-| main.rs:214:34:214:34 | v | main.rs:12:36:12:43 | ...: usize | provenance | |
-| main.rs:215:42:215:42 | v | main.rs:43:44:43:51 | ...: usize | provenance | |
-| main.rs:216:36:216:36 | v | main.rs:81:38:81:45 | ...: usize | provenance | |
-| main.rs:217:27:217:27 | v | main.rs:128:29:128:36 | ...: usize | provenance | |
-| main.rs:218:25:218:25 | v | main.rs:162:27:162:34 | ...: usize | provenance | |
+| main.rs:224:24:224:41 | ...: String | main.rs:225:21:225:47 | user_input.parse(...) [Ok] | provenance | MaD:32 |
+| main.rs:225:9:225:17 | num_bytes | main.rs:227:54:227:62 | num_bytes | provenance | |
+| main.rs:225:21:225:47 | user_input.parse(...) [Ok] | main.rs:225:21:225:48 | TryExpr | provenance | |
+| main.rs:225:21:225:48 | TryExpr | main.rs:225:9:225:17 | num_bytes | provenance | |
+| main.rs:227:9:227:14 | layout | main.rs:229:40:229:45 | layout | provenance | |
+| main.rs:227:18:227:66 | ...::from_size_align(...) [Ok] | main.rs:227:18:227:75 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:227:18:227:75 | ... .unwrap(...) | main.rs:227:9:227:14 | layout | provenance | |
+| main.rs:227:54:227:62 | num_bytes | main.rs:227:18:227:66 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
+| main.rs:229:40:229:45 | layout | main.rs:229:22:229:38 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:237:25:237:42 | ...: String | main.rs:238:16:238:42 | user_input.parse(...) [Ok] | provenance | MaD:32 |
+| main.rs:238:9:238:12 | size | main.rs:242:9:242:17 | num_bytes | provenance | |
+| main.rs:238:16:238:42 | user_input.parse(...) [Ok] | main.rs:238:16:238:43 | TryExpr | provenance | |
+| main.rs:238:16:238:43 | TryExpr | main.rs:238:9:238:12 | size | provenance | |
+| main.rs:242:9:242:17 | num_bytes | main.rs:244:54:244:62 | num_bytes | provenance | |
+| main.rs:244:9:244:14 | layout | main.rs:246:40:246:45 | layout | provenance | |
+| main.rs:244:18:244:66 | ...::from_size_align(...) [Ok] | main.rs:244:18:244:75 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:244:18:244:75 | ... .unwrap(...) | main.rs:244:9:244:14 | layout | provenance | |
+| main.rs:244:54:244:62 | num_bytes | main.rs:244:18:244:66 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
+| main.rs:246:40:246:45 | layout | main.rs:246:22:246:38 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:253:25:253:38 | ...::args | main.rs:253:25:253:40 | ...::args(...) [element] | provenance | Src:MaD:16 |
+| main.rs:253:25:253:40 | ...::args(...) [element] | main.rs:253:25:253:47 | ... .nth(...) [Some] | provenance | MaD:35 |
+| main.rs:253:25:253:47 | ... .nth(...) [Some] | main.rs:253:25:253:74 | ... .unwrap_or(...) | provenance | MaD:29 |
+| main.rs:253:25:253:74 | ... .unwrap_or(...) | main.rs:224:24:224:41 | ...: String | provenance | |
+| main.rs:254:26:254:39 | ...::args | main.rs:254:26:254:41 | ...::args(...) [element] | provenance | Src:MaD:16 |
+| main.rs:254:26:254:41 | ...::args(...) [element] | main.rs:254:26:254:48 | ... .nth(...) [Some] | provenance | MaD:35 |
+| main.rs:254:26:254:48 | ... .nth(...) [Some] | main.rs:254:26:254:75 | ... .unwrap_or(...) | provenance | MaD:29 |
+| main.rs:254:26:254:75 | ... .unwrap_or(...) | main.rs:237:25:237:42 | ...: String | provenance | |
+| main.rs:262:9:262:9 | v | main.rs:265:34:265:34 | v | provenance | |
+| main.rs:262:9:262:9 | v | main.rs:266:42:266:42 | v | provenance | |
+| main.rs:262:9:262:9 | v | main.rs:267:36:267:36 | v | provenance | |
+| main.rs:262:9:262:9 | v | main.rs:268:27:268:27 | v | provenance | |
+| main.rs:262:9:262:9 | v | main.rs:269:25:269:25 | v | provenance | |
+| main.rs:262:13:262:26 | ...::args | main.rs:262:13:262:28 | ...::args(...) [element] | provenance | Src:MaD:16 |
+| main.rs:262:13:262:28 | ...::args(...) [element] | main.rs:262:13:262:35 | ... .nth(...) [Some] | provenance | MaD:35 |
+| main.rs:262:13:262:35 | ... .nth(...) [Some] | main.rs:262:13:262:65 | ... .unwrap_or(...) | provenance | MaD:29 |
+| main.rs:262:13:262:65 | ... .unwrap_or(...) | main.rs:262:13:262:82 | ... .parse(...) [Ok] | provenance | MaD:32 |
+| main.rs:262:13:262:82 | ... .parse(...) [Ok] | main.rs:262:13:262:91 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:262:13:262:91 | ... .unwrap(...) | main.rs:262:9:262:9 | v | provenance | |
+| main.rs:265:34:265:34 | v | main.rs:12:36:12:43 | ...: usize | provenance | |
+| main.rs:266:42:266:42 | v | main.rs:43:44:43:51 | ...: usize | provenance | |
+| main.rs:267:36:267:36 | v | main.rs:81:38:81:45 | ...: usize | provenance | |
+| main.rs:268:27:268:27 | v | main.rs:128:29:128:36 | ...: usize | provenance | |
+| main.rs:269:25:269:25 | v | main.rs:162:27:162:34 | ...: usize | provenance | |
models
| 1 | Sink: lang:alloc; ::allocate; alloc-layout; Argument[0] |
| 2 | Sink: lang:alloc; ::allocate_zeroed; alloc-layout; Argument[0] |
@@ -461,17 +490,46 @@ nodes
| main.rs:169:13:169:25 | ...::realloc | semmle.label | ...::realloc |
| main.rs:169:13:169:25 | ...::realloc | semmle.label | ...::realloc |
| main.rs:169:31:169:31 | v | semmle.label | v |
-| main.rs:211:9:211:9 | v | semmle.label | v |
-| main.rs:211:13:211:26 | ...::args | semmle.label | ...::args |
-| main.rs:211:13:211:28 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
-| main.rs:211:13:211:35 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
-| main.rs:211:13:211:65 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
-| main.rs:211:13:211:82 | ... .parse(...) [Ok] | semmle.label | ... .parse(...) [Ok] |
-| main.rs:211:13:211:91 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:214:34:214:34 | v | semmle.label | v |
-| main.rs:215:42:215:42 | v | semmle.label | v |
-| main.rs:216:36:216:36 | v | semmle.label | v |
-| main.rs:217:27:217:27 | v | semmle.label | v |
-| main.rs:218:25:218:25 | v | semmle.label | v |
+| main.rs:224:24:224:41 | ...: String | semmle.label | ...: String |
+| main.rs:225:9:225:17 | num_bytes | semmle.label | num_bytes |
+| main.rs:225:21:225:47 | user_input.parse(...) [Ok] | semmle.label | user_input.parse(...) [Ok] |
+| main.rs:225:21:225:48 | TryExpr | semmle.label | TryExpr |
+| main.rs:227:9:227:14 | layout | semmle.label | layout |
+| main.rs:227:18:227:66 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
+| main.rs:227:18:227:75 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:227:54:227:62 | num_bytes | semmle.label | num_bytes |
+| main.rs:229:22:229:38 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:229:40:229:45 | layout | semmle.label | layout |
+| main.rs:237:25:237:42 | ...: String | semmle.label | ...: String |
+| main.rs:238:9:238:12 | size | semmle.label | size |
+| main.rs:238:16:238:42 | user_input.parse(...) [Ok] | semmle.label | user_input.parse(...) [Ok] |
+| main.rs:238:16:238:43 | TryExpr | semmle.label | TryExpr |
+| main.rs:242:9:242:17 | num_bytes | semmle.label | num_bytes |
+| main.rs:244:9:244:14 | layout | semmle.label | layout |
+| main.rs:244:18:244:66 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
+| main.rs:244:18:244:75 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:244:54:244:62 | num_bytes | semmle.label | num_bytes |
+| main.rs:246:22:246:38 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:246:40:246:45 | layout | semmle.label | layout |
+| main.rs:253:25:253:38 | ...::args | semmle.label | ...::args |
+| main.rs:253:25:253:40 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
+| main.rs:253:25:253:47 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
+| main.rs:253:25:253:74 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
+| main.rs:254:26:254:39 | ...::args | semmle.label | ...::args |
+| main.rs:254:26:254:41 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
+| main.rs:254:26:254:48 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
+| main.rs:254:26:254:75 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
+| main.rs:262:9:262:9 | v | semmle.label | v |
+| main.rs:262:13:262:26 | ...::args | semmle.label | ...::args |
+| main.rs:262:13:262:28 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
+| main.rs:262:13:262:35 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
+| main.rs:262:13:262:65 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
+| main.rs:262:13:262:82 | ... .parse(...) [Ok] | semmle.label | ... .parse(...) [Ok] |
+| main.rs:262:13:262:91 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:265:34:265:34 | v | semmle.label | v |
+| main.rs:266:42:266:42 | v | semmle.label | v |
+| main.rs:267:36:267:36 | v | semmle.label | v |
+| main.rs:268:27:268:27 | v | semmle.label | v |
+| main.rs:269:25:269:25 | v | semmle.label | v |
subpaths
| main.rs:116:53:116:53 | v | main.rs:71:35:71:38 | ...: T | main.rs:77:9:77:16 | return v | main.rs:116:47:116:62 | clamp(...) |
diff --git a/rust/ql/test/query-tests/security/CWE-770/main.rs b/rust/ql/test/query-tests/security/CWE-770/main.rs
index d2b5c109fa77..a699767dc1a8 100644
--- a/rust/ql/test/query-tests/security/CWE-770/main.rs
+++ b/rust/ql/test/query-tests/security/CWE-770/main.rs
@@ -203,6 +203,57 @@ unsafe fn test_vectors(v: usize) {
let _ = Vec::::from_raw_parts_in(m7, 100, v, std::alloc::Global); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
}
+// --- examples from the qhelp ---
+
+struct Error {
+ msg: String,
+}
+
+impl From for Error {
+ fn from(err: std::num::ParseIntError) -> Self {
+ Error { msg: "ParseIntError".to_string() }
+ }
+}
+
+impl From<&str> for Error {
+ fn from(msg: &str) -> Self {
+ Error { msg: msg.to_string() }
+ }
+}
+
+fn allocate_buffer_bad(user_input: String) -> Result<*mut u8, Error> {
+ let num_bytes = user_input.parse::()? * std::mem::size_of::();
+
+ let layout = std::alloc::Layout::from_size_align(num_bytes, 1).unwrap();
+ unsafe {
+ let buffer = std::alloc::alloc(layout); // $ Alert[rust/uncontrolled-allocation-size]=example1
+
+ Ok(buffer)
+ }
+}
+
+const BUFFER_LIMIT: usize = 10 * 1024;
+
+fn allocate_buffer_good(user_input: String) -> Result<*mut u8, Error> {
+ let size = user_input.parse::()?;
+ if (size > BUFFER_LIMIT) {
+ return Err("Size exceeds limit".into());
+ }
+ let num_bytes = size * std::mem::size_of::();
+
+ let layout = std::alloc::Layout::from_size_align(num_bytes, 1).unwrap();
+ unsafe {
+ let buffer = std::alloc::alloc(layout); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=example2
+
+ Ok(buffer)
+ }
+}
+
+fn test_examples() {
+ allocate_buffer_bad(std::env::args().nth(1).unwrap_or("0".to_string())); // $ Source=example1
+ allocate_buffer_good(std::env::args().nth(1).unwrap_or("0".to_string())); // $ Source=example2
+}
+
// --- main ---
fn main() {
@@ -217,6 +268,7 @@ fn main() {
test_system_alloc(v);
test_libc_alloc(v);
test_vectors(v);
+ test_examples();
}
println!("--- end ---");
From cdd5cb05237dd1300945f4888af1a1236fe53063 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 31 Mar 2025 09:28:10 +0100
Subject: [PATCH 086/409] Rust: More test cases for bounds / guards.
---
.../UncontrolledAllocationSize.expected | 780 +++++++++++-------
.../test/query-tests/security/CWE-770/main.rs | 83 +-
2 files changed, 537 insertions(+), 326 deletions(-)
diff --git a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
index 7ef8327b64ed..cca67133563a 100644
--- a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
+++ b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
@@ -1,54 +1,66 @@
#select
-| main.rs:18:13:18:31 | ...::realloc | main.rs:262:13:262:26 | ...::args | main.rs:18:13:18:31 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:21:13:21:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:21:13:21:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:22:13:22:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:22:13:22:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:23:13:23:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:23:13:23:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:24:13:24:36 | ...::alloc_zeroed | main.rs:262:13:262:26 | ...::args | main.rs:24:13:24:36 | ...::alloc_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:30:13:30:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:30:13:30:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:33:13:33:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:33:13:33:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:37:13:37:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:37:13:37:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:40:13:40:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:40:13:40:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:50:13:50:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:50:13:50:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:51:13:51:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:51:13:51:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:53:13:53:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:53:13:53:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:54:13:54:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:54:13:54:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:59:13:59:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:59:13:59:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:61:13:61:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:61:13:61:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:63:13:63:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:63:13:63:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:64:13:64:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:64:13:64:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:65:13:65:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:65:13:65:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:68:13:68:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:68:13:68:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:85:17:85:33 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:85:17:85:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:87:17:87:33 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:87:17:87:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:91:17:91:33 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:91:17:91:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:93:17:93:33 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:93:17:93:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:104:17:104:33 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:104:17:104:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:107:17:107:33 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:107:17:107:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:111:13:111:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:111:13:111:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:114:13:114:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:114:13:114:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:117:13:117:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:117:13:117:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:119:13:119:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:119:13:119:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:123:13:123:29 | ...::alloc | main.rs:262:13:262:26 | ...::args | main.rs:123:13:123:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:138:32:138:36 | alloc | main.rs:262:13:262:26 | ...::args | main.rs:138:32:138:36 | alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:139:32:139:43 | alloc_zeroed | main.rs:262:13:262:26 | ...::args | main.rs:139:32:139:43 | alloc_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:140:32:140:39 | allocate | main.rs:262:13:262:26 | ...::args | main.rs:140:32:140:39 | allocate | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:141:32:141:46 | allocate_zeroed | main.rs:262:13:262:26 | ...::args | main.rs:141:32:141:46 | allocate_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:142:32:142:39 | allocate | main.rs:262:13:262:26 | ...::args | main.rs:142:32:142:39 | allocate | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:143:32:143:46 | allocate_zeroed | main.rs:262:13:262:26 | ...::args | main.rs:143:32:143:46 | allocate_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:153:40:153:43 | grow | main.rs:262:13:262:26 | ...::args | main.rs:153:40:153:43 | grow | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:155:40:155:50 | grow_zeroed | main.rs:262:13:262:26 | ...::args | main.rs:155:40:155:50 | grow_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:164:13:164:24 | ...::malloc | main.rs:262:13:262:26 | ...::args | main.rs:164:13:164:24 | ...::malloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:164:13:164:24 | ...::malloc | main.rs:262:13:262:26 | ...::args | main.rs:164:13:164:24 | ...::malloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:165:13:165:31 | ...::aligned_alloc | main.rs:262:13:262:26 | ...::args | main.rs:165:13:165:31 | ...::aligned_alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:165:13:165:31 | ...::aligned_alloc | main.rs:262:13:262:26 | ...::args | main.rs:165:13:165:31 | ...::aligned_alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:167:13:167:24 | ...::calloc | main.rs:262:13:262:26 | ...::args | main.rs:167:13:167:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:167:13:167:24 | ...::calloc | main.rs:262:13:262:26 | ...::args | main.rs:167:13:167:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:168:13:168:24 | ...::calloc | main.rs:262:13:262:26 | ...::args | main.rs:168:13:168:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:168:13:168:24 | ...::calloc | main.rs:262:13:262:26 | ...::args | main.rs:168:13:168:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:169:13:169:25 | ...::realloc | main.rs:262:13:262:26 | ...::args | main.rs:169:13:169:25 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:169:13:169:25 | ...::realloc | main.rs:262:13:262:26 | ...::args | main.rs:169:13:169:25 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:262:13:262:26 | ...::args | user-provided value |
-| main.rs:229:22:229:38 | ...::alloc | main.rs:253:25:253:38 | ...::args | main.rs:229:22:229:38 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:253:25:253:38 | ...::args | user-provided value |
-| main.rs:246:22:246:38 | ...::alloc | main.rs:254:26:254:39 | ...::args | main.rs:246:22:246:38 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:254:26:254:39 | ...::args | user-provided value |
+| main.rs:18:13:18:31 | ...::realloc | main.rs:317:13:317:26 | ...::args | main.rs:18:13:18:31 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:21:13:21:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:21:13:21:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:22:13:22:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:22:13:22:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:23:13:23:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:23:13:23:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:24:13:24:36 | ...::alloc_zeroed | main.rs:317:13:317:26 | ...::args | main.rs:24:13:24:36 | ...::alloc_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:30:13:30:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:30:13:30:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:33:13:33:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:33:13:33:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:37:13:37:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:37:13:37:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:40:13:40:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:40:13:40:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:50:13:50:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:50:13:50:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:51:13:51:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:51:13:51:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:53:13:53:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:53:13:53:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:54:13:54:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:54:13:54:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:59:13:59:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:59:13:59:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:61:13:61:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:61:13:61:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:63:13:63:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:63:13:63:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:64:13:64:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:64:13:64:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:65:13:65:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:65:13:65:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:68:13:68:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:68:13:68:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:83:13:83:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:83:13:83:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:88:13:88:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:88:13:88:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:96:17:96:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:96:17:96:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:97:17:97:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:97:17:97:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:102:17:102:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:102:17:102:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:103:17:103:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:103:17:103:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:109:17:109:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:109:17:109:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:111:17:111:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:111:17:111:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:116:17:116:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:116:17:116:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:121:17:121:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:121:17:121:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:126:17:126:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:126:17:126:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:135:13:135:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:135:13:135:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:146:17:146:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:146:17:146:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:147:17:147:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:147:17:147:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:148:17:148:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:148:17:148:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:152:13:152:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:152:13:152:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:155:13:155:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:155:13:155:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:158:13:158:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:158:13:158:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:162:17:162:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:162:17:162:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:169:17:169:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:169:17:169:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:170:17:170:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:170:17:170:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:177:13:177:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:177:13:177:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:178:13:178:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:178:13:178:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:193:32:193:36 | alloc | main.rs:317:13:317:26 | ...::args | main.rs:193:32:193:36 | alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:194:32:194:43 | alloc_zeroed | main.rs:317:13:317:26 | ...::args | main.rs:194:32:194:43 | alloc_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:195:32:195:39 | allocate | main.rs:317:13:317:26 | ...::args | main.rs:195:32:195:39 | allocate | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:196:32:196:46 | allocate_zeroed | main.rs:317:13:317:26 | ...::args | main.rs:196:32:196:46 | allocate_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:197:32:197:39 | allocate | main.rs:317:13:317:26 | ...::args | main.rs:197:32:197:39 | allocate | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:198:32:198:46 | allocate_zeroed | main.rs:317:13:317:26 | ...::args | main.rs:198:32:198:46 | allocate_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:208:40:208:43 | grow | main.rs:317:13:317:26 | ...::args | main.rs:208:40:208:43 | grow | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:210:40:210:50 | grow_zeroed | main.rs:317:13:317:26 | ...::args | main.rs:210:40:210:50 | grow_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:219:13:219:24 | ...::malloc | main.rs:317:13:317:26 | ...::args | main.rs:219:13:219:24 | ...::malloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:219:13:219:24 | ...::malloc | main.rs:317:13:317:26 | ...::args | main.rs:219:13:219:24 | ...::malloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:220:13:220:31 | ...::aligned_alloc | main.rs:317:13:317:26 | ...::args | main.rs:220:13:220:31 | ...::aligned_alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:220:13:220:31 | ...::aligned_alloc | main.rs:317:13:317:26 | ...::args | main.rs:220:13:220:31 | ...::aligned_alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:222:13:222:24 | ...::calloc | main.rs:317:13:317:26 | ...::args | main.rs:222:13:222:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:222:13:222:24 | ...::calloc | main.rs:317:13:317:26 | ...::args | main.rs:222:13:222:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:223:13:223:24 | ...::calloc | main.rs:317:13:317:26 | ...::args | main.rs:223:13:223:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:223:13:223:24 | ...::calloc | main.rs:317:13:317:26 | ...::args | main.rs:223:13:223:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:224:13:224:25 | ...::realloc | main.rs:317:13:317:26 | ...::args | main.rs:224:13:224:25 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:224:13:224:25 | ...::realloc | main.rs:317:13:317:26 | ...::args | main.rs:224:13:224:25 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
+| main.rs:284:22:284:38 | ...::alloc | main.rs:308:25:308:38 | ...::args | main.rs:284:22:284:38 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:308:25:308:38 | ...::args | user-provided value |
+| main.rs:301:22:301:38 | ...::alloc | main.rs:309:26:309:39 | ...::args | main.rs:301:22:301:38 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:309:26:309:39 | ...::args | user-provided value |
edges
| main.rs:12:36:12:43 | ...: usize | main.rs:18:41:18:41 | v | provenance | |
| main.rs:18:41:18:41 | v | main.rs:18:13:18:31 | ...::realloc | provenance | MaD:5 Sink:MaD:5 |
@@ -140,138 +152,210 @@ edges
| main.rs:67:46:67:46 | v | main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:68:31:68:32 | l4 | main.rs:68:13:68:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:71:35:71:38 | ...: T | main.rs:77:9:77:16 | return v | provenance | |
-| main.rs:81:38:81:45 | ...: usize | main.rs:82:47:82:47 | v | provenance | |
-| main.rs:81:38:81:45 | ...: usize | main.rs:97:13:97:21 | mut v_mut | provenance | |
-| main.rs:81:38:81:45 | ...: usize | main.rs:106:51:106:51 | v | provenance | |
-| main.rs:81:38:81:45 | ...: usize | main.rs:110:61:110:61 | v | provenance | |
-| main.rs:81:38:81:45 | ...: usize | main.rs:113:61:113:61 | v | provenance | |
-| main.rs:81:38:81:45 | ...: usize | main.rs:116:53:116:53 | v | provenance | |
-| main.rs:82:9:82:10 | l1 | main.rs:85:35:85:36 | l1 | provenance | |
-| main.rs:82:9:82:10 | l1 | main.rs:87:35:87:36 | l1 | provenance | |
-| main.rs:82:14:82:48 | ...::array::<...>(...) [Ok] | main.rs:82:14:82:57 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:82:14:82:57 | ... .unwrap(...) | main.rs:82:9:82:10 | l1 | provenance | |
-| main.rs:82:47:82:47 | v | main.rs:82:14:82:48 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
-| main.rs:85:35:85:36 | l1 | main.rs:85:17:85:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:85:35:85:36 | l1 | main.rs:91:35:91:36 | l1 | provenance | |
-| main.rs:85:35:85:36 | l1 | main.rs:93:35:93:36 | l1 | provenance | |
-| main.rs:87:35:87:36 | l1 | main.rs:87:17:87:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:87:35:87:36 | l1 | main.rs:91:35:91:36 | l1 | provenance | |
-| main.rs:87:35:87:36 | l1 | main.rs:93:35:93:36 | l1 | provenance | |
-| main.rs:91:35:91:36 | l1 | main.rs:91:17:91:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:91:35:91:36 | l1 | main.rs:119:31:119:32 | l1 | provenance | |
-| main.rs:93:35:93:36 | l1 | main.rs:93:17:93:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:93:35:93:36 | l1 | main.rs:119:31:119:32 | l1 | provenance | |
-| main.rs:97:13:97:21 | mut v_mut | main.rs:103:51:103:55 | v_mut | provenance | |
-| main.rs:103:13:103:14 | l2 | main.rs:104:35:104:36 | l2 | provenance | |
-| main.rs:103:18:103:56 | ...::array::<...>(...) [Ok] | main.rs:103:18:103:65 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:103:18:103:65 | ... .unwrap(...) | main.rs:103:13:103:14 | l2 | provenance | |
-| main.rs:103:51:103:55 | v_mut | main.rs:103:18:103:56 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
-| main.rs:104:35:104:36 | l2 | main.rs:104:17:104:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:106:13:106:14 | l3 | main.rs:107:35:107:36 | l3 | provenance | |
-| main.rs:106:18:106:52 | ...::array::<...>(...) [Ok] | main.rs:106:18:106:61 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:106:18:106:61 | ... .unwrap(...) | main.rs:106:13:106:14 | l3 | provenance | |
-| main.rs:106:51:106:51 | v | main.rs:106:18:106:52 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
-| main.rs:107:35:107:36 | l3 | main.rs:107:17:107:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:110:9:110:10 | l4 | main.rs:111:31:111:32 | l4 | provenance | |
-| main.rs:110:14:110:68 | ...::array::<...>(...) [Ok] | main.rs:110:14:110:77 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:110:14:110:77 | ... .unwrap(...) | main.rs:110:9:110:10 | l4 | provenance | |
-| main.rs:110:47:110:67 | ...::min(...) | main.rs:110:14:110:68 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
-| main.rs:110:61:110:61 | v | main.rs:110:47:110:67 | ...::min(...) | provenance | MaD:34 |
-| main.rs:111:31:111:32 | l4 | main.rs:111:13:111:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:113:9:113:10 | l5 | main.rs:114:31:114:32 | l5 | provenance | |
-| main.rs:113:14:113:68 | ...::array::<...>(...) [Ok] | main.rs:113:14:113:77 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:113:14:113:77 | ... .unwrap(...) | main.rs:113:9:113:10 | l5 | provenance | |
-| main.rs:113:47:113:67 | ...::max(...) | main.rs:113:14:113:68 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
-| main.rs:113:61:113:61 | v | main.rs:113:47:113:67 | ...::max(...) | provenance | MaD:33 |
-| main.rs:114:31:114:32 | l5 | main.rs:114:13:114:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:116:9:116:10 | l6 | main.rs:117:31:117:32 | l6 | provenance | |
-| main.rs:116:14:116:63 | ...::array::<...>(...) [Ok] | main.rs:116:14:116:72 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:116:14:116:72 | ... .unwrap(...) | main.rs:116:9:116:10 | l6 | provenance | |
-| main.rs:116:47:116:62 | clamp(...) | main.rs:116:14:116:63 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
-| main.rs:116:53:116:53 | v | main.rs:71:35:71:38 | ...: T | provenance | |
-| main.rs:116:53:116:53 | v | main.rs:116:47:116:62 | clamp(...) | provenance | |
-| main.rs:117:31:117:32 | l6 | main.rs:117:13:117:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:119:31:119:32 | l1 | main.rs:119:13:119:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:119:31:119:32 | l1 | main.rs:123:31:123:32 | l1 | provenance | |
-| main.rs:123:31:123:32 | l1 | main.rs:123:13:123:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:128:29:128:36 | ...: usize | main.rs:137:46:137:46 | v | provenance | |
-| main.rs:137:9:137:10 | l2 | main.rs:138:38:138:39 | l2 | provenance | |
-| main.rs:137:14:137:47 | ...::array::<...>(...) [Ok] | main.rs:137:14:137:56 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:137:14:137:56 | ... .unwrap(...) | main.rs:137:9:137:10 | l2 | provenance | |
-| main.rs:137:46:137:46 | v | main.rs:137:14:137:47 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
-| main.rs:138:38:138:39 | l2 | main.rs:138:32:138:36 | alloc | provenance | MaD:10 Sink:MaD:10 |
-| main.rs:138:38:138:39 | l2 | main.rs:139:45:139:46 | l2 | provenance | |
-| main.rs:139:45:139:46 | l2 | main.rs:139:32:139:43 | alloc_zeroed | provenance | MaD:11 Sink:MaD:11 |
-| main.rs:139:45:139:46 | l2 | main.rs:140:41:140:42 | l2 | provenance | |
-| main.rs:140:41:140:42 | l2 | main.rs:140:32:140:39 | allocate | provenance | MaD:6 Sink:MaD:6 |
-| main.rs:140:41:140:42 | l2 | main.rs:141:48:141:49 | l2 | provenance | |
-| main.rs:141:48:141:49 | l2 | main.rs:141:32:141:46 | allocate_zeroed | provenance | MaD:7 Sink:MaD:7 |
-| main.rs:141:48:141:49 | l2 | main.rs:142:41:142:42 | l2 | provenance | |
-| main.rs:142:41:142:42 | l2 | main.rs:142:32:142:39 | allocate | provenance | MaD:1 Sink:MaD:1 |
-| main.rs:142:41:142:42 | l2 | main.rs:143:48:143:49 | l2 | provenance | |
-| main.rs:143:48:143:49 | l2 | main.rs:143:32:143:46 | allocate_zeroed | provenance | MaD:2 Sink:MaD:2 |
-| main.rs:143:48:143:49 | l2 | main.rs:153:53:153:54 | l2 | provenance | |
-| main.rs:143:48:143:49 | l2 | main.rs:155:60:155:61 | l2 | provenance | |
-| main.rs:153:53:153:54 | l2 | main.rs:153:40:153:43 | grow | provenance | MaD:8 Sink:MaD:8 |
-| main.rs:155:60:155:61 | l2 | main.rs:155:40:155:50 | grow_zeroed | provenance | MaD:9 Sink:MaD:9 |
-| main.rs:162:27:162:34 | ...: usize | main.rs:164:26:164:26 | v | provenance | |
-| main.rs:164:26:164:26 | v | main.rs:164:13:164:24 | ...::malloc | provenance | MaD:14 Sink:MaD:14 |
-| main.rs:164:26:164:26 | v | main.rs:164:13:164:24 | ...::malloc | provenance | MaD:14 Sink:MaD:14 |
-| main.rs:164:26:164:26 | v | main.rs:165:36:165:36 | v | provenance | |
-| main.rs:165:36:165:36 | v | main.rs:165:13:165:31 | ...::aligned_alloc | provenance | MaD:12 Sink:MaD:12 |
-| main.rs:165:36:165:36 | v | main.rs:165:13:165:31 | ...::aligned_alloc | provenance | MaD:12 Sink:MaD:12 |
-| main.rs:165:36:165:36 | v | main.rs:167:30:167:30 | v | provenance | |
-| main.rs:167:30:167:30 | v | main.rs:167:13:167:24 | ...::calloc | provenance | MaD:13 Sink:MaD:13 |
-| main.rs:167:30:167:30 | v | main.rs:167:13:167:24 | ...::calloc | provenance | MaD:13 Sink:MaD:13 |
-| main.rs:167:30:167:30 | v | main.rs:168:26:168:26 | v | provenance | |
-| main.rs:168:26:168:26 | v | main.rs:168:13:168:24 | ...::calloc | provenance | MaD:13 Sink:MaD:13 |
-| main.rs:168:26:168:26 | v | main.rs:168:13:168:24 | ...::calloc | provenance | MaD:13 Sink:MaD:13 |
-| main.rs:168:26:168:26 | v | main.rs:169:31:169:31 | v | provenance | |
-| main.rs:169:31:169:31 | v | main.rs:169:13:169:25 | ...::realloc | provenance | MaD:15 Sink:MaD:15 |
-| main.rs:169:31:169:31 | v | main.rs:169:13:169:25 | ...::realloc | provenance | MaD:15 Sink:MaD:15 |
-| main.rs:224:24:224:41 | ...: String | main.rs:225:21:225:47 | user_input.parse(...) [Ok] | provenance | MaD:32 |
-| main.rs:225:9:225:17 | num_bytes | main.rs:227:54:227:62 | num_bytes | provenance | |
-| main.rs:225:21:225:47 | user_input.parse(...) [Ok] | main.rs:225:21:225:48 | TryExpr | provenance | |
-| main.rs:225:21:225:48 | TryExpr | main.rs:225:9:225:17 | num_bytes | provenance | |
-| main.rs:227:9:227:14 | layout | main.rs:229:40:229:45 | layout | provenance | |
-| main.rs:227:18:227:66 | ...::from_size_align(...) [Ok] | main.rs:227:18:227:75 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:227:18:227:75 | ... .unwrap(...) | main.rs:227:9:227:14 | layout | provenance | |
-| main.rs:227:54:227:62 | num_bytes | main.rs:227:18:227:66 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
-| main.rs:229:40:229:45 | layout | main.rs:229:22:229:38 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:237:25:237:42 | ...: String | main.rs:238:16:238:42 | user_input.parse(...) [Ok] | provenance | MaD:32 |
-| main.rs:238:9:238:12 | size | main.rs:242:9:242:17 | num_bytes | provenance | |
-| main.rs:238:16:238:42 | user_input.parse(...) [Ok] | main.rs:238:16:238:43 | TryExpr | provenance | |
-| main.rs:238:16:238:43 | TryExpr | main.rs:238:9:238:12 | size | provenance | |
-| main.rs:242:9:242:17 | num_bytes | main.rs:244:54:244:62 | num_bytes | provenance | |
-| main.rs:244:9:244:14 | layout | main.rs:246:40:246:45 | layout | provenance | |
-| main.rs:244:18:244:66 | ...::from_size_align(...) [Ok] | main.rs:244:18:244:75 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:244:18:244:75 | ... .unwrap(...) | main.rs:244:9:244:14 | layout | provenance | |
-| main.rs:244:54:244:62 | num_bytes | main.rs:244:18:244:66 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
-| main.rs:246:40:246:45 | layout | main.rs:246:22:246:38 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:253:25:253:38 | ...::args | main.rs:253:25:253:40 | ...::args(...) [element] | provenance | Src:MaD:16 |
-| main.rs:253:25:253:40 | ...::args(...) [element] | main.rs:253:25:253:47 | ... .nth(...) [Some] | provenance | MaD:35 |
-| main.rs:253:25:253:47 | ... .nth(...) [Some] | main.rs:253:25:253:74 | ... .unwrap_or(...) | provenance | MaD:29 |
-| main.rs:253:25:253:74 | ... .unwrap_or(...) | main.rs:224:24:224:41 | ...: String | provenance | |
-| main.rs:254:26:254:39 | ...::args | main.rs:254:26:254:41 | ...::args(...) [element] | provenance | Src:MaD:16 |
-| main.rs:254:26:254:41 | ...::args(...) [element] | main.rs:254:26:254:48 | ... .nth(...) [Some] | provenance | MaD:35 |
-| main.rs:254:26:254:48 | ... .nth(...) [Some] | main.rs:254:26:254:75 | ... .unwrap_or(...) | provenance | MaD:29 |
-| main.rs:254:26:254:75 | ... .unwrap_or(...) | main.rs:237:25:237:42 | ...: String | provenance | |
-| main.rs:262:9:262:9 | v | main.rs:265:34:265:34 | v | provenance | |
-| main.rs:262:9:262:9 | v | main.rs:266:42:266:42 | v | provenance | |
-| main.rs:262:9:262:9 | v | main.rs:267:36:267:36 | v | provenance | |
-| main.rs:262:9:262:9 | v | main.rs:268:27:268:27 | v | provenance | |
-| main.rs:262:9:262:9 | v | main.rs:269:25:269:25 | v | provenance | |
-| main.rs:262:13:262:26 | ...::args | main.rs:262:13:262:28 | ...::args(...) [element] | provenance | Src:MaD:16 |
-| main.rs:262:13:262:28 | ...::args(...) [element] | main.rs:262:13:262:35 | ... .nth(...) [Some] | provenance | MaD:35 |
-| main.rs:262:13:262:35 | ... .nth(...) [Some] | main.rs:262:13:262:65 | ... .unwrap_or(...) | provenance | MaD:29 |
-| main.rs:262:13:262:65 | ... .unwrap_or(...) | main.rs:262:13:262:82 | ... .parse(...) [Ok] | provenance | MaD:32 |
-| main.rs:262:13:262:82 | ... .parse(...) [Ok] | main.rs:262:13:262:91 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:262:13:262:91 | ... .unwrap(...) | main.rs:262:9:262:9 | v | provenance | |
-| main.rs:265:34:265:34 | v | main.rs:12:36:12:43 | ...: usize | provenance | |
-| main.rs:266:42:266:42 | v | main.rs:43:44:43:51 | ...: usize | provenance | |
-| main.rs:267:36:267:36 | v | main.rs:81:38:81:45 | ...: usize | provenance | |
-| main.rs:268:27:268:27 | v | main.rs:128:29:128:36 | ...: usize | provenance | |
-| main.rs:269:25:269:25 | v | main.rs:162:27:162:34 | ...: usize | provenance | |
+| main.rs:81:33:81:40 | ...: usize | main.rs:82:54:82:54 | v | provenance | |
+| main.rs:82:9:82:14 | layout | main.rs:83:31:83:36 | layout | provenance | |
+| main.rs:82:18:82:58 | ...::from_size_align(...) [Ok] | main.rs:82:18:82:67 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:82:18:82:67 | ... .unwrap(...) | main.rs:82:9:82:14 | layout | provenance | |
+| main.rs:82:54:82:54 | v | main.rs:82:18:82:58 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
+| main.rs:83:31:83:36 | layout | main.rs:83:13:83:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:86:35:86:42 | ...: usize | main.rs:87:54:87:54 | v | provenance | |
+| main.rs:87:9:87:14 | layout | main.rs:88:31:88:36 | layout | provenance | |
+| main.rs:87:18:87:58 | ...::from_size_align(...) [Ok] | main.rs:87:18:87:67 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:87:18:87:67 | ... .unwrap(...) | main.rs:87:9:87:14 | layout | provenance | |
+| main.rs:87:54:87:54 | v | main.rs:87:18:87:58 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
+| main.rs:88:31:88:36 | layout | main.rs:88:13:88:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:91:38:91:45 | ...: usize | main.rs:92:47:92:47 | v | provenance | |
+| main.rs:91:38:91:45 | ...: usize | main.rs:95:51:95:51 | v | provenance | |
+| main.rs:91:38:91:45 | ...: usize | main.rs:99:31:99:31 | v | provenance | |
+| main.rs:91:38:91:45 | ...: usize | main.rs:101:51:101:51 | v | provenance | |
+| main.rs:91:38:91:45 | ...: usize | main.rs:105:33:105:33 | v | provenance | |
+| main.rs:91:38:91:45 | ...: usize | main.rs:115:54:115:54 | v | provenance | |
+| main.rs:91:38:91:45 | ...: usize | main.rs:120:54:120:54 | v | provenance | |
+| main.rs:91:38:91:45 | ...: usize | main.rs:125:54:125:54 | v | provenance | |
+| main.rs:91:38:91:45 | ...: usize | main.rs:131:50:131:50 | v | provenance | |
+| main.rs:91:38:91:45 | ...: usize | main.rs:138:13:138:21 | mut v_mut | provenance | |
+| main.rs:91:38:91:45 | ...: usize | main.rs:145:51:145:51 | v | provenance | |
+| main.rs:91:38:91:45 | ...: usize | main.rs:151:62:151:62 | v | provenance | |
+| main.rs:91:38:91:45 | ...: usize | main.rs:154:62:154:62 | v | provenance | |
+| main.rs:91:38:91:45 | ...: usize | main.rs:157:54:157:54 | v | provenance | |
+| main.rs:91:38:91:45 | ...: usize | main.rs:161:55:161:55 | v | provenance | |
+| main.rs:91:38:91:45 | ...: usize | main.rs:168:55:168:55 | v | provenance | |
+| main.rs:91:38:91:45 | ...: usize | main.rs:176:51:176:51 | v | provenance | |
+| main.rs:92:9:92:10 | l1 | main.rs:96:35:96:36 | l1 | provenance | |
+| main.rs:92:9:92:10 | l1 | main.rs:102:35:102:36 | l1 | provenance | |
+| main.rs:92:14:92:48 | ...::array::<...>(...) [Ok] | main.rs:92:14:92:57 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:92:14:92:57 | ... .unwrap(...) | main.rs:92:9:92:10 | l1 | provenance | |
+| main.rs:92:47:92:47 | v | main.rs:92:14:92:48 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
+| main.rs:95:13:95:14 | l2 | main.rs:97:35:97:36 | l2 | provenance | |
+| main.rs:95:18:95:52 | ...::array::<...>(...) [Ok] | main.rs:95:18:95:61 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:95:18:95:61 | ... .unwrap(...) | main.rs:95:13:95:14 | l2 | provenance | |
+| main.rs:95:51:95:51 | v | main.rs:95:18:95:52 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
+| main.rs:96:35:96:36 | l1 | main.rs:96:17:96:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:96:35:96:36 | l1 | main.rs:109:35:109:36 | l1 | provenance | |
+| main.rs:96:35:96:36 | l1 | main.rs:111:35:111:36 | l1 | provenance | |
+| main.rs:97:35:97:36 | l2 | main.rs:97:17:97:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:99:31:99:31 | v | main.rs:81:33:81:40 | ...: usize | provenance | |
+| main.rs:101:13:101:14 | l3 | main.rs:103:35:103:36 | l3 | provenance | |
+| main.rs:101:18:101:52 | ...::array::<...>(...) [Ok] | main.rs:101:18:101:61 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:101:18:101:61 | ... .unwrap(...) | main.rs:101:13:101:14 | l3 | provenance | |
+| main.rs:101:51:101:51 | v | main.rs:101:18:101:52 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
+| main.rs:102:35:102:36 | l1 | main.rs:102:17:102:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:102:35:102:36 | l1 | main.rs:109:35:109:36 | l1 | provenance | |
+| main.rs:102:35:102:36 | l1 | main.rs:111:35:111:36 | l1 | provenance | |
+| main.rs:103:35:103:36 | l3 | main.rs:103:17:103:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:105:33:105:33 | v | main.rs:86:35:86:42 | ...: usize | provenance | |
+| main.rs:109:35:109:36 | l1 | main.rs:109:17:109:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:109:35:109:36 | l1 | main.rs:146:35:146:36 | l1 | provenance | |
+| main.rs:111:35:111:36 | l1 | main.rs:111:17:111:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:111:35:111:36 | l1 | main.rs:146:35:146:36 | l1 | provenance | |
+| main.rs:115:13:115:14 | l4 | main.rs:116:35:116:36 | l4 | provenance | |
+| main.rs:115:18:115:58 | ...::from_size_align(...) [Ok] | main.rs:115:18:115:67 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:115:18:115:67 | ... .unwrap(...) | main.rs:115:13:115:14 | l4 | provenance | |
+| main.rs:115:54:115:54 | v | main.rs:115:18:115:58 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
+| main.rs:116:35:116:36 | l4 | main.rs:116:17:116:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:120:13:120:14 | l5 | main.rs:121:35:121:36 | l5 | provenance | |
+| main.rs:120:18:120:58 | ...::from_size_align(...) [Ok] | main.rs:120:18:120:67 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:120:18:120:67 | ... .unwrap(...) | main.rs:120:13:120:14 | l5 | provenance | |
+| main.rs:120:54:120:54 | v | main.rs:120:18:120:58 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
+| main.rs:121:35:121:36 | l5 | main.rs:121:17:121:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:125:13:125:14 | l6 | main.rs:126:35:126:36 | l6 | provenance | |
+| main.rs:125:18:125:58 | ...::from_size_align(...) [Ok] | main.rs:125:18:125:67 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:125:18:125:67 | ... .unwrap(...) | main.rs:125:13:125:14 | l6 | provenance | |
+| main.rs:125:54:125:54 | v | main.rs:125:18:125:58 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
+| main.rs:126:35:126:36 | l6 | main.rs:126:17:126:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:131:9:131:10 | l7 | main.rs:135:31:135:32 | l7 | provenance | |
+| main.rs:131:14:131:54 | ...::from_size_align(...) [Ok] | main.rs:131:14:131:63 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:131:14:131:63 | ... .unwrap(...) | main.rs:131:9:131:10 | l7 | provenance | |
+| main.rs:131:50:131:50 | v | main.rs:131:14:131:54 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
+| main.rs:135:31:135:32 | l7 | main.rs:135:13:135:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:138:13:138:21 | mut v_mut | main.rs:144:51:144:55 | v_mut | provenance | |
+| main.rs:144:13:144:14 | l8 | main.rs:147:35:147:36 | l8 | provenance | |
+| main.rs:144:18:144:56 | ...::array::<...>(...) [Ok] | main.rs:144:18:144:65 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:144:18:144:65 | ... .unwrap(...) | main.rs:144:13:144:14 | l8 | provenance | |
+| main.rs:144:51:144:55 | v_mut | main.rs:144:18:144:56 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
+| main.rs:145:13:145:14 | l9 | main.rs:148:35:148:36 | l9 | provenance | |
+| main.rs:145:18:145:52 | ...::array::<...>(...) [Ok] | main.rs:145:18:145:61 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:145:18:145:61 | ... .unwrap(...) | main.rs:145:13:145:14 | l9 | provenance | |
+| main.rs:145:51:145:51 | v | main.rs:145:18:145:52 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
+| main.rs:146:35:146:36 | l1 | main.rs:146:17:146:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:146:35:146:36 | l1 | main.rs:177:31:177:32 | l1 | provenance | |
+| main.rs:147:35:147:36 | l8 | main.rs:147:17:147:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:148:35:148:36 | l9 | main.rs:148:17:148:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:151:9:151:11 | l10 | main.rs:152:31:152:33 | l10 | provenance | |
+| main.rs:151:15:151:69 | ...::array::<...>(...) [Ok] | main.rs:151:15:151:78 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:151:15:151:78 | ... .unwrap(...) | main.rs:151:9:151:11 | l10 | provenance | |
+| main.rs:151:48:151:68 | ...::min(...) | main.rs:151:15:151:69 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
+| main.rs:151:62:151:62 | v | main.rs:151:48:151:68 | ...::min(...) | provenance | MaD:34 |
+| main.rs:152:31:152:33 | l10 | main.rs:152:13:152:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:154:9:154:11 | l11 | main.rs:155:31:155:33 | l11 | provenance | |
+| main.rs:154:15:154:69 | ...::array::<...>(...) [Ok] | main.rs:154:15:154:78 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:154:15:154:78 | ... .unwrap(...) | main.rs:154:9:154:11 | l11 | provenance | |
+| main.rs:154:48:154:68 | ...::max(...) | main.rs:154:15:154:69 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
+| main.rs:154:62:154:62 | v | main.rs:154:48:154:68 | ...::max(...) | provenance | MaD:33 |
+| main.rs:155:31:155:33 | l11 | main.rs:155:13:155:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:157:9:157:11 | l12 | main.rs:158:31:158:33 | l12 | provenance | |
+| main.rs:157:15:157:64 | ...::array::<...>(...) [Ok] | main.rs:157:15:157:73 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:157:15:157:73 | ... .unwrap(...) | main.rs:157:9:157:11 | l12 | provenance | |
+| main.rs:157:48:157:63 | clamp(...) | main.rs:157:15:157:64 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
+| main.rs:157:54:157:54 | v | main.rs:71:35:71:38 | ...: T | provenance | |
+| main.rs:157:54:157:54 | v | main.rs:157:48:157:63 | clamp(...) | provenance | |
+| main.rs:158:31:158:33 | l12 | main.rs:158:13:158:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:161:13:161:15 | l13 | main.rs:162:35:162:37 | l13 | provenance | |
+| main.rs:161:19:161:59 | ...::from_size_align(...) [Ok] | main.rs:161:19:161:68 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:161:19:161:68 | ... .unwrap(...) | main.rs:161:13:161:15 | l13 | provenance | |
+| main.rs:161:55:161:55 | v | main.rs:161:19:161:59 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
+| main.rs:162:35:162:37 | l13 | main.rs:162:17:162:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:162:35:162:37 | l13 | main.rs:169:35:169:37 | l13 | provenance | |
+| main.rs:168:13:168:15 | l14 | main.rs:170:35:170:37 | l14 | provenance | |
+| main.rs:168:19:168:59 | ...::from_size_align(...) [Ok] | main.rs:168:19:168:68 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:168:19:168:68 | ... .unwrap(...) | main.rs:168:13:168:15 | l14 | provenance | |
+| main.rs:168:55:168:55 | v | main.rs:168:19:168:59 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
+| main.rs:169:35:169:37 | l13 | main.rs:169:17:169:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:170:35:170:37 | l14 | main.rs:170:17:170:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:176:9:176:11 | l15 | main.rs:178:31:178:33 | l15 | provenance | |
+| main.rs:176:15:176:55 | ...::from_size_align(...) [Ok] | main.rs:176:15:176:64 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:176:15:176:64 | ... .unwrap(...) | main.rs:176:9:176:11 | l15 | provenance | |
+| main.rs:176:51:176:51 | v | main.rs:176:15:176:55 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
+| main.rs:177:31:177:32 | l1 | main.rs:177:13:177:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:178:31:178:33 | l15 | main.rs:178:13:178:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:183:29:183:36 | ...: usize | main.rs:192:46:192:46 | v | provenance | |
+| main.rs:192:9:192:10 | l2 | main.rs:193:38:193:39 | l2 | provenance | |
+| main.rs:192:14:192:47 | ...::array::<...>(...) [Ok] | main.rs:192:14:192:56 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:192:14:192:56 | ... .unwrap(...) | main.rs:192:9:192:10 | l2 | provenance | |
+| main.rs:192:46:192:46 | v | main.rs:192:14:192:47 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
+| main.rs:193:38:193:39 | l2 | main.rs:193:32:193:36 | alloc | provenance | MaD:10 Sink:MaD:10 |
+| main.rs:193:38:193:39 | l2 | main.rs:194:45:194:46 | l2 | provenance | |
+| main.rs:194:45:194:46 | l2 | main.rs:194:32:194:43 | alloc_zeroed | provenance | MaD:11 Sink:MaD:11 |
+| main.rs:194:45:194:46 | l2 | main.rs:195:41:195:42 | l2 | provenance | |
+| main.rs:195:41:195:42 | l2 | main.rs:195:32:195:39 | allocate | provenance | MaD:6 Sink:MaD:6 |
+| main.rs:195:41:195:42 | l2 | main.rs:196:48:196:49 | l2 | provenance | |
+| main.rs:196:48:196:49 | l2 | main.rs:196:32:196:46 | allocate_zeroed | provenance | MaD:7 Sink:MaD:7 |
+| main.rs:196:48:196:49 | l2 | main.rs:197:41:197:42 | l2 | provenance | |
+| main.rs:197:41:197:42 | l2 | main.rs:197:32:197:39 | allocate | provenance | MaD:1 Sink:MaD:1 |
+| main.rs:197:41:197:42 | l2 | main.rs:198:48:198:49 | l2 | provenance | |
+| main.rs:198:48:198:49 | l2 | main.rs:198:32:198:46 | allocate_zeroed | provenance | MaD:2 Sink:MaD:2 |
+| main.rs:198:48:198:49 | l2 | main.rs:208:53:208:54 | l2 | provenance | |
+| main.rs:198:48:198:49 | l2 | main.rs:210:60:210:61 | l2 | provenance | |
+| main.rs:208:53:208:54 | l2 | main.rs:208:40:208:43 | grow | provenance | MaD:8 Sink:MaD:8 |
+| main.rs:210:60:210:61 | l2 | main.rs:210:40:210:50 | grow_zeroed | provenance | MaD:9 Sink:MaD:9 |
+| main.rs:217:27:217:34 | ...: usize | main.rs:219:26:219:26 | v | provenance | |
+| main.rs:219:26:219:26 | v | main.rs:219:13:219:24 | ...::malloc | provenance | MaD:14 Sink:MaD:14 |
+| main.rs:219:26:219:26 | v | main.rs:219:13:219:24 | ...::malloc | provenance | MaD:14 Sink:MaD:14 |
+| main.rs:219:26:219:26 | v | main.rs:220:36:220:36 | v | provenance | |
+| main.rs:220:36:220:36 | v | main.rs:220:13:220:31 | ...::aligned_alloc | provenance | MaD:12 Sink:MaD:12 |
+| main.rs:220:36:220:36 | v | main.rs:220:13:220:31 | ...::aligned_alloc | provenance | MaD:12 Sink:MaD:12 |
+| main.rs:220:36:220:36 | v | main.rs:222:30:222:30 | v | provenance | |
+| main.rs:222:30:222:30 | v | main.rs:222:13:222:24 | ...::calloc | provenance | MaD:13 Sink:MaD:13 |
+| main.rs:222:30:222:30 | v | main.rs:222:13:222:24 | ...::calloc | provenance | MaD:13 Sink:MaD:13 |
+| main.rs:222:30:222:30 | v | main.rs:223:26:223:26 | v | provenance | |
+| main.rs:223:26:223:26 | v | main.rs:223:13:223:24 | ...::calloc | provenance | MaD:13 Sink:MaD:13 |
+| main.rs:223:26:223:26 | v | main.rs:223:13:223:24 | ...::calloc | provenance | MaD:13 Sink:MaD:13 |
+| main.rs:223:26:223:26 | v | main.rs:224:31:224:31 | v | provenance | |
+| main.rs:224:31:224:31 | v | main.rs:224:13:224:25 | ...::realloc | provenance | MaD:15 Sink:MaD:15 |
+| main.rs:224:31:224:31 | v | main.rs:224:13:224:25 | ...::realloc | provenance | MaD:15 Sink:MaD:15 |
+| main.rs:279:24:279:41 | ...: String | main.rs:280:21:280:47 | user_input.parse(...) [Ok] | provenance | MaD:32 |
+| main.rs:280:9:280:17 | num_bytes | main.rs:282:54:282:62 | num_bytes | provenance | |
+| main.rs:280:21:280:47 | user_input.parse(...) [Ok] | main.rs:280:21:280:48 | TryExpr | provenance | |
+| main.rs:280:21:280:48 | TryExpr | main.rs:280:9:280:17 | num_bytes | provenance | |
+| main.rs:282:9:282:14 | layout | main.rs:284:40:284:45 | layout | provenance | |
+| main.rs:282:18:282:66 | ...::from_size_align(...) [Ok] | main.rs:282:18:282:75 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:282:18:282:75 | ... .unwrap(...) | main.rs:282:9:282:14 | layout | provenance | |
+| main.rs:282:54:282:62 | num_bytes | main.rs:282:18:282:66 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
+| main.rs:284:40:284:45 | layout | main.rs:284:22:284:38 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:292:25:292:42 | ...: String | main.rs:293:16:293:42 | user_input.parse(...) [Ok] | provenance | MaD:32 |
+| main.rs:293:9:293:12 | size | main.rs:297:9:297:17 | num_bytes | provenance | |
+| main.rs:293:16:293:42 | user_input.parse(...) [Ok] | main.rs:293:16:293:43 | TryExpr | provenance | |
+| main.rs:293:16:293:43 | TryExpr | main.rs:293:9:293:12 | size | provenance | |
+| main.rs:297:9:297:17 | num_bytes | main.rs:299:54:299:62 | num_bytes | provenance | |
+| main.rs:299:9:299:14 | layout | main.rs:301:40:301:45 | layout | provenance | |
+| main.rs:299:18:299:66 | ...::from_size_align(...) [Ok] | main.rs:299:18:299:75 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:299:18:299:75 | ... .unwrap(...) | main.rs:299:9:299:14 | layout | provenance | |
+| main.rs:299:54:299:62 | num_bytes | main.rs:299:18:299:66 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
+| main.rs:301:40:301:45 | layout | main.rs:301:22:301:38 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
+| main.rs:308:25:308:38 | ...::args | main.rs:308:25:308:40 | ...::args(...) [element] | provenance | Src:MaD:16 |
+| main.rs:308:25:308:40 | ...::args(...) [element] | main.rs:308:25:308:47 | ... .nth(...) [Some] | provenance | MaD:35 |
+| main.rs:308:25:308:47 | ... .nth(...) [Some] | main.rs:308:25:308:74 | ... .unwrap_or(...) | provenance | MaD:29 |
+| main.rs:308:25:308:74 | ... .unwrap_or(...) | main.rs:279:24:279:41 | ...: String | provenance | |
+| main.rs:309:26:309:39 | ...::args | main.rs:309:26:309:41 | ...::args(...) [element] | provenance | Src:MaD:16 |
+| main.rs:309:26:309:41 | ...::args(...) [element] | main.rs:309:26:309:48 | ... .nth(...) [Some] | provenance | MaD:35 |
+| main.rs:309:26:309:48 | ... .nth(...) [Some] | main.rs:309:26:309:75 | ... .unwrap_or(...) | provenance | MaD:29 |
+| main.rs:309:26:309:75 | ... .unwrap_or(...) | main.rs:292:25:292:42 | ...: String | provenance | |
+| main.rs:317:9:317:9 | v | main.rs:320:34:320:34 | v | provenance | |
+| main.rs:317:9:317:9 | v | main.rs:321:42:321:42 | v | provenance | |
+| main.rs:317:9:317:9 | v | main.rs:322:36:322:36 | v | provenance | |
+| main.rs:317:9:317:9 | v | main.rs:323:27:323:27 | v | provenance | |
+| main.rs:317:9:317:9 | v | main.rs:324:25:324:25 | v | provenance | |
+| main.rs:317:13:317:26 | ...::args | main.rs:317:13:317:28 | ...::args(...) [element] | provenance | Src:MaD:16 |
+| main.rs:317:13:317:28 | ...::args(...) [element] | main.rs:317:13:317:35 | ... .nth(...) [Some] | provenance | MaD:35 |
+| main.rs:317:13:317:35 | ... .nth(...) [Some] | main.rs:317:13:317:65 | ... .unwrap_or(...) | provenance | MaD:29 |
+| main.rs:317:13:317:65 | ... .unwrap_or(...) | main.rs:317:13:317:82 | ... .parse(...) [Ok] | provenance | MaD:32 |
+| main.rs:317:13:317:82 | ... .parse(...) [Ok] | main.rs:317:13:317:91 | ... .unwrap(...) | provenance | MaD:31 |
+| main.rs:317:13:317:91 | ... .unwrap(...) | main.rs:317:9:317:9 | v | provenance | |
+| main.rs:320:34:320:34 | v | main.rs:12:36:12:43 | ...: usize | provenance | |
+| main.rs:321:42:321:42 | v | main.rs:43:44:43:51 | ...: usize | provenance | |
+| main.rs:322:36:322:36 | v | main.rs:91:38:91:45 | ...: usize | provenance | |
+| main.rs:323:27:323:27 | v | main.rs:183:29:183:36 | ...: usize | provenance | |
+| main.rs:324:25:324:25 | v | main.rs:217:27:217:34 | ...: usize | provenance | |
models
| 1 | Sink: lang:alloc; ::allocate; alloc-layout; Argument[0] |
| 2 | Sink: lang:alloc; ::allocate_zeroed; alloc-layout; Argument[0] |
@@ -402,134 +486,206 @@ nodes
| main.rs:68:31:68:32 | l4 | semmle.label | l4 |
| main.rs:71:35:71:38 | ...: T | semmle.label | ...: T |
| main.rs:77:9:77:16 | return v | semmle.label | return v |
-| main.rs:81:38:81:45 | ...: usize | semmle.label | ...: usize |
-| main.rs:82:9:82:10 | l1 | semmle.label | l1 |
-| main.rs:82:14:82:48 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
-| main.rs:82:14:82:57 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:82:47:82:47 | v | semmle.label | v |
-| main.rs:85:17:85:33 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:85:35:85:36 | l1 | semmle.label | l1 |
-| main.rs:87:17:87:33 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:87:35:87:36 | l1 | semmle.label | l1 |
-| main.rs:91:17:91:33 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:91:35:91:36 | l1 | semmle.label | l1 |
-| main.rs:93:17:93:33 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:93:35:93:36 | l1 | semmle.label | l1 |
-| main.rs:97:13:97:21 | mut v_mut | semmle.label | mut v_mut |
-| main.rs:103:13:103:14 | l2 | semmle.label | l2 |
-| main.rs:103:18:103:56 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
-| main.rs:103:18:103:65 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:103:51:103:55 | v_mut | semmle.label | v_mut |
-| main.rs:104:17:104:33 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:104:35:104:36 | l2 | semmle.label | l2 |
-| main.rs:106:13:106:14 | l3 | semmle.label | l3 |
-| main.rs:106:18:106:52 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
-| main.rs:106:18:106:61 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:106:51:106:51 | v | semmle.label | v |
-| main.rs:107:17:107:33 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:107:35:107:36 | l3 | semmle.label | l3 |
-| main.rs:110:9:110:10 | l4 | semmle.label | l4 |
-| main.rs:110:14:110:68 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
-| main.rs:110:14:110:77 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:110:47:110:67 | ...::min(...) | semmle.label | ...::min(...) |
-| main.rs:110:61:110:61 | v | semmle.label | v |
-| main.rs:111:13:111:29 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:111:31:111:32 | l4 | semmle.label | l4 |
-| main.rs:113:9:113:10 | l5 | semmle.label | l5 |
-| main.rs:113:14:113:68 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
-| main.rs:113:14:113:77 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:113:47:113:67 | ...::max(...) | semmle.label | ...::max(...) |
-| main.rs:113:61:113:61 | v | semmle.label | v |
-| main.rs:114:13:114:29 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:114:31:114:32 | l5 | semmle.label | l5 |
-| main.rs:116:9:116:10 | l6 | semmle.label | l6 |
-| main.rs:116:14:116:63 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
-| main.rs:116:14:116:72 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:116:47:116:62 | clamp(...) | semmle.label | clamp(...) |
-| main.rs:116:53:116:53 | v | semmle.label | v |
-| main.rs:117:13:117:29 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:117:31:117:32 | l6 | semmle.label | l6 |
-| main.rs:119:13:119:29 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:119:31:119:32 | l1 | semmle.label | l1 |
-| main.rs:123:13:123:29 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:123:31:123:32 | l1 | semmle.label | l1 |
-| main.rs:128:29:128:36 | ...: usize | semmle.label | ...: usize |
-| main.rs:137:9:137:10 | l2 | semmle.label | l2 |
-| main.rs:137:14:137:47 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
-| main.rs:137:14:137:56 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:137:46:137:46 | v | semmle.label | v |
-| main.rs:138:32:138:36 | alloc | semmle.label | alloc |
-| main.rs:138:38:138:39 | l2 | semmle.label | l2 |
-| main.rs:139:32:139:43 | alloc_zeroed | semmle.label | alloc_zeroed |
-| main.rs:139:45:139:46 | l2 | semmle.label | l2 |
-| main.rs:140:32:140:39 | allocate | semmle.label | allocate |
-| main.rs:140:41:140:42 | l2 | semmle.label | l2 |
-| main.rs:141:32:141:46 | allocate_zeroed | semmle.label | allocate_zeroed |
-| main.rs:141:48:141:49 | l2 | semmle.label | l2 |
-| main.rs:142:32:142:39 | allocate | semmle.label | allocate |
-| main.rs:142:41:142:42 | l2 | semmle.label | l2 |
-| main.rs:143:32:143:46 | allocate_zeroed | semmle.label | allocate_zeroed |
-| main.rs:143:48:143:49 | l2 | semmle.label | l2 |
-| main.rs:153:40:153:43 | grow | semmle.label | grow |
-| main.rs:153:53:153:54 | l2 | semmle.label | l2 |
-| main.rs:155:40:155:50 | grow_zeroed | semmle.label | grow_zeroed |
-| main.rs:155:60:155:61 | l2 | semmle.label | l2 |
-| main.rs:162:27:162:34 | ...: usize | semmle.label | ...: usize |
-| main.rs:164:13:164:24 | ...::malloc | semmle.label | ...::malloc |
-| main.rs:164:13:164:24 | ...::malloc | semmle.label | ...::malloc |
-| main.rs:164:26:164:26 | v | semmle.label | v |
-| main.rs:165:13:165:31 | ...::aligned_alloc | semmle.label | ...::aligned_alloc |
-| main.rs:165:13:165:31 | ...::aligned_alloc | semmle.label | ...::aligned_alloc |
-| main.rs:165:36:165:36 | v | semmle.label | v |
-| main.rs:167:13:167:24 | ...::calloc | semmle.label | ...::calloc |
-| main.rs:167:13:167:24 | ...::calloc | semmle.label | ...::calloc |
-| main.rs:167:30:167:30 | v | semmle.label | v |
-| main.rs:168:13:168:24 | ...::calloc | semmle.label | ...::calloc |
-| main.rs:168:13:168:24 | ...::calloc | semmle.label | ...::calloc |
-| main.rs:168:26:168:26 | v | semmle.label | v |
-| main.rs:169:13:169:25 | ...::realloc | semmle.label | ...::realloc |
-| main.rs:169:13:169:25 | ...::realloc | semmle.label | ...::realloc |
-| main.rs:169:31:169:31 | v | semmle.label | v |
-| main.rs:224:24:224:41 | ...: String | semmle.label | ...: String |
-| main.rs:225:9:225:17 | num_bytes | semmle.label | num_bytes |
-| main.rs:225:21:225:47 | user_input.parse(...) [Ok] | semmle.label | user_input.parse(...) [Ok] |
-| main.rs:225:21:225:48 | TryExpr | semmle.label | TryExpr |
-| main.rs:227:9:227:14 | layout | semmle.label | layout |
-| main.rs:227:18:227:66 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
-| main.rs:227:18:227:75 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:227:54:227:62 | num_bytes | semmle.label | num_bytes |
-| main.rs:229:22:229:38 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:229:40:229:45 | layout | semmle.label | layout |
-| main.rs:237:25:237:42 | ...: String | semmle.label | ...: String |
-| main.rs:238:9:238:12 | size | semmle.label | size |
-| main.rs:238:16:238:42 | user_input.parse(...) [Ok] | semmle.label | user_input.parse(...) [Ok] |
-| main.rs:238:16:238:43 | TryExpr | semmle.label | TryExpr |
-| main.rs:242:9:242:17 | num_bytes | semmle.label | num_bytes |
-| main.rs:244:9:244:14 | layout | semmle.label | layout |
-| main.rs:244:18:244:66 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
-| main.rs:244:18:244:75 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:244:54:244:62 | num_bytes | semmle.label | num_bytes |
-| main.rs:246:22:246:38 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:246:40:246:45 | layout | semmle.label | layout |
-| main.rs:253:25:253:38 | ...::args | semmle.label | ...::args |
-| main.rs:253:25:253:40 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
-| main.rs:253:25:253:47 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
-| main.rs:253:25:253:74 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
-| main.rs:254:26:254:39 | ...::args | semmle.label | ...::args |
-| main.rs:254:26:254:41 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
-| main.rs:254:26:254:48 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
-| main.rs:254:26:254:75 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
-| main.rs:262:9:262:9 | v | semmle.label | v |
-| main.rs:262:13:262:26 | ...::args | semmle.label | ...::args |
-| main.rs:262:13:262:28 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
-| main.rs:262:13:262:35 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
-| main.rs:262:13:262:65 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
-| main.rs:262:13:262:82 | ... .parse(...) [Ok] | semmle.label | ... .parse(...) [Ok] |
-| main.rs:262:13:262:91 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:265:34:265:34 | v | semmle.label | v |
-| main.rs:266:42:266:42 | v | semmle.label | v |
-| main.rs:267:36:267:36 | v | semmle.label | v |
-| main.rs:268:27:268:27 | v | semmle.label | v |
-| main.rs:269:25:269:25 | v | semmle.label | v |
+| main.rs:81:33:81:40 | ...: usize | semmle.label | ...: usize |
+| main.rs:82:9:82:14 | layout | semmle.label | layout |
+| main.rs:82:18:82:58 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
+| main.rs:82:18:82:67 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:82:54:82:54 | v | semmle.label | v |
+| main.rs:83:13:83:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:83:31:83:36 | layout | semmle.label | layout |
+| main.rs:86:35:86:42 | ...: usize | semmle.label | ...: usize |
+| main.rs:87:9:87:14 | layout | semmle.label | layout |
+| main.rs:87:18:87:58 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
+| main.rs:87:18:87:67 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:87:54:87:54 | v | semmle.label | v |
+| main.rs:88:13:88:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:88:31:88:36 | layout | semmle.label | layout |
+| main.rs:91:38:91:45 | ...: usize | semmle.label | ...: usize |
+| main.rs:92:9:92:10 | l1 | semmle.label | l1 |
+| main.rs:92:14:92:48 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:92:14:92:57 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:92:47:92:47 | v | semmle.label | v |
+| main.rs:95:13:95:14 | l2 | semmle.label | l2 |
+| main.rs:95:18:95:52 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:95:18:95:61 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:95:51:95:51 | v | semmle.label | v |
+| main.rs:96:17:96:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:96:35:96:36 | l1 | semmle.label | l1 |
+| main.rs:97:17:97:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:97:35:97:36 | l2 | semmle.label | l2 |
+| main.rs:99:31:99:31 | v | semmle.label | v |
+| main.rs:101:13:101:14 | l3 | semmle.label | l3 |
+| main.rs:101:18:101:52 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:101:18:101:61 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:101:51:101:51 | v | semmle.label | v |
+| main.rs:102:17:102:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:102:35:102:36 | l1 | semmle.label | l1 |
+| main.rs:103:17:103:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:103:35:103:36 | l3 | semmle.label | l3 |
+| main.rs:105:33:105:33 | v | semmle.label | v |
+| main.rs:109:17:109:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:109:35:109:36 | l1 | semmle.label | l1 |
+| main.rs:111:17:111:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:111:35:111:36 | l1 | semmle.label | l1 |
+| main.rs:115:13:115:14 | l4 | semmle.label | l4 |
+| main.rs:115:18:115:58 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
+| main.rs:115:18:115:67 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:115:54:115:54 | v | semmle.label | v |
+| main.rs:116:17:116:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:116:35:116:36 | l4 | semmle.label | l4 |
+| main.rs:120:13:120:14 | l5 | semmle.label | l5 |
+| main.rs:120:18:120:58 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
+| main.rs:120:18:120:67 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:120:54:120:54 | v | semmle.label | v |
+| main.rs:121:17:121:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:121:35:121:36 | l5 | semmle.label | l5 |
+| main.rs:125:13:125:14 | l6 | semmle.label | l6 |
+| main.rs:125:18:125:58 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
+| main.rs:125:18:125:67 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:125:54:125:54 | v | semmle.label | v |
+| main.rs:126:17:126:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:126:35:126:36 | l6 | semmle.label | l6 |
+| main.rs:131:9:131:10 | l7 | semmle.label | l7 |
+| main.rs:131:14:131:54 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
+| main.rs:131:14:131:63 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:131:50:131:50 | v | semmle.label | v |
+| main.rs:135:13:135:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:135:31:135:32 | l7 | semmle.label | l7 |
+| main.rs:138:13:138:21 | mut v_mut | semmle.label | mut v_mut |
+| main.rs:144:13:144:14 | l8 | semmle.label | l8 |
+| main.rs:144:18:144:56 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:144:18:144:65 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:144:51:144:55 | v_mut | semmle.label | v_mut |
+| main.rs:145:13:145:14 | l9 | semmle.label | l9 |
+| main.rs:145:18:145:52 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:145:18:145:61 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:145:51:145:51 | v | semmle.label | v |
+| main.rs:146:17:146:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:146:35:146:36 | l1 | semmle.label | l1 |
+| main.rs:147:17:147:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:147:35:147:36 | l8 | semmle.label | l8 |
+| main.rs:148:17:148:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:148:35:148:36 | l9 | semmle.label | l9 |
+| main.rs:151:9:151:11 | l10 | semmle.label | l10 |
+| main.rs:151:15:151:69 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:151:15:151:78 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:151:48:151:68 | ...::min(...) | semmle.label | ...::min(...) |
+| main.rs:151:62:151:62 | v | semmle.label | v |
+| main.rs:152:13:152:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:152:31:152:33 | l10 | semmle.label | l10 |
+| main.rs:154:9:154:11 | l11 | semmle.label | l11 |
+| main.rs:154:15:154:69 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:154:15:154:78 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:154:48:154:68 | ...::max(...) | semmle.label | ...::max(...) |
+| main.rs:154:62:154:62 | v | semmle.label | v |
+| main.rs:155:13:155:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:155:31:155:33 | l11 | semmle.label | l11 |
+| main.rs:157:9:157:11 | l12 | semmle.label | l12 |
+| main.rs:157:15:157:64 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:157:15:157:73 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:157:48:157:63 | clamp(...) | semmle.label | clamp(...) |
+| main.rs:157:54:157:54 | v | semmle.label | v |
+| main.rs:158:13:158:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:158:31:158:33 | l12 | semmle.label | l12 |
+| main.rs:161:13:161:15 | l13 | semmle.label | l13 |
+| main.rs:161:19:161:59 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
+| main.rs:161:19:161:68 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:161:55:161:55 | v | semmle.label | v |
+| main.rs:162:17:162:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:162:35:162:37 | l13 | semmle.label | l13 |
+| main.rs:168:13:168:15 | l14 | semmle.label | l14 |
+| main.rs:168:19:168:59 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
+| main.rs:168:19:168:68 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:168:55:168:55 | v | semmle.label | v |
+| main.rs:169:17:169:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:169:35:169:37 | l13 | semmle.label | l13 |
+| main.rs:170:17:170:33 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:170:35:170:37 | l14 | semmle.label | l14 |
+| main.rs:176:9:176:11 | l15 | semmle.label | l15 |
+| main.rs:176:15:176:55 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
+| main.rs:176:15:176:64 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:176:51:176:51 | v | semmle.label | v |
+| main.rs:177:13:177:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:177:31:177:32 | l1 | semmle.label | l1 |
+| main.rs:178:13:178:29 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:178:31:178:33 | l15 | semmle.label | l15 |
+| main.rs:183:29:183:36 | ...: usize | semmle.label | ...: usize |
+| main.rs:192:9:192:10 | l2 | semmle.label | l2 |
+| main.rs:192:14:192:47 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
+| main.rs:192:14:192:56 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:192:46:192:46 | v | semmle.label | v |
+| main.rs:193:32:193:36 | alloc | semmle.label | alloc |
+| main.rs:193:38:193:39 | l2 | semmle.label | l2 |
+| main.rs:194:32:194:43 | alloc_zeroed | semmle.label | alloc_zeroed |
+| main.rs:194:45:194:46 | l2 | semmle.label | l2 |
+| main.rs:195:32:195:39 | allocate | semmle.label | allocate |
+| main.rs:195:41:195:42 | l2 | semmle.label | l2 |
+| main.rs:196:32:196:46 | allocate_zeroed | semmle.label | allocate_zeroed |
+| main.rs:196:48:196:49 | l2 | semmle.label | l2 |
+| main.rs:197:32:197:39 | allocate | semmle.label | allocate |
+| main.rs:197:41:197:42 | l2 | semmle.label | l2 |
+| main.rs:198:32:198:46 | allocate_zeroed | semmle.label | allocate_zeroed |
+| main.rs:198:48:198:49 | l2 | semmle.label | l2 |
+| main.rs:208:40:208:43 | grow | semmle.label | grow |
+| main.rs:208:53:208:54 | l2 | semmle.label | l2 |
+| main.rs:210:40:210:50 | grow_zeroed | semmle.label | grow_zeroed |
+| main.rs:210:60:210:61 | l2 | semmle.label | l2 |
+| main.rs:217:27:217:34 | ...: usize | semmle.label | ...: usize |
+| main.rs:219:13:219:24 | ...::malloc | semmle.label | ...::malloc |
+| main.rs:219:13:219:24 | ...::malloc | semmle.label | ...::malloc |
+| main.rs:219:26:219:26 | v | semmle.label | v |
+| main.rs:220:13:220:31 | ...::aligned_alloc | semmle.label | ...::aligned_alloc |
+| main.rs:220:13:220:31 | ...::aligned_alloc | semmle.label | ...::aligned_alloc |
+| main.rs:220:36:220:36 | v | semmle.label | v |
+| main.rs:222:13:222:24 | ...::calloc | semmle.label | ...::calloc |
+| main.rs:222:13:222:24 | ...::calloc | semmle.label | ...::calloc |
+| main.rs:222:30:222:30 | v | semmle.label | v |
+| main.rs:223:13:223:24 | ...::calloc | semmle.label | ...::calloc |
+| main.rs:223:13:223:24 | ...::calloc | semmle.label | ...::calloc |
+| main.rs:223:26:223:26 | v | semmle.label | v |
+| main.rs:224:13:224:25 | ...::realloc | semmle.label | ...::realloc |
+| main.rs:224:13:224:25 | ...::realloc | semmle.label | ...::realloc |
+| main.rs:224:31:224:31 | v | semmle.label | v |
+| main.rs:279:24:279:41 | ...: String | semmle.label | ...: String |
+| main.rs:280:9:280:17 | num_bytes | semmle.label | num_bytes |
+| main.rs:280:21:280:47 | user_input.parse(...) [Ok] | semmle.label | user_input.parse(...) [Ok] |
+| main.rs:280:21:280:48 | TryExpr | semmle.label | TryExpr |
+| main.rs:282:9:282:14 | layout | semmle.label | layout |
+| main.rs:282:18:282:66 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
+| main.rs:282:18:282:75 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:282:54:282:62 | num_bytes | semmle.label | num_bytes |
+| main.rs:284:22:284:38 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:284:40:284:45 | layout | semmle.label | layout |
+| main.rs:292:25:292:42 | ...: String | semmle.label | ...: String |
+| main.rs:293:9:293:12 | size | semmle.label | size |
+| main.rs:293:16:293:42 | user_input.parse(...) [Ok] | semmle.label | user_input.parse(...) [Ok] |
+| main.rs:293:16:293:43 | TryExpr | semmle.label | TryExpr |
+| main.rs:297:9:297:17 | num_bytes | semmle.label | num_bytes |
+| main.rs:299:9:299:14 | layout | semmle.label | layout |
+| main.rs:299:18:299:66 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
+| main.rs:299:18:299:75 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:299:54:299:62 | num_bytes | semmle.label | num_bytes |
+| main.rs:301:22:301:38 | ...::alloc | semmle.label | ...::alloc |
+| main.rs:301:40:301:45 | layout | semmle.label | layout |
+| main.rs:308:25:308:38 | ...::args | semmle.label | ...::args |
+| main.rs:308:25:308:40 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
+| main.rs:308:25:308:47 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
+| main.rs:308:25:308:74 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
+| main.rs:309:26:309:39 | ...::args | semmle.label | ...::args |
+| main.rs:309:26:309:41 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
+| main.rs:309:26:309:48 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
+| main.rs:309:26:309:75 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
+| main.rs:317:9:317:9 | v | semmle.label | v |
+| main.rs:317:13:317:26 | ...::args | semmle.label | ...::args |
+| main.rs:317:13:317:28 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
+| main.rs:317:13:317:35 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
+| main.rs:317:13:317:65 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
+| main.rs:317:13:317:82 | ... .parse(...) [Ok] | semmle.label | ... .parse(...) [Ok] |
+| main.rs:317:13:317:91 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
+| main.rs:320:34:320:34 | v | semmle.label | v |
+| main.rs:321:42:321:42 | v | semmle.label | v |
+| main.rs:322:36:322:36 | v | semmle.label | v |
+| main.rs:323:27:323:27 | v | semmle.label | v |
+| main.rs:324:25:324:25 | v | semmle.label | v |
subpaths
-| main.rs:116:53:116:53 | v | main.rs:71:35:71:38 | ...: T | main.rs:77:9:77:16 | return v | main.rs:116:47:116:62 | clamp(...) |
+| main.rs:157:54:157:54 | v | main.rs:71:35:71:38 | ...: T | main.rs:77:9:77:16 | return v | main.rs:157:48:157:63 | clamp(...) |
diff --git a/rust/ql/test/query-tests/security/CWE-770/main.rs b/rust/ql/test/query-tests/security/CWE-770/main.rs
index a699767dc1a8..558979ebfc2c 100644
--- a/rust/ql/test/query-tests/security/CWE-770/main.rs
+++ b/rust/ql/test/query-tests/security/CWE-770/main.rs
@@ -78,13 +78,31 @@ fn clamp(v: T, min: T, max: T) -> T {
}
}
-unsafe fn test_std_alloc_with_bounds(v: usize) {
+unsafe fn test_fn_alloc_bounded(v: usize) {
+ let layout = std::alloc::Layout::from_size_align(v, 1).unwrap();
+ let _ = std::alloc::alloc(layout); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+}
+
+unsafe fn test_fn_alloc_unbounded(v: usize) {
+ let layout = std::alloc::Layout::from_size_align(v, 1).unwrap();
+ let _ = std::alloc::alloc(layout); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+}
+
+unsafe fn test_std_alloc_with_bounds(v: usize, limit: usize) {
let l1 = std::alloc::Layout::array::(v).unwrap();
if v < 100 {
+ let l2 = std::alloc::Layout::array::(v).unwrap();
let _ = std::alloc::alloc(l1); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(l2); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+
+ test_fn_alloc_bounded(v);
} else {
+ let l3 = std::alloc::Layout::array::(v).unwrap();
let _ = std::alloc::alloc(l1); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(l3); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+
+ test_fn_alloc_unbounded(v);
}
if v == 100 {
@@ -93,6 +111,29 @@ unsafe fn test_std_alloc_with_bounds(v: usize) {
let _ = std::alloc::alloc(l1); // $ Alert[rust/uncontrolled-allocation-size]=arg1
}
+ if (v < limit) {
+ let l4 = std::alloc::Layout::from_size_align(v, 1).unwrap();
+ let _ = std::alloc::alloc(l4); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+ }
+
+ if (v < 2 * v) { // not a good bound
+ let l5 = std::alloc::Layout::from_size_align(v, 1).unwrap();
+ let _ = std::alloc::alloc(l5); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ }
+
+ if (true && v < limit && true) {
+ let l6 = std::alloc::Layout::from_size_align(v, 1).unwrap();
+ let _ = std::alloc::alloc(l6); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+ }
+
+ let mut l7;
+ if (v < 100) {
+ l7 = std::alloc::Layout::from_size_align(v, 1).unwrap();
+ } else {
+ l7 = std::alloc::Layout::from_size_align(100, 1).unwrap();
+ }
+ let _ = std::alloc::alloc(l7); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+
{
let mut v_mut = v;
@@ -100,27 +141,41 @@ unsafe fn test_std_alloc_with_bounds(v: usize) {
v_mut = 100;
}
- let l2 = std::alloc::Layout::array::(v_mut).unwrap();
- let _ = std::alloc::alloc(l2); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
-
- let l3 = std::alloc::Layout::array::(v).unwrap();
- let _ = std::alloc::alloc(l3); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let l8 = std::alloc::Layout::array::(v_mut).unwrap();
+ let l9 = std::alloc::Layout::array::(v).unwrap();
+ let _ = std::alloc::alloc(l1); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(l8); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(l9); // $ Alert[rust/uncontrolled-allocation-size]=arg1
}
- let l4 = std::alloc::Layout::array::(std::cmp::min(v, 100)).unwrap();
- let _ = std::alloc::alloc(l4); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+ let l10 = std::alloc::Layout::array::(std::cmp::min(v, 100)).unwrap();
+ let _ = std::alloc::alloc(l10); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
- let l5 = std::alloc::Layout::array::(std::cmp::max(v, 100)).unwrap();
- let _ = std::alloc::alloc(l5); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let l11 = std::alloc::Layout::array::(std::cmp::max(v, 100)).unwrap();
+ let _ = std::alloc::alloc(l11); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+
+ let l12 = std::alloc::Layout::array::(clamp(v, 1, 100)).unwrap();
+ let _ = std::alloc::alloc(l12); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+
+ for i in 0..10 {
+ let l13 = std::alloc::Layout::from_size_align(v, 1).unwrap();
+ let _ = std::alloc::alloc(l13); // $ Alert[rust/uncontrolled-allocation-size]=arg1
- let l6 = std::alloc::Layout::array::(clamp(v, 1, 100)).unwrap();
- let _ = std::alloc::alloc(l6); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+ if (v > 1000) {
+ continue;
+ }
+
+ let l14 = std::alloc::Layout::from_size_align(v, 1).unwrap();
+ let _ = std::alloc::alloc(l13); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(l14); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+ }
- let _ = std::alloc::alloc(l1); // $ Alert[rust/uncontrolled-allocation-size]=arg1
if v > 100 {
return;
}
+ let l15 = std::alloc::Layout::from_size_align(v, 1).unwrap();
let _ = std::alloc::alloc(l1); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(l15); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
}
use std::alloc::{GlobalAlloc, Allocator};
@@ -264,7 +319,7 @@ fn main() {
unsafe {
test_std_alloc_from_size(v);
test_std_alloc_new_repeat_extend(v);
- test_std_alloc_with_bounds(v);
+ test_std_alloc_with_bounds(v, 1000);
test_system_alloc(v);
test_libc_alloc(v);
test_vectors(v);
From f7d3a51f2728d3bb4769c1813b3ff455fd190e0c Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Fri, 28 Mar 2025 19:37:05 +0000
Subject: [PATCH 087/409] Rust: Implement barrier guard.
---
.../UncontrolledAllocationSizeExtensions.qll | 20 +-
.../UncontrolledAllocationSize.expected | 272 +-----------------
.../test/query-tests/security/CWE-770/main.rs | 38 +--
3 files changed, 41 insertions(+), 289 deletions(-)
diff --git a/rust/ql/lib/codeql/rust/security/UncontrolledAllocationSizeExtensions.qll b/rust/ql/lib/codeql/rust/security/UncontrolledAllocationSizeExtensions.qll
index bb0ffbb4e3c1..9efffeee9ae3 100644
--- a/rust/ql/lib/codeql/rust/security/UncontrolledAllocationSizeExtensions.qll
+++ b/rust/ql/lib/codeql/rust/security/UncontrolledAllocationSizeExtensions.qll
@@ -7,6 +7,8 @@ import rust
private import codeql.rust.Concepts
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.FlowSink
+private import codeql.rust.controlflow.ControlFlowGraph as Cfg
+private import codeql.rust.controlflow.CfgNodes as CfgNodes
/**
* Provides default sources, sinks and barriers for detecting uncontrolled
@@ -26,9 +28,25 @@ module UncontrolledAllocationSize {
abstract class Barrier extends DataFlow::Node { }
/**
- * sink for uncontrolled allocation size from model data.
+ * A sink for uncontrolled allocation size from model data.
*/
private class ModelsAsDataSink extends Sink {
ModelsAsDataSink() { sinkNode(this, ["alloc-size", "alloc-layout"]) }
}
+
+ /**
+ * A barrier for uncontrolled allocation size that is an guard / bound check.
+ */
+ private class BoundCheckBarrier extends Barrier {
+ BoundCheckBarrier() { this = DataFlow::BarrierGuard::getABarrierNode() }
+ }
+
+ private predicate isBoundCheck(CfgNodes::AstCfgNode g, Cfg::CfgNode node, boolean branch) {
+ // any comparison (`g` / `cmp`) guards the expression on either side (`node`)
+ exists(BinaryExpr cmp |
+ g = cmp.getACfgNode() and
+ [cmp.getLhs(), cmp.getRhs()].getACfgNode() = node and
+ branch = [true, false]
+ )
+ }
}
diff --git a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
index cca67133563a..e10c26338dce 100644
--- a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
+++ b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected
@@ -18,29 +18,12 @@
| main.rs:64:13:64:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:64:13:64:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:65:13:65:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:65:13:65:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:68:13:68:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:68:13:68:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:83:13:83:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:83:13:83:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:88:13:88:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:88:13:88:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:96:17:96:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:96:17:96:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:97:17:97:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:97:17:97:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:102:17:102:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:102:17:102:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:103:17:103:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:103:17:103:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:109:17:109:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:109:17:109:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:111:17:111:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:111:17:111:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:116:17:116:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:116:17:116:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:121:17:121:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:121:17:121:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:126:17:126:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:126:17:126:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:135:13:135:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:135:13:135:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:146:17:146:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:146:17:146:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:147:17:147:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:147:17:147:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:148:17:148:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:148:17:148:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:152:13:152:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:152:13:152:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:155:13:155:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:155:13:155:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:158:13:158:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:158:13:158:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:162:17:162:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:162:17:162:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:169:17:169:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:169:17:169:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:170:17:170:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:170:17:170:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:177:13:177:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:177:13:177:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
-| main.rs:178:13:178:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:178:13:178:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:193:32:193:36 | alloc | main.rs:317:13:317:26 | ...::args | main.rs:193:32:193:36 | alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:194:32:194:43 | alloc_zeroed | main.rs:317:13:317:26 | ...::args | main.rs:194:32:194:43 | alloc_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:195:32:195:39 | allocate | main.rs:317:13:317:26 | ...::args | main.rs:195:32:195:39 | allocate | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
@@ -60,7 +43,6 @@
| main.rs:224:13:224:25 | ...::realloc | main.rs:317:13:317:26 | ...::args | main.rs:224:13:224:25 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:224:13:224:25 | ...::realloc | main.rs:317:13:317:26 | ...::args | main.rs:224:13:224:25 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:284:22:284:38 | ...::alloc | main.rs:308:25:308:38 | ...::args | main.rs:284:22:284:38 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:308:25:308:38 | ...::args | user-provided value |
-| main.rs:301:22:301:38 | ...::alloc | main.rs:309:26:309:39 | ...::args | main.rs:301:22:301:38 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:309:26:309:39 | ...::args | user-provided value |
edges
| main.rs:12:36:12:43 | ...: usize | main.rs:18:41:18:41 | v | provenance | |
| main.rs:18:41:18:41 | v | main.rs:18:13:18:31 | ...::realloc | provenance | MaD:5 Sink:MaD:5 |
@@ -151,133 +133,25 @@ edges
| main.rs:67:14:67:56 | ... .unwrap(...) | main.rs:67:9:67:10 | l4 | provenance | |
| main.rs:67:46:67:46 | v | main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:68:31:68:32 | l4 | main.rs:68:13:68:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:71:35:71:38 | ...: T | main.rs:77:9:77:16 | return v | provenance | |
-| main.rs:81:33:81:40 | ...: usize | main.rs:82:54:82:54 | v | provenance | |
-| main.rs:82:9:82:14 | layout | main.rs:83:31:83:36 | layout | provenance | |
-| main.rs:82:18:82:58 | ...::from_size_align(...) [Ok] | main.rs:82:18:82:67 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:82:18:82:67 | ... .unwrap(...) | main.rs:82:9:82:14 | layout | provenance | |
-| main.rs:82:54:82:54 | v | main.rs:82:18:82:58 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
-| main.rs:83:31:83:36 | layout | main.rs:83:13:83:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:86:35:86:42 | ...: usize | main.rs:87:54:87:54 | v | provenance | |
-| main.rs:87:9:87:14 | layout | main.rs:88:31:88:36 | layout | provenance | |
-| main.rs:87:18:87:58 | ...::from_size_align(...) [Ok] | main.rs:87:18:87:67 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:87:18:87:67 | ... .unwrap(...) | main.rs:87:9:87:14 | layout | provenance | |
-| main.rs:87:54:87:54 | v | main.rs:87:18:87:58 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
-| main.rs:88:31:88:36 | layout | main.rs:88:13:88:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:91:38:91:45 | ...: usize | main.rs:92:47:92:47 | v | provenance | |
-| main.rs:91:38:91:45 | ...: usize | main.rs:95:51:95:51 | v | provenance | |
-| main.rs:91:38:91:45 | ...: usize | main.rs:99:31:99:31 | v | provenance | |
-| main.rs:91:38:91:45 | ...: usize | main.rs:101:51:101:51 | v | provenance | |
-| main.rs:91:38:91:45 | ...: usize | main.rs:105:33:105:33 | v | provenance | |
-| main.rs:91:38:91:45 | ...: usize | main.rs:115:54:115:54 | v | provenance | |
-| main.rs:91:38:91:45 | ...: usize | main.rs:120:54:120:54 | v | provenance | |
-| main.rs:91:38:91:45 | ...: usize | main.rs:125:54:125:54 | v | provenance | |
-| main.rs:91:38:91:45 | ...: usize | main.rs:131:50:131:50 | v | provenance | |
-| main.rs:91:38:91:45 | ...: usize | main.rs:138:13:138:21 | mut v_mut | provenance | |
-| main.rs:91:38:91:45 | ...: usize | main.rs:145:51:145:51 | v | provenance | |
-| main.rs:91:38:91:45 | ...: usize | main.rs:151:62:151:62 | v | provenance | |
-| main.rs:91:38:91:45 | ...: usize | main.rs:154:62:154:62 | v | provenance | |
-| main.rs:91:38:91:45 | ...: usize | main.rs:157:54:157:54 | v | provenance | |
-| main.rs:91:38:91:45 | ...: usize | main.rs:161:55:161:55 | v | provenance | |
-| main.rs:91:38:91:45 | ...: usize | main.rs:168:55:168:55 | v | provenance | |
-| main.rs:91:38:91:45 | ...: usize | main.rs:176:51:176:51 | v | provenance | |
| main.rs:92:9:92:10 | l1 | main.rs:96:35:96:36 | l1 | provenance | |
| main.rs:92:9:92:10 | l1 | main.rs:102:35:102:36 | l1 | provenance | |
| main.rs:92:14:92:48 | ...::array::<...>(...) [Ok] | main.rs:92:14:92:57 | ... .unwrap(...) | provenance | MaD:31 |
| main.rs:92:14:92:57 | ... .unwrap(...) | main.rs:92:9:92:10 | l1 | provenance | |
| main.rs:92:47:92:47 | v | main.rs:92:14:92:48 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
-| main.rs:95:13:95:14 | l2 | main.rs:97:35:97:36 | l2 | provenance | |
-| main.rs:95:18:95:52 | ...::array::<...>(...) [Ok] | main.rs:95:18:95:61 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:95:18:95:61 | ... .unwrap(...) | main.rs:95:13:95:14 | l2 | provenance | |
-| main.rs:95:51:95:51 | v | main.rs:95:18:95:52 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:96:35:96:36 | l1 | main.rs:96:17:96:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:96:35:96:36 | l1 | main.rs:109:35:109:36 | l1 | provenance | |
| main.rs:96:35:96:36 | l1 | main.rs:111:35:111:36 | l1 | provenance | |
-| main.rs:97:35:97:36 | l2 | main.rs:97:17:97:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:99:31:99:31 | v | main.rs:81:33:81:40 | ...: usize | provenance | |
-| main.rs:101:13:101:14 | l3 | main.rs:103:35:103:36 | l3 | provenance | |
-| main.rs:101:18:101:52 | ...::array::<...>(...) [Ok] | main.rs:101:18:101:61 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:101:18:101:61 | ... .unwrap(...) | main.rs:101:13:101:14 | l3 | provenance | |
-| main.rs:101:51:101:51 | v | main.rs:101:18:101:52 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:102:35:102:36 | l1 | main.rs:102:17:102:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:102:35:102:36 | l1 | main.rs:109:35:109:36 | l1 | provenance | |
| main.rs:102:35:102:36 | l1 | main.rs:111:35:111:36 | l1 | provenance | |
-| main.rs:103:35:103:36 | l3 | main.rs:103:17:103:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:105:33:105:33 | v | main.rs:86:35:86:42 | ...: usize | provenance | |
| main.rs:109:35:109:36 | l1 | main.rs:109:17:109:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:109:35:109:36 | l1 | main.rs:146:35:146:36 | l1 | provenance | |
| main.rs:111:35:111:36 | l1 | main.rs:111:17:111:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:111:35:111:36 | l1 | main.rs:146:35:146:36 | l1 | provenance | |
-| main.rs:115:13:115:14 | l4 | main.rs:116:35:116:36 | l4 | provenance | |
-| main.rs:115:18:115:58 | ...::from_size_align(...) [Ok] | main.rs:115:18:115:67 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:115:18:115:67 | ... .unwrap(...) | main.rs:115:13:115:14 | l4 | provenance | |
-| main.rs:115:54:115:54 | v | main.rs:115:18:115:58 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
-| main.rs:116:35:116:36 | l4 | main.rs:116:17:116:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:120:13:120:14 | l5 | main.rs:121:35:121:36 | l5 | provenance | |
-| main.rs:120:18:120:58 | ...::from_size_align(...) [Ok] | main.rs:120:18:120:67 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:120:18:120:67 | ... .unwrap(...) | main.rs:120:13:120:14 | l5 | provenance | |
-| main.rs:120:54:120:54 | v | main.rs:120:18:120:58 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
-| main.rs:121:35:121:36 | l5 | main.rs:121:17:121:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:125:13:125:14 | l6 | main.rs:126:35:126:36 | l6 | provenance | |
-| main.rs:125:18:125:58 | ...::from_size_align(...) [Ok] | main.rs:125:18:125:67 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:125:18:125:67 | ... .unwrap(...) | main.rs:125:13:125:14 | l6 | provenance | |
-| main.rs:125:54:125:54 | v | main.rs:125:18:125:58 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
-| main.rs:126:35:126:36 | l6 | main.rs:126:17:126:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:131:9:131:10 | l7 | main.rs:135:31:135:32 | l7 | provenance | |
-| main.rs:131:14:131:54 | ...::from_size_align(...) [Ok] | main.rs:131:14:131:63 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:131:14:131:63 | ... .unwrap(...) | main.rs:131:9:131:10 | l7 | provenance | |
-| main.rs:131:50:131:50 | v | main.rs:131:14:131:54 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
-| main.rs:135:31:135:32 | l7 | main.rs:135:13:135:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:138:13:138:21 | mut v_mut | main.rs:144:51:144:55 | v_mut | provenance | |
-| main.rs:144:13:144:14 | l8 | main.rs:147:35:147:36 | l8 | provenance | |
-| main.rs:144:18:144:56 | ...::array::<...>(...) [Ok] | main.rs:144:18:144:65 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:144:18:144:65 | ... .unwrap(...) | main.rs:144:13:144:14 | l8 | provenance | |
-| main.rs:144:51:144:55 | v_mut | main.rs:144:18:144:56 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
-| main.rs:145:13:145:14 | l9 | main.rs:148:35:148:36 | l9 | provenance | |
-| main.rs:145:18:145:52 | ...::array::<...>(...) [Ok] | main.rs:145:18:145:61 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:145:18:145:61 | ... .unwrap(...) | main.rs:145:13:145:14 | l9 | provenance | |
-| main.rs:145:51:145:51 | v | main.rs:145:18:145:52 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:146:35:146:36 | l1 | main.rs:146:17:146:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:146:35:146:36 | l1 | main.rs:177:31:177:32 | l1 | provenance | |
-| main.rs:147:35:147:36 | l8 | main.rs:147:17:147:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:148:35:148:36 | l9 | main.rs:148:17:148:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:151:9:151:11 | l10 | main.rs:152:31:152:33 | l10 | provenance | |
-| main.rs:151:15:151:69 | ...::array::<...>(...) [Ok] | main.rs:151:15:151:78 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:151:15:151:78 | ... .unwrap(...) | main.rs:151:9:151:11 | l10 | provenance | |
-| main.rs:151:48:151:68 | ...::min(...) | main.rs:151:15:151:69 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
-| main.rs:151:62:151:62 | v | main.rs:151:48:151:68 | ...::min(...) | provenance | MaD:34 |
-| main.rs:152:31:152:33 | l10 | main.rs:152:13:152:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:154:9:154:11 | l11 | main.rs:155:31:155:33 | l11 | provenance | |
-| main.rs:154:15:154:69 | ...::array::<...>(...) [Ok] | main.rs:154:15:154:78 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:154:15:154:78 | ... .unwrap(...) | main.rs:154:9:154:11 | l11 | provenance | |
-| main.rs:154:48:154:68 | ...::max(...) | main.rs:154:15:154:69 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
-| main.rs:154:62:154:62 | v | main.rs:154:48:154:68 | ...::max(...) | provenance | MaD:33 |
-| main.rs:155:31:155:33 | l11 | main.rs:155:13:155:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:157:9:157:11 | l12 | main.rs:158:31:158:33 | l12 | provenance | |
-| main.rs:157:15:157:64 | ...::array::<...>(...) [Ok] | main.rs:157:15:157:73 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:157:15:157:73 | ... .unwrap(...) | main.rs:157:9:157:11 | l12 | provenance | |
-| main.rs:157:48:157:63 | clamp(...) | main.rs:157:15:157:64 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
-| main.rs:157:54:157:54 | v | main.rs:71:35:71:38 | ...: T | provenance | |
-| main.rs:157:54:157:54 | v | main.rs:157:48:157:63 | clamp(...) | provenance | |
-| main.rs:158:31:158:33 | l12 | main.rs:158:13:158:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:161:13:161:15 | l13 | main.rs:162:35:162:37 | l13 | provenance | |
-| main.rs:161:19:161:59 | ...::from_size_align(...) [Ok] | main.rs:161:19:161:68 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:161:19:161:68 | ... .unwrap(...) | main.rs:161:13:161:15 | l13 | provenance | |
-| main.rs:161:55:161:55 | v | main.rs:161:19:161:59 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
-| main.rs:162:35:162:37 | l13 | main.rs:162:17:162:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:162:35:162:37 | l13 | main.rs:169:35:169:37 | l13 | provenance | |
-| main.rs:168:13:168:15 | l14 | main.rs:170:35:170:37 | l14 | provenance | |
-| main.rs:168:19:168:59 | ...::from_size_align(...) [Ok] | main.rs:168:19:168:68 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:168:19:168:68 | ... .unwrap(...) | main.rs:168:13:168:15 | l14 | provenance | |
-| main.rs:168:55:168:55 | v | main.rs:168:19:168:59 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
-| main.rs:169:35:169:37 | l13 | main.rs:169:17:169:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:170:35:170:37 | l14 | main.rs:170:17:170:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:176:9:176:11 | l15 | main.rs:178:31:178:33 | l15 | provenance | |
-| main.rs:176:15:176:55 | ...::from_size_align(...) [Ok] | main.rs:176:15:176:64 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:176:15:176:64 | ... .unwrap(...) | main.rs:176:9:176:11 | l15 | provenance | |
-| main.rs:176:51:176:51 | v | main.rs:176:15:176:55 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
| main.rs:177:31:177:32 | l1 | main.rs:177:13:177:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:178:31:178:33 | l15 | main.rs:178:13:178:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:183:29:183:36 | ...: usize | main.rs:192:46:192:46 | v | provenance | |
| main.rs:192:9:192:10 | l2 | main.rs:193:38:193:39 | l2 | provenance | |
| main.rs:192:14:192:47 | ...::array::<...>(...) [Ok] | main.rs:192:14:192:56 | ... .unwrap(...) | provenance | MaD:31 |
@@ -322,31 +196,17 @@ edges
| main.rs:282:18:282:75 | ... .unwrap(...) | main.rs:282:9:282:14 | layout | provenance | |
| main.rs:282:54:282:62 | num_bytes | main.rs:282:18:282:66 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
| main.rs:284:40:284:45 | layout | main.rs:284:22:284:38 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
-| main.rs:292:25:292:42 | ...: String | main.rs:293:16:293:42 | user_input.parse(...) [Ok] | provenance | MaD:32 |
-| main.rs:293:9:293:12 | size | main.rs:297:9:297:17 | num_bytes | provenance | |
-| main.rs:293:16:293:42 | user_input.parse(...) [Ok] | main.rs:293:16:293:43 | TryExpr | provenance | |
-| main.rs:293:16:293:43 | TryExpr | main.rs:293:9:293:12 | size | provenance | |
-| main.rs:297:9:297:17 | num_bytes | main.rs:299:54:299:62 | num_bytes | provenance | |
-| main.rs:299:9:299:14 | layout | main.rs:301:40:301:45 | layout | provenance | |
-| main.rs:299:18:299:66 | ...::from_size_align(...) [Ok] | main.rs:299:18:299:75 | ... .unwrap(...) | provenance | MaD:31 |
-| main.rs:299:18:299:75 | ... .unwrap(...) | main.rs:299:9:299:14 | layout | provenance | |
-| main.rs:299:54:299:62 | num_bytes | main.rs:299:18:299:66 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
-| main.rs:301:40:301:45 | layout | main.rs:301:22:301:38 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:308:25:308:38 | ...::args | main.rs:308:25:308:40 | ...::args(...) [element] | provenance | Src:MaD:16 |
-| main.rs:308:25:308:40 | ...::args(...) [element] | main.rs:308:25:308:47 | ... .nth(...) [Some] | provenance | MaD:35 |
+| main.rs:308:25:308:40 | ...::args(...) [element] | main.rs:308:25:308:47 | ... .nth(...) [Some] | provenance | MaD:33 |
| main.rs:308:25:308:47 | ... .nth(...) [Some] | main.rs:308:25:308:74 | ... .unwrap_or(...) | provenance | MaD:29 |
| main.rs:308:25:308:74 | ... .unwrap_or(...) | main.rs:279:24:279:41 | ...: String | provenance | |
-| main.rs:309:26:309:39 | ...::args | main.rs:309:26:309:41 | ...::args(...) [element] | provenance | Src:MaD:16 |
-| main.rs:309:26:309:41 | ...::args(...) [element] | main.rs:309:26:309:48 | ... .nth(...) [Some] | provenance | MaD:35 |
-| main.rs:309:26:309:48 | ... .nth(...) [Some] | main.rs:309:26:309:75 | ... .unwrap_or(...) | provenance | MaD:29 |
-| main.rs:309:26:309:75 | ... .unwrap_or(...) | main.rs:292:25:292:42 | ...: String | provenance | |
| main.rs:317:9:317:9 | v | main.rs:320:34:320:34 | v | provenance | |
| main.rs:317:9:317:9 | v | main.rs:321:42:321:42 | v | provenance | |
| main.rs:317:9:317:9 | v | main.rs:322:36:322:36 | v | provenance | |
| main.rs:317:9:317:9 | v | main.rs:323:27:323:27 | v | provenance | |
| main.rs:317:9:317:9 | v | main.rs:324:25:324:25 | v | provenance | |
| main.rs:317:13:317:26 | ...::args | main.rs:317:13:317:28 | ...::args(...) [element] | provenance | Src:MaD:16 |
-| main.rs:317:13:317:28 | ...::args(...) [element] | main.rs:317:13:317:35 | ... .nth(...) [Some] | provenance | MaD:35 |
+| main.rs:317:13:317:28 | ...::args(...) [element] | main.rs:317:13:317:35 | ... .nth(...) [Some] | provenance | MaD:33 |
| main.rs:317:13:317:35 | ... .nth(...) [Some] | main.rs:317:13:317:65 | ... .unwrap_or(...) | provenance | MaD:29 |
| main.rs:317:13:317:65 | ... .unwrap_or(...) | main.rs:317:13:317:82 | ... .parse(...) [Ok] | provenance | MaD:32 |
| main.rs:317:13:317:82 | ... .parse(...) [Ok] | main.rs:317:13:317:91 | ... .unwrap(...) | provenance | MaD:31 |
@@ -389,9 +249,7 @@ models
| 30 | Summary: lang:core; ::expect; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value |
| 31 | Summary: lang:core; ::unwrap; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value |
| 32 | Summary: lang:core; ::parse; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
-| 33 | Summary: lang:core; crate::cmp::max; Argument[0]; ReturnValue; value |
-| 34 | Summary: lang:core; crate::cmp::min; Argument[0]; ReturnValue; value |
-| 35 | Summary: lang:core; crate::iter::traits::iterator::Iterator::nth; Argument[self].Element; ReturnValue.Field[crate::option::Option::Some(0)]; value |
+| 33 | Summary: lang:core; crate::iter::traits::iterator::Iterator::nth; Argument[self].Element; ReturnValue.Field[crate::option::Option::Some(0)]; value |
nodes
| main.rs:12:36:12:43 | ...: usize | semmle.label | ...: usize |
| main.rs:18:13:18:31 | ...::realloc | semmle.label | ...::realloc |
@@ -484,131 +342,23 @@ nodes
| main.rs:67:46:67:46 | v | semmle.label | v |
| main.rs:68:13:68:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:68:31:68:32 | l4 | semmle.label | l4 |
-| main.rs:71:35:71:38 | ...: T | semmle.label | ...: T |
-| main.rs:77:9:77:16 | return v | semmle.label | return v |
-| main.rs:81:33:81:40 | ...: usize | semmle.label | ...: usize |
-| main.rs:82:9:82:14 | layout | semmle.label | layout |
-| main.rs:82:18:82:58 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
-| main.rs:82:18:82:67 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:82:54:82:54 | v | semmle.label | v |
-| main.rs:83:13:83:29 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:83:31:83:36 | layout | semmle.label | layout |
-| main.rs:86:35:86:42 | ...: usize | semmle.label | ...: usize |
-| main.rs:87:9:87:14 | layout | semmle.label | layout |
-| main.rs:87:18:87:58 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
-| main.rs:87:18:87:67 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:87:54:87:54 | v | semmle.label | v |
-| main.rs:88:13:88:29 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:88:31:88:36 | layout | semmle.label | layout |
| main.rs:91:38:91:45 | ...: usize | semmle.label | ...: usize |
| main.rs:92:9:92:10 | l1 | semmle.label | l1 |
| main.rs:92:14:92:48 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
| main.rs:92:14:92:57 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
| main.rs:92:47:92:47 | v | semmle.label | v |
-| main.rs:95:13:95:14 | l2 | semmle.label | l2 |
-| main.rs:95:18:95:52 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
-| main.rs:95:18:95:61 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:95:51:95:51 | v | semmle.label | v |
| main.rs:96:17:96:33 | ...::alloc | semmle.label | ...::alloc |
| main.rs:96:35:96:36 | l1 | semmle.label | l1 |
-| main.rs:97:17:97:33 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:97:35:97:36 | l2 | semmle.label | l2 |
-| main.rs:99:31:99:31 | v | semmle.label | v |
-| main.rs:101:13:101:14 | l3 | semmle.label | l3 |
-| main.rs:101:18:101:52 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
-| main.rs:101:18:101:61 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:101:51:101:51 | v | semmle.label | v |
| main.rs:102:17:102:33 | ...::alloc | semmle.label | ...::alloc |
| main.rs:102:35:102:36 | l1 | semmle.label | l1 |
-| main.rs:103:17:103:33 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:103:35:103:36 | l3 | semmle.label | l3 |
-| main.rs:105:33:105:33 | v | semmle.label | v |
| main.rs:109:17:109:33 | ...::alloc | semmle.label | ...::alloc |
| main.rs:109:35:109:36 | l1 | semmle.label | l1 |
| main.rs:111:17:111:33 | ...::alloc | semmle.label | ...::alloc |
| main.rs:111:35:111:36 | l1 | semmle.label | l1 |
-| main.rs:115:13:115:14 | l4 | semmle.label | l4 |
-| main.rs:115:18:115:58 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
-| main.rs:115:18:115:67 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:115:54:115:54 | v | semmle.label | v |
-| main.rs:116:17:116:33 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:116:35:116:36 | l4 | semmle.label | l4 |
-| main.rs:120:13:120:14 | l5 | semmle.label | l5 |
-| main.rs:120:18:120:58 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
-| main.rs:120:18:120:67 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:120:54:120:54 | v | semmle.label | v |
-| main.rs:121:17:121:33 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:121:35:121:36 | l5 | semmle.label | l5 |
-| main.rs:125:13:125:14 | l6 | semmle.label | l6 |
-| main.rs:125:18:125:58 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
-| main.rs:125:18:125:67 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:125:54:125:54 | v | semmle.label | v |
-| main.rs:126:17:126:33 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:126:35:126:36 | l6 | semmle.label | l6 |
-| main.rs:131:9:131:10 | l7 | semmle.label | l7 |
-| main.rs:131:14:131:54 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
-| main.rs:131:14:131:63 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:131:50:131:50 | v | semmle.label | v |
-| main.rs:135:13:135:29 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:135:31:135:32 | l7 | semmle.label | l7 |
-| main.rs:138:13:138:21 | mut v_mut | semmle.label | mut v_mut |
-| main.rs:144:13:144:14 | l8 | semmle.label | l8 |
-| main.rs:144:18:144:56 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
-| main.rs:144:18:144:65 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:144:51:144:55 | v_mut | semmle.label | v_mut |
-| main.rs:145:13:145:14 | l9 | semmle.label | l9 |
-| main.rs:145:18:145:52 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
-| main.rs:145:18:145:61 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:145:51:145:51 | v | semmle.label | v |
| main.rs:146:17:146:33 | ...::alloc | semmle.label | ...::alloc |
| main.rs:146:35:146:36 | l1 | semmle.label | l1 |
-| main.rs:147:17:147:33 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:147:35:147:36 | l8 | semmle.label | l8 |
-| main.rs:148:17:148:33 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:148:35:148:36 | l9 | semmle.label | l9 |
-| main.rs:151:9:151:11 | l10 | semmle.label | l10 |
-| main.rs:151:15:151:69 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
-| main.rs:151:15:151:78 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:151:48:151:68 | ...::min(...) | semmle.label | ...::min(...) |
-| main.rs:151:62:151:62 | v | semmle.label | v |
-| main.rs:152:13:152:29 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:152:31:152:33 | l10 | semmle.label | l10 |
-| main.rs:154:9:154:11 | l11 | semmle.label | l11 |
-| main.rs:154:15:154:69 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
-| main.rs:154:15:154:78 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:154:48:154:68 | ...::max(...) | semmle.label | ...::max(...) |
-| main.rs:154:62:154:62 | v | semmle.label | v |
-| main.rs:155:13:155:29 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:155:31:155:33 | l11 | semmle.label | l11 |
-| main.rs:157:9:157:11 | l12 | semmle.label | l12 |
-| main.rs:157:15:157:64 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
-| main.rs:157:15:157:73 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:157:48:157:63 | clamp(...) | semmle.label | clamp(...) |
-| main.rs:157:54:157:54 | v | semmle.label | v |
-| main.rs:158:13:158:29 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:158:31:158:33 | l12 | semmle.label | l12 |
-| main.rs:161:13:161:15 | l13 | semmle.label | l13 |
-| main.rs:161:19:161:59 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
-| main.rs:161:19:161:68 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:161:55:161:55 | v | semmle.label | v |
-| main.rs:162:17:162:33 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:162:35:162:37 | l13 | semmle.label | l13 |
-| main.rs:168:13:168:15 | l14 | semmle.label | l14 |
-| main.rs:168:19:168:59 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
-| main.rs:168:19:168:68 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:168:55:168:55 | v | semmle.label | v |
-| main.rs:169:17:169:33 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:169:35:169:37 | l13 | semmle.label | l13 |
-| main.rs:170:17:170:33 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:170:35:170:37 | l14 | semmle.label | l14 |
-| main.rs:176:9:176:11 | l15 | semmle.label | l15 |
-| main.rs:176:15:176:55 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
-| main.rs:176:15:176:64 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:176:51:176:51 | v | semmle.label | v |
| main.rs:177:13:177:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:177:31:177:32 | l1 | semmle.label | l1 |
-| main.rs:178:13:178:29 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:178:31:178:33 | l15 | semmle.label | l15 |
| main.rs:183:29:183:36 | ...: usize | semmle.label | ...: usize |
| main.rs:192:9:192:10 | l2 | semmle.label | l2 |
| main.rs:192:14:192:47 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
@@ -656,25 +406,10 @@ nodes
| main.rs:282:54:282:62 | num_bytes | semmle.label | num_bytes |
| main.rs:284:22:284:38 | ...::alloc | semmle.label | ...::alloc |
| main.rs:284:40:284:45 | layout | semmle.label | layout |
-| main.rs:292:25:292:42 | ...: String | semmle.label | ...: String |
-| main.rs:293:9:293:12 | size | semmle.label | size |
-| main.rs:293:16:293:42 | user_input.parse(...) [Ok] | semmle.label | user_input.parse(...) [Ok] |
-| main.rs:293:16:293:43 | TryExpr | semmle.label | TryExpr |
-| main.rs:297:9:297:17 | num_bytes | semmle.label | num_bytes |
-| main.rs:299:9:299:14 | layout | semmle.label | layout |
-| main.rs:299:18:299:66 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
-| main.rs:299:18:299:75 | ... .unwrap(...) | semmle.label | ... .unwrap(...) |
-| main.rs:299:54:299:62 | num_bytes | semmle.label | num_bytes |
-| main.rs:301:22:301:38 | ...::alloc | semmle.label | ...::alloc |
-| main.rs:301:40:301:45 | layout | semmle.label | layout |
| main.rs:308:25:308:38 | ...::args | semmle.label | ...::args |
| main.rs:308:25:308:40 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
| main.rs:308:25:308:47 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
| main.rs:308:25:308:74 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
-| main.rs:309:26:309:39 | ...::args | semmle.label | ...::args |
-| main.rs:309:26:309:41 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
-| main.rs:309:26:309:48 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
-| main.rs:309:26:309:75 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
| main.rs:317:9:317:9 | v | semmle.label | v |
| main.rs:317:13:317:26 | ...::args | semmle.label | ...::args |
| main.rs:317:13:317:28 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
@@ -688,4 +423,3 @@ nodes
| main.rs:323:27:323:27 | v | semmle.label | v |
| main.rs:324:25:324:25 | v | semmle.label | v |
subpaths
-| main.rs:157:54:157:54 | v | main.rs:71:35:71:38 | ...: T | main.rs:77:9:77:16 | return v | main.rs:157:48:157:63 | clamp(...) |
diff --git a/rust/ql/test/query-tests/security/CWE-770/main.rs b/rust/ql/test/query-tests/security/CWE-770/main.rs
index 558979ebfc2c..e9cea0f604a7 100644
--- a/rust/ql/test/query-tests/security/CWE-770/main.rs
+++ b/rust/ql/test/query-tests/security/CWE-770/main.rs
@@ -80,12 +80,12 @@ fn clamp(v: T, min: T, max: T) -> T {
unsafe fn test_fn_alloc_bounded(v: usize) {
let layout = std::alloc::Layout::from_size_align(v, 1).unwrap();
- let _ = std::alloc::alloc(layout); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(layout); // $ GOOD (bounded)
}
unsafe fn test_fn_alloc_unbounded(v: usize) {
let layout = std::alloc::Layout::from_size_align(v, 1).unwrap();
- let _ = std::alloc::alloc(layout); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(layout); // $ MISSING: Alert[rust/uncontrolled-allocation-size]=arg1
}
unsafe fn test_std_alloc_with_bounds(v: usize, limit: usize) {
@@ -94,13 +94,13 @@ unsafe fn test_std_alloc_with_bounds(v: usize, limit: usize) {
if v < 100 {
let l2 = std::alloc::Layout::array::(v).unwrap();
let _ = std::alloc::alloc(l1); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
- let _ = std::alloc::alloc(l2); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(l2); // $ GOOD (bounded)
test_fn_alloc_bounded(v);
} else {
let l3 = std::alloc::Layout::array::(v).unwrap();
let _ = std::alloc::alloc(l1); // $ Alert[rust/uncontrolled-allocation-size]=arg1
- let _ = std::alloc::alloc(l3); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(l3); // $ MISSING: Alert[rust/uncontrolled-allocation-size]=arg1
test_fn_alloc_unbounded(v);
}
@@ -113,17 +113,17 @@ unsafe fn test_std_alloc_with_bounds(v: usize, limit: usize) {
if (v < limit) {
let l4 = std::alloc::Layout::from_size_align(v, 1).unwrap();
- let _ = std::alloc::alloc(l4); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(l4); // $ GOOD (bounded)
}
if (v < 2 * v) { // not a good bound
let l5 = std::alloc::Layout::from_size_align(v, 1).unwrap();
- let _ = std::alloc::alloc(l5); // $ Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(l5); // $ MISSING: Alert[rust/uncontrolled-allocation-size]=arg1
}
if (true && v < limit && true) {
let l6 = std::alloc::Layout::from_size_align(v, 1).unwrap();
- let _ = std::alloc::alloc(l6); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(l6); // $ GOOD (bounded)
}
let mut l7;
@@ -132,7 +132,7 @@ unsafe fn test_std_alloc_with_bounds(v: usize, limit: usize) {
} else {
l7 = std::alloc::Layout::from_size_align(100, 1).unwrap();
}
- let _ = std::alloc::alloc(l7); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
+ let _ = std::alloc::alloc(l7); // $ GOOD (bounded)
{
let mut v_mut = v;
@@ -144,30 +144,30 @@ unsafe fn test_std_alloc_with_bounds(v: usize, limit: usize) {
let l8 = std::alloc::Layout::array::(v_mut).unwrap();
let l9 = std::alloc::Layout::array::