From 38f00775bd87f6c1f27608dc23e072671c07cda5 Mon Sep 17 00:00:00 2001 From: Adnan Khan Date: Fri, 25 Apr 2025 14:49:01 -0400 Subject: [PATCH 001/199] Exclude artifacts downloaded to runner temp. --- .../ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/actions/ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll b/actions/ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll index d8d5f83c867..24e0f400e92 100644 --- a/actions/ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll +++ b/actions/ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll @@ -262,8 +262,9 @@ class ArtifactPoisoningSink extends DataFlow::Node { ArtifactPoisoningSink() { download.getAFollowingStep() = poisonable and - // excluding artifacts downloaded to /tmp + // excluding artifacts downloaded to /tmp and runner.tmp not download.getPath().regexpMatch("^/tmp.*") and + not download.getPath().regexpMatch("^\${{\s?runner.temp\s?}}.*") and ( poisonable.(Run).getScript() = this.asExpr() and ( From a9c4d6f383c68df3491fb6537519139aacee7681 Mon Sep 17 00:00:00 2001 From: Adnan Khan Date: Fri, 25 Apr 2025 15:00:14 -0400 Subject: [PATCH 002/199] Fix escaping. --- .../ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll b/actions/ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll index 24e0f400e92..8c6471b3c58 100644 --- a/actions/ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll +++ b/actions/ql/lib/codeql/actions/security/ArtifactPoisoningQuery.qll @@ -264,7 +264,7 @@ class ArtifactPoisoningSink extends DataFlow::Node { download.getAFollowingStep() = poisonable and // excluding artifacts downloaded to /tmp and runner.tmp not download.getPath().regexpMatch("^/tmp.*") and - not download.getPath().regexpMatch("^\${{\s?runner.temp\s?}}.*") and + not download.getPath().regexpMatch("^\\${{\\s?runner.temp\\s?}}.*") and ( poisonable.(Run).getScript() = this.asExpr() and ( From f96a250ffc511b3d710ef2cb26b896c27aa520f3 Mon Sep 17 00:00:00 2001 From: Lindsay Simpkins Date: Mon, 9 Jun 2025 18:36:44 -0400 Subject: [PATCH 003/199] fix qhelp files --- .../src/Metrics/Classes/CNumberOfFunctions.qhelp | 11 +++-------- cpp/ql/src/Metrics/Classes/CSizeOfAPI.qhelp | 12 ++++-------- .../src/Metrics/RefTypes/TInheritanceDepth.qhelp | 14 ++++---------- .../src/Metrics/RefTypes/TNumberOfCallables.qhelp | 12 ++++-------- java/ql/src/Metrics/RefTypes/TNumberOfFields.qhelp | 2 -- java/ql/src/Metrics/RefTypes/TSizeOfAPI.qhelp | 12 ++++-------- 6 files changed, 19 insertions(+), 44 deletions(-) diff --git a/cpp/ql/src/Metrics/Classes/CNumberOfFunctions.qhelp b/cpp/ql/src/Metrics/Classes/CNumberOfFunctions.qhelp index cc62cb50f49..8ef045c7092 100644 --- a/cpp/ql/src/Metrics/Classes/CNumberOfFunctions.qhelp +++ b/cpp/ql/src/Metrics/Classes/CNumberOfFunctions.qhelp @@ -49,21 +49,16 @@ need to be part of the class. (A classic example of this is the observes, there are at least two key problems with this approach: -
    -
  • -It may be possible to generalize some of the utility functions beyond the +1. It may be possible to generalize some of the utility functions beyond the narrow context of the class in question -- by bundling them with the class, the class author reduces the scope for functionality reuse. -
  • -
  • -It's usually impossible for the class author to know every possible +2. It's usually impossible for the class author to know every possible operation that the user might want to perform on the class, so the public interface will inherently be incomplete. New utility functions will end up having a different syntax to the privileged public functions in the class, negatively impacting on code consistency. -
  • -
+ To refactor a class like this, simply move its utility functions elsewhere, paring its public interface down to the bare minimum. diff --git a/cpp/ql/src/Metrics/Classes/CSizeOfAPI.qhelp b/cpp/ql/src/Metrics/Classes/CSizeOfAPI.qhelp index 0d560f920aa..70c4c862fb6 100644 --- a/cpp/ql/src/Metrics/Classes/CSizeOfAPI.qhelp +++ b/cpp/ql/src/Metrics/Classes/CSizeOfAPI.qhelp @@ -46,21 +46,17 @@ need to be part of the class. (A classic example of this is the std::string class in the C++ Standard Library.) As [Sutter] observes, there are at least two key problems with this approach: -
    -
  • -It may be possible to generalize some of the utility functions beyond the + +1. It may be possible to generalize some of the utility functions beyond the narrow context of the class in question -- by bundling them with the class, the class author reduces the scope for functionality reuse. -
  • -
  • -It's usually impossible for the class author to know every possible +2. It's usually impossible for the class author to know every possible operation that the user might want to perform on the class, so the public interface will inherently be incomplete. New utility functions will end up having a different syntax to the privileged public functions in the class, negatively impacting on code consistency. -
  • -
+ To refactor a class like this, simply move its utility functions elsewhere, paring its public interface down to the bare minimum. diff --git a/java/ql/src/Metrics/RefTypes/TInheritanceDepth.qhelp b/java/ql/src/Metrics/RefTypes/TInheritanceDepth.qhelp index 7d78490985b..970b1c4e19e 100644 --- a/java/ql/src/Metrics/RefTypes/TInheritanceDepth.qhelp +++ b/java/ql/src/Metrics/RefTypes/TInheritanceDepth.qhelp @@ -29,14 +29,13 @@ that something is amiss, but further investigation will be needed to clarify the cause of the problem. Here are two possibilities:

-
    - -
  • -A class and its superclass represent fundamentally the same abstraction. +

    +1. A class and its superclass represent fundamentally the same abstraction. In this case, they should generally be merged together (see the 'Collapse Hierarchy' refactoring on pp.279-80 of [Fowler]). For example, suppose that in the following class hierarchy both A and C represent fundamentally the same thing, then they should be merged together as shown: +

    @@ -48,11 +47,9 @@ the same thing, then they should be merged together as shown:
    After
    -
  • -
  • -The class hierarchy is trying to represent variation in more than one +2. The class hierarchy is trying to represent variation in more than one dimension using single inheritance. This can lead to an unnecessarily deep class hierarchy with lots of code duplication. For example, consider the following: @@ -81,9 +78,6 @@ amount of code duplication that will be necessary. For readers who are interested in this sort of approach, a good reference is [West].

    -
  • - -
diff --git a/java/ql/src/Metrics/RefTypes/TNumberOfCallables.qhelp b/java/ql/src/Metrics/RefTypes/TNumberOfCallables.qhelp index 49827592849..4f9452789a8 100644 --- a/java/ql/src/Metrics/RefTypes/TNumberOfCallables.qhelp +++ b/java/ql/src/Metrics/RefTypes/TNumberOfCallables.qhelp @@ -49,21 +49,17 @@ need to be part of the class. (A classic example of this is the std::string class in the C++ Standard Library.) As [Sutter] observes, there are at least two key problems with this approach: -
    -
  • -It may be possible to generalize some of the utility methods beyond the + +1. It may be possible to generalize some of the utility methods beyond the narrow context of the class in question -- by bundling them with the class, the class author reduces the scope for functionality reuse. -
  • -
  • -It's usually impossible for the class author to know every possible +2. It's usually impossible for the class author to know every possible operation that the user might want to perform on the class, so the public interface will inherently be incomplete. New utility methods will end up having a different syntax to the privileged public methods in the class, negatively impacting on code consistency. -
  • -
+ To refactor a class like this, simply move its utility methods elsewhere, paring its public interface down to the bare minimum. diff --git a/java/ql/src/Metrics/RefTypes/TNumberOfFields.qhelp b/java/ql/src/Metrics/RefTypes/TNumberOfFields.qhelp index befc6409449..2934ba958b5 100644 --- a/java/ql/src/Metrics/RefTypes/TNumberOfFields.qhelp +++ b/java/ql/src/Metrics/RefTypes/TNumberOfFields.qhelp @@ -25,11 +25,9 @@ If the class is too big, you should split it into multiple smaller classes.
  • -

    If several of the fields are part of the same abstraction, you should group them into a separate class, using the 'Extract Class' refactoring described in [Fowler]. -

  • diff --git a/java/ql/src/Metrics/RefTypes/TSizeOfAPI.qhelp b/java/ql/src/Metrics/RefTypes/TSizeOfAPI.qhelp index 3095d82049a..eda183a287c 100644 --- a/java/ql/src/Metrics/RefTypes/TSizeOfAPI.qhelp +++ b/java/ql/src/Metrics/RefTypes/TSizeOfAPI.qhelp @@ -46,21 +46,17 @@ need to be part of the class. (A classic example of this is the std::string class in the C++ Standard Library.) As [Sutter] observes, there are at least two key problems with this approach: -
      -
    • -It may be possible to generalize some of the utility methods beyond the + +1. It may be possible to generalize some of the utility methods beyond the narrow context of the class in question -- by bundling them with the class, the class author reduces the scope for functionality reuse. -
    • -
    • -It's usually impossible for the class author to know every possible +2. It's usually impossible for the class author to know every possible operation that the user might want to perform on the class, so the public interface will inherently be incomplete. New utility methods will end up having a different syntax to the privileged public methods in the class, negatively impacting on code consistency. -
    • -
    + To refactor a class like this, simply move its utility methods elsewhere, paring its public interface down to the bare minimum. From cb6640474ed280239eb7496828b8c9575d479685 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 19 Jun 2025 19:39:38 +0100 Subject: [PATCH 004/199] Rust: Translate more legacy models -> new models (from data + manual extrapolation). --- .../codeql/rust/frameworks/postgres.model.yml | 22 ++--- .../rustcrypto/rustcrypto.model.yml | 12 +-- .../rust/frameworks/stdlib/io.model.yml | 64 +++++++------- .../rust/frameworks/tokio-postgres.model.yml | 33 ++++--- .../codeql/rust/frameworks/tokio/io.model.yml | 88 +++++++++---------- 5 files changed, 109 insertions(+), 110 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/postgres.model.yml b/rust/ql/lib/codeql/rust/frameworks/postgres.model.yml index 4aba20e3450..81877ed17bd 100644 --- a/rust/ql/lib/codeql/rust/frameworks/postgres.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/postgres.model.yml @@ -1,15 +1,15 @@ extensions: - addsTo: pack: codeql/rust-all - extensible: sinkModelDeprecated + extensible: sinkModel data: - - ["repo:https://github.com/sfackler/rust-postgres:postgres", "::execute", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:postgres", "::batch_execute", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:postgres", "::prepare", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:postgres", "::prepare_typed", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:postgres", "::query", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:postgres", "::query_one", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:postgres", "::query_opt", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:postgres", "::query_raw", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:postgres", "::query_typed", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:postgres", "::query_typed_raw", "Argument[0]", "sql-injection", "manual"] + - ["::execute", "Argument[0]", "sql-injection", "manual"] + - ["::batch_execute", "Argument[0]", "sql-injection", "manual"] + - ["::prepare", "Argument[0]", "sql-injection", "manual"] + - ["::prepare_typed", "Argument[0]", "sql-injection", "manual"] + - ["::query", "Argument[0]", "sql-injection", "manual"] + - ["::query_one", "Argument[0]", "sql-injection", "manual"] + - ["::query_opt", "Argument[0]", "sql-injection", "manual"] + - ["::query_raw", "Argument[0]", "sql-injection", "manual"] + - ["::query_typed", "Argument[0]", "sql-injection", "manual"] + - ["::query_typed_raw", "Argument[0]", "sql-injection", "manual"] diff --git a/rust/ql/lib/codeql/rust/frameworks/rustcrypto/rustcrypto.model.yml b/rust/ql/lib/codeql/rust/frameworks/rustcrypto/rustcrypto.model.yml index 7b7a7964400..d1aefe5b983 100644 --- a/rust/ql/lib/codeql/rust/frameworks/rustcrypto/rustcrypto.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/rustcrypto/rustcrypto.model.yml @@ -1,10 +1,10 @@ extensions: - addsTo: pack: codeql/rust-all - extensible: sinkModelDeprecated + extensible: sinkModel data: - - ["repo:https://github.com/RustCrypto/traits:digest", "<_ as crate::digest::Digest>::new_with_prefix", "Argument[0]", "hasher-input", "manual"] - - ["repo:https://github.com/RustCrypto/traits:digest", "<_ as crate::digest::Digest>::update", "Argument[0]", "hasher-input", "manual"] - - ["repo:https://github.com/RustCrypto/traits:digest", "<_ as crate::digest::Digest>::chain_update", "Argument[0]", "hasher-input", "manual"] - - ["repo:https://github.com/RustCrypto/traits:digest", "<_ as crate::digest::Digest>::digest", "Argument[0]", "hasher-input", "manual"] - - ["repo:https://github.com/stainless-steel/md5:md5", "crate::compute", "Argument[0]", "hasher-input", "manual"] + - ["::new_with_prefix", "Argument[0]", "hasher-input", "manual"] + - ["::update", "Argument[0]", "hasher-input", "manual"] + - ["::chain_update", "Argument[0]", "hasher-input", "manual"] + - ["::digest", "Argument[0]", "hasher-input", "manual"] + - ["md5::compute", "Argument[0]", "hasher-input", "manual"] diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml index fc86d2fb908..b05ee510586 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml @@ -1,39 +1,39 @@ extensions: - addsTo: pack: codeql/rust-all - extensible: sourceModelDeprecated + extensible: sourceModel data: - - ["lang:std", "crate::io::stdio::stdin", "ReturnValue", "stdin", "manual"] + - ["std::io::stdio::stdin", "ReturnValue", "stdin", "manual"] - addsTo: pack: codeql/rust-all - extensible: summaryModelDeprecated + extensible: summaryModel data: - - ["lang:std", "::new", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["lang:std", "::fill_buf", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["lang:std", "::buffer", "Argument[self]", "ReturnValue", "taint", "manual"] - - ["lang:std", "::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "crate::io::Read::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "crate::io::Read::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", ":::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", ":::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "crate::io::Read::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "crate::io::Read::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "crate::io::BufRead::read_line", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "crate::io::BufRead::read_until", "Argument[self]", "Argument[1].Reference", "taint", "manual"] - - ["lang:std", "crate::io::BufRead::split", "Argument[self]", "ReturnValue", "taint", "manual"] - - ["lang:std", "crate::io::BufRead::lines", "Argument[self]", "ReturnValue", "taint", "manual"] - - ["lang:std", "crate::io::Read::bytes", "Argument[self]", "ReturnValue", "taint", "manual"] - - ["lang:std", "crate::io::Read::chain", "Argument[self]", "ReturnValue", "taint", "manual"] - - ["lang:std", "crate::io::Read::chain", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["lang:std", "crate::io::Read::take", "Argument[self]", "ReturnValue", "taint", "manual"] - - ["lang:std", "::lock", "Argument[self]", "ReturnValue", "taint", "manual"] - - ["lang:std", "::next", "Argument[self]", "ReturnValue.Field[core::option::Option::Some(0)].Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::new", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["::fill_buf", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::buffer", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["<_ as std::io::Read>::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::read_to_string", "", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["<_ as std::io::Read>::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["<_ as std::io::Read>::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["<_ as std::io::Read>::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["<_ as std::io::BufRead>::read_line", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["<_ as std::io::BufRead>::read_until", "Argument[self]", "Argument[1].Reference", "taint", "manual"] + - ["<_ as std::io::BufRead>::split", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["<_ as std::io::BufRead>::lines", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["<_ as std::io::Read>::bytes", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["<_ as std::io::Read>::chain", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["<_ as std::io::Read>::chain", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["<_ as std::io::Read>::take", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["::lock", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["::next", "Argument[self]", "ReturnValue.Field[core::option::Option::Some(0)].Field[core::result::Result::Ok(0)]", "taint", "manual"] diff --git a/rust/ql/lib/codeql/rust/frameworks/tokio-postgres.model.yml b/rust/ql/lib/codeql/rust/frameworks/tokio-postgres.model.yml index 7ad54022784..9cac599357d 100644 --- a/rust/ql/lib/codeql/rust/frameworks/tokio-postgres.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/tokio-postgres.model.yml @@ -1,24 +1,23 @@ extensions: - addsTo: pack: codeql/rust-all - extensible: sinkModelDeprecated + extensible: sinkModel data: - - ["repo:https://github.com/sfackler/rust-postgres:tokio-postgres", "::execute", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:tokio-postgres", "::batch_execute", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:tokio-postgres", "::execute_raw", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:tokio-postgres", "::prepare", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:tokio-postgres", "::prepare_typed", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:tokio-postgres", "::query", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:tokio-postgres", "::query_opt", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:tokio-postgres", "::query_raw", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:tokio-postgres", "::query_typed", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:tokio-postgres", "::query_typed_raw", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:tokio-postgres", "::simple_query", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:tokio-postgres", "::simple_query_raw", "Argument[0]", "sql-injection", "manual"] - + - ["::execute", "Argument[0]", "sql-injection", "manual"] + - ["::batch_execute", "Argument[0]", "sql-injection", "manual"] + - ["::execute_raw", "Argument[0]", "sql-injection", "manual"] + - ["::prepare", "Argument[0]", "sql-injection", "manual"] + - ["::prepare_typed", "Argument[0]", "sql-injection", "manual"] + - ["::query", "Argument[0]", "sql-injection", "manual"] + - ["::query_opt", "Argument[0]", "sql-injection", "manual"] + - ["::query_raw", "Argument[0]", "sql-injection", "manual"] + - ["::query_typed", "Argument[0]", "sql-injection", "manual"] + - ["::query_typed_raw", "Argument[0]", "sql-injection", "manual"] + - ["::simple_query", "Argument[0]", "sql-injection", "manual"] + - ["::simple_query_raw", "Argument[0]", "sql-injection", "manual"] - addsTo: pack: codeql/rust-all - extensible: sourceModelDeprecated + extensible: sourceModel data: - - ["repo:https://github.com/sfackler/rust-postgres:tokio-postgres", "::get", "ReturnValue", "database", "manual"] - - ["repo:https://github.com/sfackler/rust-postgres:tokio-postgres", "::try_get", "ReturnValue.Field[core::result::Result::Ok(0)]", "database", "manual"] + - ["::get", "ReturnValue", "database", "manual"] + - ["::try_get", "ReturnValue.Field[core::result::Result::Ok(0)]", "database", "manual"] diff --git a/rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml b/rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml index 35dcd597c0d..d5e91afa663 100644 --- a/rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml @@ -1,51 +1,51 @@ extensions: - addsTo: pack: codeql/rust-all - extensible: sourceModelDeprecated + extensible: sourceModel data: - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::stdin::stdin", "ReturnValue", "stdin", "manual"] + - ["tokio::io::stdin::stdin", "ReturnValue", "stdin", "manual"] - addsTo: pack: codeql/rust-all - extensible: summaryModelDeprecated + extensible: summaryModel data: - - ["repo:https://github.com/tokio-rs/tokio:tokio", "::new", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_buf_read_ext::AsyncBufReadExt::fill_buf", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "::buffer", "Argument[self]", "ReturnValue", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_buf_read_ext::AsyncBufReadExt::read_line", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_buf_read_ext::AsyncBufReadExt::read_until", "Argument[self]", "Argument[1].Reference", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_buf_read_ext::AsyncBufReadExt::split", "Argument[self]", "ReturnValue", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "::next_segment", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_buf_read_ext::AsyncBufReadExt::lines", "Argument[self]", "ReturnValue", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "::next_line", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_buf", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u8", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u8_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u16", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u16_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u32", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u32_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u64", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u64_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u128", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_u128_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i8", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i8_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i16", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i16_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i32", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i32_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i64", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i64_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i128", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_i128_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_f32", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_f32_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_f64", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::read_f64_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::chain", "Argument[self]", "ReturnValue", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::chain", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["repo:https://github.com/tokio-rs/tokio:tokio", "crate::io::util::async_read_ext::AsyncReadExt::take", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["::new", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["<_ as tokio::io::util::async_buf_read_ext::AsyncBufReadExt>::fill_buf", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::buffer", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_exact ", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["<_ as tokio::io::util::async_buf_read_ext::AsyncBufReadExt>::read_line", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["<_ as tokio::io::util::async_buf_read_ext::AsyncBufReadExt>::read_until", "Argument[self]", "Argument[1].Reference", "taint", "manual"] + - ["<_ as tokio::io::util::async_buf_read_ext::AsyncBufReadExt>::split", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["::next_segment", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_buf_read_ext::AsyncBufReadExt>::lines", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["::next_line", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_buf", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u8", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u8_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u16", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u16_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u32", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u32_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u64", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u64_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u128", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_u128_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i8", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i8_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i16", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i16_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i32", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i32_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i64", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i64_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i128", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_i128_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_f32", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>:::read_f32_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_f64", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_f64_le", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["<_ as core::iter::traits::iterator::Iterator>::chain", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["<_ as core::iter::traits::iterator::Iterator>::chain", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["<_ as core::iter::traits::iterator::Iterator>::take", "Argument[self]", "ReturnValue", "taint", "manual"] From 3027f75617bdc966f6653858171e102cbecd0f7e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 19 Jun 2025 19:39:38 +0100 Subject: [PATCH 005/199] Rust: Translate more legacy models -> new models (from data). --- .../lib/codeql/rust/frameworks/http.model.yml | 18 +-- .../codeql/rust/frameworks/reqwest.model.yml | 34 ++--- .../codeql/rust/frameworks/rusqlite.model.yml | 25 ++-- .../codeql/rust/frameworks/rustls.model.yml | 14 +- .../frameworks/stdlib/lang-alloc.model.yml | 63 ++++----- .../frameworks/stdlib/lang-core.model.yml | 121 +++++++++--------- .../rust/frameworks/stdlib/net.model.yml | 18 +-- 7 files changed, 150 insertions(+), 143 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/http.model.yml b/rust/ql/lib/codeql/rust/frameworks/http.model.yml index 5ad34ef53fe..6a497f34647 100644 --- a/rust/ql/lib/codeql/rust/frameworks/http.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/http.model.yml @@ -1,13 +1,13 @@ extensions: - addsTo: pack: codeql/rust-all - extensible: sourceModelDeprecated + extensible: sourceModel data: - - ["repo:https://github.com/hyperium/hyper:hyper", "::send_request", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "remote", "manual"] - - ["repo:https://github.com/hyperium/hyper:hyper", "::send_request", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "remote", "manual"] - - ["repo:https://github.com/hyperium/hyper:hyper", "::try_send_request", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "remote", "manual"] - - ["repo:https://github.com/hyperium/hyper:hyper", "::try_send_request", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "remote", "manual"] - - ["repo:https://github.com/hyperium/hyper:hyper", "::get", "ReturnValue.Future", "remote", "manual"] - - ["repo:https://github.com/hyperium/hyper:hyper", "::request", "ReturnValue.Future", "remote", "manual"] - - ["repo:https://github.com/hyperium/hyper-util:hyper-util", "::get", "ReturnValue.Future", "remote", "manual"] - - ["repo:https://github.com/hyperium/hyper-util:hyper-util", "::request", "ReturnValue.Future", "remote", "manual"] + - ["::send_request", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "remote", "manual"] + - ["::send_request", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "remote", "manual"] + - ["::try_send_request", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "remote", "manual"] + - ["::try_send_request", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "remote", "manual"] + - ["::get", "ReturnValue.Future", "remote", "manual"] + - ["::request", "ReturnValue.Future", "remote", "manual"] + - ["::get", "ReturnValue.Future", "remote", "manual"] + - ["::request", "ReturnValue.Future", "remote", "manual"] diff --git a/rust/ql/lib/codeql/rust/frameworks/reqwest.model.yml b/rust/ql/lib/codeql/rust/frameworks/reqwest.model.yml index 3974d5b0817..8c24bbf148d 100644 --- a/rust/ql/lib/codeql/rust/frameworks/reqwest.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/reqwest.model.yml @@ -1,27 +1,27 @@ extensions: - addsTo: pack: codeql/rust-all - extensible: sourceModelDeprecated + extensible: sourceModel data: - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "crate::get", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "remote", "manual"] - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "crate::blocking::get", "ReturnValue.Field[core::result::Result::Ok(0)]", "remote", "manual"] + - ["reqwest::get", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "remote", "manual"] + - ["reqwest::blocking::get", "ReturnValue.Field[core::result::Result::Ok(0)]", "remote", "manual"] - addsTo: pack: codeql/rust-all - extensible: sinkModelDeprecated + extensible: sinkModel data: - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::request", "Argument[1]", "transmission", "manual"] - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::request", "Argument[1]", "transmission", "manual"] + - ["::request", "Argument[1]", "transmission", "manual"] + - ["::request", "Argument[1]", "transmission", "manual"] - addsTo: pack: codeql/rust-all - extensible: summaryModelDeprecated + extensible: summaryModel data: - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::text", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::text_with_charset", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::bytes", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::chunk", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "taint", "manual"] - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::text", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::text_with_charset", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::bytes", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::text", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::bytes", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/seanmonstar/reqwest:reqwest", "::chunk", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "taint", "manual"] + - ["::text", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::text_with_charset", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::bytes", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::chunk", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "taint", "manual"] + - ["::text", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::text_with_charset", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::bytes", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::text", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::bytes", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::chunk", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)].Field[core::option::Option::Some(0)]", "taint", "manual"] diff --git a/rust/ql/lib/codeql/rust/frameworks/rusqlite.model.yml b/rust/ql/lib/codeql/rust/frameworks/rusqlite.model.yml index 3da7e2a1bc6..43030de02d5 100644 --- a/rust/ql/lib/codeql/rust/frameworks/rusqlite.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/rusqlite.model.yml @@ -1,20 +1,19 @@ extensions: - addsTo: pack: codeql/rust-all - extensible: sinkModelDeprecated + extensible: sinkModel data: - - ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "::execute", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "::execute_batch", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "::prepare", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "::prepare_with_flags", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "::query_row", "Argument[0]", "sql-injection", "manual"] - - ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "::query_row_and_then", "Argument[0]", "sql-injection", "manual"] - + - ["::execute", "Argument[0]", "sql-injection", "manual"] + - ["::execute_batch", "Argument[0]", "sql-injection", "manual"] + - ["::prepare", "Argument[0]", "sql-injection", "manual"] + - [::prepare_with_flags", "Argument[0]", "sql-injection", "manual"] + - ["::query_row", "Argument[0]", "sql-injection", "manual"] + - ["::query_row_and_then", "Argument[0]", "sql-injection", "manual"] - addsTo: pack: codeql/rust-all - extensible: sourceModelDeprecated + extensible: sourceModel data: - - ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "::get", "ReturnValue.Field[core::result::Result::Ok(0)]", "database", "manual"] - - ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "::get_unwrap", "ReturnValue", "database", "manual"] - - ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "::get_ref", "ReturnValue.Field[core::result::Result::Ok(0)]", "database", "manual"] - - ["repo:https://github.com/rusqlite/rusqlite:rusqlite", "::get_ref_unwrap", "ReturnValue", "database", "manual"] + - ["::get", "ReturnValue.Field[core::result::Result::Ok(0)]", "database", "manual"] + - ["::get_unwrap", "ReturnValue", "database", "manual"] + - ["::get_ref", "ReturnValue.Field[core::result::Result::Ok(0)]", "database", "manual"] + - ["::get_ref_unwrap", "ReturnValue", "database", "manual"] diff --git a/rust/ql/lib/codeql/rust/frameworks/rustls.model.yml b/rust/ql/lib/codeql/rust/frameworks/rustls.model.yml index 1e21646f2ca..19f7ececcd2 100644 --- a/rust/ql/lib/codeql/rust/frameworks/rustls.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/rustls.model.yml @@ -1,14 +1,14 @@ extensions: - addsTo: pack: codeql/rust-all - extensible: sourceModelDeprecated + extensible: sourceModel data: - - ["repo:https://github.com/rustls/rustls:rustls", "::new", "ReturnValue.Field[core::result::Result::Ok(0)]", "remote", "manual"] + - ["::new", "ReturnValue.Field[core::result::Result::Ok(0)]", "remote", "manual"] - addsTo: pack: codeql/rust-all - extensible: summaryModelDeprecated + extensible: summaryModel data: - - ["repo:https://github.com/quininer/futures-rustls:futures-rustls", "::connect", "Argument[1]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/quininer/futures-rustls:futures-rustls", "::poll_read", "Argument[self].Reference", "Argument[1].Reference", "taint", "manual"] - - ["repo:https://github.com/rustls/rustls:rustls", "::reader", "Argument[self]", "ReturnValue", "taint", "manual"] - - ["repo:https://github.com/rustls/rustls:rustls", "::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::connect", "Argument[1]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::poll_read", "Argument[self].Reference", "Argument[1].Reference", "taint", "manual"] + - ["::reader", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["::read", "Argument[self]", "Argument[0].Reference", "taint", "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 eea2f6726db..08fd458576d 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 @@ -1,44 +1,49 @@ extensions: - addsTo: pack: codeql/rust-all - extensible: sourceModelDeprecated + extensible: sourceModel data: # Alloc - - ["lang:alloc", "crate::alloc::dealloc", "Argument[0]", "pointer-invalidate", "manual"] + - ["alloc::alloc::dealloc", "Argument[0]", "pointer-invalidate", "manual"] - addsTo: pack: codeql/rust-all - extensible: sinkModelDeprecated + 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"] + - ["alloc::alloc::alloc", "Argument[0]", "alloc-layout", "manual"] + - ["alloc::alloc::alloc_zeroed", "Argument[0]", "alloc-layout", "manual"] + - ["alloc::alloc::realloc", "Argument[2]", "alloc-size", "manual"] + - ["<_ as core::alloc::global::GlobalAlloc>::alloc", "Argument[0]", "alloc-layout", "manual"] + - ["::alloc", "Argument[0]", "alloc-layout", "manual"] + - ["<_ as core::alloc::global::GlobalAlloc>::alloc_zeroed", "Argument[0]", "alloc-layout", "manual"] + - ["::alloc_zeroed", "Argument[0]", "alloc-layout", "manual"] + - ["::allocate", "Argument[0]", "alloc-layout", "manual"] + - ["::allocate_zeroed", "Argument[0]", "alloc-layout", "manual"] + - ["::grow", "Argument[2]", "alloc-layout", "manual"] + - ["::grow_zeroed", "Argument[2]", "alloc-layout", "manual"] + - ["::alloc", "Argument[0]", "alloc-layout", "manual"] + - ["::alloc_zeroed", "Argument[0]", "alloc-layout", "manual"] + - ["::allocate", "Argument[0]", "alloc-layout", "manual"] + - ["::allocate_zeroed", "Argument[0]", "alloc-layout", "manual"] + - ["::grow", "Argument[2]", "alloc-layout", "manual"] + - ["::grow_zeroed", "Argument[2]", "alloc-layout", "manual"] - addsTo: pack: codeql/rust-all - extensible: summaryModelDeprecated + extensible: summaryModel data: # Box - - ["lang:alloc", "::pin", "Argument[0]", "ReturnValue.Reference", "value", "manual"] - - ["lang:alloc", "::new", "Argument[0]", "ReturnValue.Reference", "value", "manual"] - - ["lang:alloc", "::into_pin", "Argument[0]", "ReturnValue", "value", "manual"] + - ["::pin", "Argument[0]", "ReturnValue.Reference", "value", "manual"] + - ["::new", "Argument[0]", "ReturnValue.Reference", "value", "manual"] + - ["::into_pin", "Argument[0]", "ReturnValue", "value", "manual"] # Fmt - - ["lang:alloc", "crate::fmt::format", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["alloc::fmt::format", "Argument[0]", "ReturnValue", "taint", "manual"] # String - - ["lang:alloc", "::as_str", "Argument[self]", "ReturnValue", "value", "manual"] - - ["lang:alloc", "::as_bytes", "Argument[self]", "ReturnValue", "value", "manual"] - - ["lang:alloc", "<_ as crate::string::ToString>::to_string", "Argument[self]", "ReturnValue", "taint", "manual"] - - ["lang:alloc", "::parse", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["lang:alloc", "::trim", "Argument[self]", "ReturnValue.Reference", "taint", "manual"] - - ["lang:alloc", "::from", "Argument[0]", "ReturnValue", "value", "manual"] + - ["::as_str", "Argument[self]", "ReturnValue", "value", "manual"] + - ["::as_bytes", "Argument[self]", "ReturnValue", "value", "manual"] + - ["::as_str", "Argument[self]", "ReturnValue", "value", "manual"] + - ["::as_bytes", "Argument[self]", "ReturnValue", "value", "manual"] + - ["::to_string", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["::to_string", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["::parse", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::trim", "Argument[self]", "ReturnValue.Reference", "taint", "manual"] + - ["::from", "Argument[0]", "ReturnValue", "value", "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 00d78a7d8cb..44319a942bf 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 @@ -1,76 +1,79 @@ extensions: - addsTo: pack: codeql/rust-all - extensible: summaryModelDeprecated + extensible: summaryModel data: # Iterator - - ["lang:core", "<[_]>::iter", "Argument[self].Element", "ReturnValue.Element", "value", "manual"] - - ["lang:core", "<[_]>::iter_mut", "Argument[self].Element", "ReturnValue.Element", "value", "manual"] - - ["lang:core", "<[_]>::into_iter", "Argument[self].Element", "ReturnValue.Element", "value", "manual"] - - ["lang:core", "crate::iter::traits::iterator::Iterator::nth", "Argument[self].Element", "ReturnValue.Field[core::option::Option::Some(0)]", "value", "manual"] - - ["lang:core", "crate::iter::traits::iterator::Iterator::next", "Argument[self].Element", "ReturnValue.Field[core::option::Option::Some(0)]", "value", "manual"] - - ["lang:core", "crate::iter::traits::iterator::Iterator::collect", "Argument[self].Element", "ReturnValue.Element", "value", "manual"] - - ["lang:core", "crate::iter::traits::iterator::Iterator::map", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"] - - ["lang:core", "crate::iter::traits::iterator::Iterator::for_each", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"] - - ["lang:core", "::nth", "Argument[self].Element", "ReturnValue.Field[core::option::Option::Some(0)]", "value", "manual"] - - ["lang:core", "::next", "Argument[self].Element", "ReturnValue.Field[core::option::Option::Some(0)]", "value", "manual"] - - ["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"] + - ["::iter", "Argument[self].Element", "ReturnValue.Element", "value", "manual"] + - ["::iter", "Argument[self].Element", "ReturnValue.Element", "value", "manual"] + - ["::iter_mut", "Argument[self].Element", "ReturnValue.Element", "value", "manual"] + - ["::into_iter", "Argument[self].Element", "ReturnValue.Element", "value", "manual"] + - ["<_ as core::iter::traits::iterator::Iterator>::nth", "Argument[self].Element", "ReturnValue.Field[core::option::Option::Some(0)]", "value", "manual"] + - ["<_ as core::iter::traits::iterator::Iterator>::next", "Argument[self].Element", "ReturnValue.Field[core::option::Option::Some(0)]", "value", "manual"] + - ["<_ as core::iter::traits::iterator::Iterator>::collect", "Argument[self].Element", "ReturnValue.Element", "value", "manual"] + - ["<_ as core::iter::traits::iterator::Iterator>::map", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"] + - ["<_ as core::iter::traits::iterator::Iterator>::for_each", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"] + - ["::nth", "Argument[self].Element", "ReturnValue.Field[core::option::Option::Some(0)]", "value", "manual"] + - ["::next", "Argument[self].Element", "ReturnValue.Field[core::option::Option::Some(0)]", "value", "manual"] + - ["::collect", "Argument[self].Element", "ReturnValue.Element", "value", "manual"] + - ["::map", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"] + - ["<_ as core::iter::traits::iterator::Iterator>::for_each", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"] # Layout - - ["lang:core", "::from_size_align", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["lang:core", "::from_size_align_unchecked", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["lang:core", "::array", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["lang:core", "::repeat", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)].Field[0]", "taint", "manual"] - - ["lang:core", "::repeat", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)].Field[0]", "taint", "manual"] - - ["lang:core", "::repeat_packed", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["lang:core", "::repeat_packed", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["lang:core", "::extend", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)].Field[0]", "taint", "manual"] - - ["lang:core", "::extend", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)].Field[0]", "taint", "manual"] - - ["lang:core", "::extend_packed", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["lang:core", "::extend_packed", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["lang:core", "::align_to", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["lang:core", "::pad_to_align", "Argument[self]", "ReturnValue", "taint", "manual"] - - ["lang:core", "::size", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["::from_size_align", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::from_size_align_unchecked", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["::array", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::repeat", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)].Field[0]", "taint", "manual"] + - ["::repeat", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)].Field[0]", "taint", "manual"] + - ["::repeat_packed", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::repeat_packed", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::extend", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)].Field[0]", "taint", "manual"] + - ["::extend", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)].Field[0]", "taint", "manual"] + - ["::extend_packed", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::extend_packed", "Argument[0]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::align_to", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::pad_to_align", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["::size", "Argument[self]", "ReturnValue", "taint", "manual"] # Pin - - ["lang:core", "crate::pin::Pin", "Argument[0]", "ReturnValue", "value", "manual"] - - ["lang:core", "::new", "Argument[0]", "ReturnValue", "value", "manual"] - - ["lang:core", "::new_unchecked", "Argument[0].Reference", "ReturnValue", "value", "manual"] - - ["lang:core", "::into_inner", "Argument[0]", "ReturnValue", "value", "manual"] - - ["lang:core", "::into_inner_unchecked", "Argument[0]", "ReturnValue", "value", "manual"] - - ["lang:core", "::set", "Argument[0]", "Argument[self]", "value", "manual"] - - ["lang:core", "::into_inner", "Argument[0]", "ReturnValue", "value", "manual"] + - ["core::pin::Pin", "Argument[0]", "ReturnValue", "value", "manual"] + - ["::new", "Argument[0]", "ReturnValue", "value", "manual"] + - ["::new_unchecked", "Argument[0].Reference", "ReturnValue", "value", "manual"] + - ["::into_inner", "Argument[0]", "ReturnValue", "value", "manual"] + - ["::into_inner_unchecked", "Argument[0]", "ReturnValue", "value", "manual"] + - ["::set", "Argument[0]", "Argument[self]", "value", "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"] - - ["lang:core", "crate::ptr::write", "Argument[1]", "Argument[0].Reference", "value", "manual"] - - ["lang:core", "crate::ptr::write_unaligned", "Argument[1]", "Argument[0].Reference", "value", "manual"] - - ["lang:core", "crate::ptr::write_volatile", "Argument[1]", "Argument[0].Reference", "value", "manual"] + - ["core::ptr::read", "Argument[0].Reference", "ReturnValue", "value", "manual"] + - ["core::ptr::read_unaligned", "Argument[0].Reference", "ReturnValue", "value", "manual"] + - ["core::ptr::read_volatile", "Argument[0].Reference", "ReturnValue", "value", "manual"] + - ["core::ptr::write", "Argument[1]", "Argument[0].Reference", "value", "manual"] + - ["core::ptr::write_unaligned", "Argument[1]", "Argument[0].Reference", "value", "manual"] + - ["core::ptr::write_volatile", "Argument[1]", "Argument[0].Reference", "value", "manual"] # Str - - ["lang:core", "::as_str", "Argument[self]", "ReturnValue", "taint", "value"] - - ["lang:core", "::as_bytes", "Argument[self]", "ReturnValue", "taint", "value"] - - ["lang:core", "::to_string", "Argument[self]", "ReturnValue", "taint", "manual"] - - ["lang:core", "::parse", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["lang:core", "::trim", "Argument[self]", "ReturnValue.Reference", "taint", "manual"] + - ["::as_str", "Argument[self]", "ReturnValue", "taint", "value"] + - ["::as_str", "Argument[self]", "ReturnValue", "taint", "value"] + - ["::as_bytes", "Argument[self]", "ReturnValue", "taint", "value"] + - ["::as_bytes", "Argument[self]", "ReturnValue", "taint", "value"] + - ["::to_string", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["::parse", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::trim", "Argument[self]", "ReturnValue.Reference", "taint", "manual"] - addsTo: pack: codeql/rust-all - extensible: sourceModelDeprecated + extensible: sourceModel data: # 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"] + - ["core::ptr::drop_in_place", "Argument[0]", "pointer-invalidate", "manual"] + - ["core::ptr::dangling", "ReturnValue", "pointer-invalidate", "manual"] + - ["core::ptr::dangling_mut", "ReturnValue", "pointer-invalidate", "manual"] + - ["core::ptr::null", "ReturnValue", "pointer-invalidate", "manual"] + - ["v8::primitives::null", "ReturnValue", "pointer-invalidate", "manual"] - addsTo: pack: codeql/rust-all - extensible: sinkModelDeprecated + 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"] + - ["core::ptr::read", "Argument[0]", "pointer-access", "manual"] + - ["core::ptr::read_unaligned", "Argument[0]", "pointer-access", "manual"] + - ["core::ptr::read_volatile", "Argument[0]", "pointer-access", "manual"] + - ["core::ptr::write", "Argument[0]", "pointer-access", "manual"] + - ["core::ptr::write_bytes", "Argument[0]", "pointer-access", "manual"] + - ["core::ptr::write_unaligned", "Argument[0]", "pointer-access", "manual"] + - ["core::ptr::write_volatile", "Argument[0]", "pointer-access", "manual"] diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/net.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/net.model.yml index 307b20b5b88..bf158cbae2d 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/net.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/net.model.yml @@ -1,16 +1,16 @@ extensions: - addsTo: pack: codeql/rust-all - extensible: sourceModelDeprecated + extensible: sourceModel data: - - ["lang:std", "::connect", "ReturnValue.Field[core::result::Result::Ok(0)]", "remote", "manual"] - - ["lang:std", "::connect_timeout", "ReturnValue.Field[core::result::Result::Ok(0)]", "remote", "manual"] + - ["::connect", "ReturnValue.Field[core::result::Result::Ok(0)]", "remote", "manual"] + - ["::connect_timeout", "ReturnValue.Field[core::result::Result::Ok(0)]", "remote", "manual"] - addsTo: pack: codeql/rust-all - extensible: summaryModelDeprecated + extensible: summaryModel data: - - ["lang:std", "::try_clone", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["lang:std", "::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", "::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::try_clone", "Argument[self]", "ReturnValue.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"] From e56b9debf876fec8b755e0efc10b613faabeee08 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 1 Jul 2025 16:55:00 +0100 Subject: [PATCH 006/199] Rust: Fix mistake. --- rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml index b05ee510586..41f1348879f 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml @@ -15,7 +15,7 @@ extensions: - ["::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - ["::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - ["<_ as std::io::Read>::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["::read_to_string", "", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - ["::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - ["::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - ["<_ as std::io::Read>::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] From 7ef5586cc7e960326c523443ed54ebc3d6dede9c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 19 Jun 2025 19:39:38 +0100 Subject: [PATCH 007/199] Rust: Translate more legacy models -> new models (mostly guesswork for these last few cases). --- .../codeql/rust/frameworks/async-rs.model.yml | 4 +-- .../codeql/rust/frameworks/futures.model.yml | 30 +++++++++---------- .../lib/codeql/rust/frameworks/libc.model.yml | 14 ++++----- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/async-rs.model.yml b/rust/ql/lib/codeql/rust/frameworks/async-rs.model.yml index 8276574e73a..d90504d77c8 100644 --- a/rust/ql/lib/codeql/rust/frameworks/async-rs.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/async-rs.model.yml @@ -1,6 +1,6 @@ extensions: - addsTo: pack: codeql/rust-all - extensible: sourceModelDeprecated + extensible: sourceModel data: - - ["repo:https://github.com/async-rs/async-std:async-std", "::connect", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "remote", "manual"] + - ["::connect", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "remote", "manual"] diff --git a/rust/ql/lib/codeql/rust/frameworks/futures.model.yml b/rust/ql/lib/codeql/rust/frameworks/futures.model.yml index b1fa17f5876..cd9f476f8fb 100644 --- a/rust/ql/lib/codeql/rust/frameworks/futures.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/futures.model.yml @@ -1,19 +1,19 @@ extensions: - addsTo: pack: codeql/rust-all - extensible: summaryModelDeprecated + extensible: summaryModel data: - - ["repo:https://github.com/rust-lang/futures-rs:futures-executor", "crate::local_pool::block_on", "Argument[0]", "ReturnValue", "value", "manual"] - - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "::new", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncReadExt::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncReadExt::read", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"] - - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncReadExt::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncReadExt::read_to_end", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"] - - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncBufReadExt::read_line", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncBufReadExt::read_line", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"] - - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncBufReadExt::read_until", "Argument[self]", "Argument[1].Reference", "taint", "manual"] - - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncBufReadExt::read_until", "Argument[self].Reference", "Argument[1].Reference", "taint", "manual"] - - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncBufReadExt::fill_buf", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] - - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::io::AsyncBufReadExt::lines", "Argument[self]", "ReturnValue", "taint", "manual"] - - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "crate::stream::stream::StreamExt::next", "Argument[self]", "ReturnValue.Future.Field[core::option::Option::Some(0)]", "taint", "manual"] - - ["repo:https://github.com/rust-lang/futures-rs:futures-util", "::poll_fill_buf", "Argument[self].Reference", "ReturnValue.Field[core::task::poll::Poll::Ready(0)].Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["futures_executor::local_pool::block_on", "Argument[0]", "ReturnValue", "value", "manual"] + - ["::new", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["futures-util::io::AsyncReadExt::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["futures-util::io::AsyncReadExt::read", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"] + - ["futures-util::io::AsyncReadExt::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["futures-util::io::AsyncReadExt::read_to_end", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"] + - ["futures-util::io::AsyncBufReadExt::read_line", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["futures-util::io::AsyncBufReadExt::read_line", "Argument[self].Reference", "Argument[0].Reference", "taint", "manual"] + - ["futures-util::io::AsyncBufReadExt::read_until", "Argument[self]", "Argument[1].Reference", "taint", "manual"] + - ["futures-util::io::AsyncBufReadExt::read_until", "Argument[self].Reference", "Argument[1].Reference", "taint", "manual"] + - ["futures-util::io::AsyncBufReadExt::fill_buf", "Argument[self]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"] + - ["futures-util::io::AsyncBufReadExt::lines", "Argument[self]", "ReturnValue", "taint", "manual"] + - ["::next", "Argument[self]", "ReturnValue.Future.Field[core::option::Option::Some(0)]", "taint", "manual"] + - ["::poll_fill_buf", "Argument[self].Reference", "ReturnValue.Field[core::task::poll::Poll::Ready(0)].Field[core::result::Result::Ok(0)]", "taint", "manual"] diff --git a/rust/ql/lib/codeql/rust/frameworks/libc.model.yml b/rust/ql/lib/codeql/rust/frameworks/libc.model.yml index ce44a71732e..efce0df7ffb 100644 --- a/rust/ql/lib/codeql/rust/frameworks/libc.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/libc.model.yml @@ -1,14 +1,14 @@ extensions: - addsTo: pack: codeql/rust-all - extensible: sourceModelDeprecated + extensible: sourceModel data: - - ["repo:https://github.com/rust-lang/libc:libc", "::free", "Argument[0]", "pointer-invalidate", "manual"] + - ["libc::free", "Argument[0]", "pointer-invalidate", "manual"] - addsTo: pack: codeql/rust-all - extensible: sinkModelDeprecated + 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"] + - ["libc::malloc", "Argument[0]", "alloc-size", "manual"] + - ["libc::aligned_alloc", "Argument[1]", "alloc-size", "manual"] + - ["libc::calloc", "Argument[0,1]", "alloc-size", "manual"] + - ["libc::realloc", "Argument[1]", "alloc-size", "manual"] From 3e11dbded0f2e5f983ee2340d3af0d57ed7b7fe3 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 1 Jul 2025 17:31:15 +0100 Subject: [PATCH 008/199] Rust: Accept test changes. --- .../library-tests/dataflow/sources/test.rs | 2 +- .../library-tests/frameworks/postgres/main.rs | 10 +-- .../CWE-328/WeakSensitiveDataHashing.expected | 66 +------------------ .../test/query-tests/security/CWE-328/test.rs | 26 ++++---- 4 files changed, 22 insertions(+), 82 deletions(-) diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index 845050c2fc9..a3dc78f9c52 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -214,7 +214,7 @@ fn test_io_stdin() -> std::io::Result<()> { { let mut buffer = Vec::::new(); let _bytes = std::io::stdin().read_to_end(&mut buffer)?; // $ Alert[rust/summary/taint-sources] - sink(&buffer); // $ MISSING: hasTaintFlow + sink(&buffer); // $ hasTaintFlow } { diff --git a/rust/ql/test/library-tests/frameworks/postgres/main.rs b/rust/ql/test/library-tests/frameworks/postgres/main.rs index 8a04f8d00e8..1ca39fb9427 100644 --- a/rust/ql/test/library-tests/frameworks/postgres/main.rs +++ b/rust/ql/test/library-tests/frameworks/postgres/main.rs @@ -16,7 +16,7 @@ fn main() -> Result<(), Box> { )", &[], )?; - + let query = format!("INSERT INTO person (name, age) VALUES ('{}', '{}')", name, age); conn.execute(query.as_str(), &[])?; // $ sql-sink @@ -33,11 +33,11 @@ fn main() -> Result<(), Box> { // conn.query_typed_raw(query.as_str(), &[])?; for row in &conn.query("SELECT id, name, age FROM person", &[])? { // $ sql-sink - let id: i32 = row.get("id"); // $ database-read - let name: &str = row.try_get("name")?; // $ database-read - let age: i32 = row.try_get("age").unwrap(); // $ database-read + let id: i32 = row.get("id"); // $ MISSING: database-read + let name: &str = row.try_get("name")?; // $ MISSING: database-read + let age: i32 = row.try_get("age").unwrap(); // $ MISSING: database-read println!("found person: {} {} {}", id, name, age); } Ok(()) -} \ No newline at end of file +} diff --git a/rust/ql/test/query-tests/security/CWE-328/WeakSensitiveDataHashing.expected b/rust/ql/test/query-tests/security/CWE-328/WeakSensitiveDataHashing.expected index 062e3a63cc3..2d4e7cd6e72 100644 --- a/rust/ql/test/query-tests/security/CWE-328/WeakSensitiveDataHashing.expected +++ b/rust/ql/test/query-tests/security/CWE-328/WeakSensitiveDataHashing.expected @@ -1,74 +1,14 @@ #select -| test.rs:14:9:14:24 | ...::digest | test.rs:14:26:14:39 | credit_card_no | test.rs:14:9:14:24 | ...::digest | $@ is used in a hashing algorithm (MD5) that is insecure. | test.rs:14:26:14:39 | credit_card_no | Sensitive data (private) | -| test.rs:15:9:15:24 | ...::digest | test.rs:15:26:15:33 | password | test.rs:15:9:15:24 | ...::digest | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:15:26:15:33 | password | Sensitive data (password) | | test.rs:20:9:20:24 | ...::compute | test.rs:20:26:20:39 | credit_card_no | test.rs:20:9:20:24 | ...::compute | $@ is used in a hashing algorithm (MD5) that is insecure. | test.rs:20:26:20:39 | credit_card_no | Sensitive data (private) | | test.rs:21:9:21:24 | ...::compute | test.rs:21:26:21:33 | password | test.rs:21:9:21:24 | ...::compute | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:21:26:21:33 | password | Sensitive data (password) | -| test.rs:26:9:26:26 | ...::digest | test.rs:26:28:26:41 | credit_card_no | test.rs:26:9:26:26 | ...::digest | $@ is used in a hashing algorithm (SHA1) that is insecure. | test.rs:26:28:26:41 | credit_card_no | Sensitive data (private) | -| test.rs:27:9:27:26 | ...::digest | test.rs:27:28:27:35 | password | test.rs:27:9:27:26 | ...::digest | $@ is used in a hashing algorithm (SHA1) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:27:28:27:35 | password | Sensitive data (password) | -| test.rs:32:9:32:34 | ...::digest | test.rs:32:36:32:49 | credit_card_no | test.rs:32:9:32:34 | ...::digest | $@ is used in a hashing algorithm (SHA1) that is insecure. | test.rs:32:36:32:49 | credit_card_no | Sensitive data (private) | -| test.rs:33:9:33:34 | ...::digest | test.rs:33:36:33:43 | password | test.rs:33:9:33:34 | ...::digest | $@ is used in a hashing algorithm (SHA1) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:33:36:33:43 | password | Sensitive data (password) | -| test.rs:39:9:39:30 | ...::digest | test.rs:39:32:39:39 | password | test.rs:39:9:39:30 | ...::digest | $@ is used in a hashing algorithm (SHA3256) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:39:32:39:39 | password | Sensitive data (password) | -| test.rs:60:9:60:24 | ...::digest | test.rs:60:26:60:37 | password_str | test.rs:60:9:60:24 | ...::digest | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:60:26:60:37 | password_str | Sensitive data (password) | -| test.rs:62:9:62:24 | ...::digest | test.rs:62:26:62:37 | password_arr | test.rs:62:9:62:24 | ...::digest | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:62:26:62:37 | password_arr | Sensitive data (password) | -| test.rs:64:9:64:24 | ...::digest | test.rs:64:26:64:37 | password_vec | test.rs:64:9:64:24 | ...::digest | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:64:26:64:37 | password_vec | Sensitive data (password) | -| test.rs:77:9:77:33 | ...::new_with_prefix | test.rs:77:35:77:42 | password | test.rs:77:9:77:33 | ...::new_with_prefix | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:77:35:77:42 | password | Sensitive data (password) | -| test.rs:81:9:81:24 | ...::digest | test.rs:81:26:81:33 | password | test.rs:81:9:81:24 | ...::digest | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:81:26:81:33 | password | Sensitive data (password) | -| test.rs:83:9:83:24 | ...::digest | test.rs:83:26:83:33 | password | test.rs:83:9:83:24 | ...::digest | $@ is used in a hashing algorithm (MD5) that is insecure for password hashing, since it is not a computationally expensive hash function. | test.rs:83:26:83:33 | password | Sensitive data (password) | edges -| test.rs:14:26:14:39 | credit_card_no | test.rs:14:9:14:24 | ...::digest | provenance | MaD:1 Sink:MaD:1 | -| test.rs:15:26:15:33 | password | test.rs:15:9:15:24 | ...::digest | provenance | MaD:1 Sink:MaD:1 | -| test.rs:20:26:20:39 | credit_card_no | test.rs:20:9:20:24 | ...::compute | provenance | MaD:3 Sink:MaD:3 | -| test.rs:21:26:21:33 | password | test.rs:21:9:21:24 | ...::compute | provenance | MaD:3 Sink:MaD:3 | -| test.rs:26:28:26:41 | credit_card_no | test.rs:26:9:26:26 | ...::digest | provenance | MaD:1 Sink:MaD:1 | -| test.rs:27:28:27:35 | password | test.rs:27:9:27:26 | ...::digest | provenance | MaD:1 Sink:MaD:1 | -| test.rs:32:36:32:49 | credit_card_no | test.rs:32:9:32:34 | ...::digest | provenance | MaD:1 Sink:MaD:1 | -| test.rs:33:36:33:43 | password | test.rs:33:9:33:34 | ...::digest | provenance | MaD:1 Sink:MaD:1 | -| test.rs:39:32:39:39 | password | test.rs:39:9:39:30 | ...::digest | provenance | MaD:1 Sink:MaD:1 | -| test.rs:60:26:60:37 | password_str | test.rs:60:9:60:24 | ...::digest | provenance | MaD:1 Sink:MaD:1 | -| test.rs:62:26:62:37 | password_arr | test.rs:62:9:62:24 | ...::digest | provenance | MaD:1 Sink:MaD:1 | -| test.rs:64:26:64:37 | password_vec | test.rs:64:9:64:24 | ...::digest | provenance | MaD:1 Sink:MaD:1 | -| test.rs:77:35:77:42 | password | test.rs:77:9:77:33 | ...::new_with_prefix | provenance | MaD:2 Sink:MaD:2 | -| test.rs:81:26:81:33 | password | test.rs:81:26:81:40 | password.trim() [&ref] | provenance | MaD:5 | -| test.rs:81:26:81:40 | password.trim() [&ref] | test.rs:81:9:81:24 | ...::digest | provenance | MaD:1 Sink:MaD:1 | -| test.rs:83:26:83:33 | password | test.rs:83:26:83:44 | password.as_bytes() | provenance | MaD:4 | -| test.rs:83:26:83:44 | password.as_bytes() | test.rs:83:9:83:24 | ...::digest | provenance | MaD:1 Sink:MaD:1 | +| test.rs:20:26:20:39 | credit_card_no | test.rs:20:9:20:24 | ...::compute | provenance | MaD:1 Sink:MaD:1 | +| test.rs:21:26:21:33 | password | test.rs:21:9:21:24 | ...::compute | provenance | MaD:1 Sink:MaD:1 | models -| 1 | Sink: repo:https://github.com/RustCrypto/traits:digest; <_ as crate::digest::Digest>::digest; Argument[0]; hasher-input | -| 2 | Sink: repo:https://github.com/RustCrypto/traits:digest; <_ as crate::digest::Digest>::new_with_prefix; Argument[0]; hasher-input | -| 3 | Sink: repo:https://github.com/stainless-steel/md5:md5; crate::compute; Argument[0]; hasher-input | -| 4 | Summary: lang:core; ::as_bytes; Argument[self]; ReturnValue; taint | -| 5 | Summary: lang:core; ::trim; Argument[self]; ReturnValue.Reference; taint | +| 1 | Sink: md5::compute; Argument[0]; hasher-input | nodes -| test.rs:14:9:14:24 | ...::digest | semmle.label | ...::digest | -| test.rs:14:26:14:39 | credit_card_no | semmle.label | credit_card_no | -| test.rs:15:9:15:24 | ...::digest | semmle.label | ...::digest | -| test.rs:15:26:15:33 | password | semmle.label | password | | test.rs:20:9:20:24 | ...::compute | semmle.label | ...::compute | | test.rs:20:26:20:39 | credit_card_no | semmle.label | credit_card_no | | test.rs:21:9:21:24 | ...::compute | semmle.label | ...::compute | | test.rs:21:26:21:33 | password | semmle.label | password | -| test.rs:26:9:26:26 | ...::digest | semmle.label | ...::digest | -| test.rs:26:28:26:41 | credit_card_no | semmle.label | credit_card_no | -| test.rs:27:9:27:26 | ...::digest | semmle.label | ...::digest | -| test.rs:27:28:27:35 | password | semmle.label | password | -| test.rs:32:9:32:34 | ...::digest | semmle.label | ...::digest | -| test.rs:32:36:32:49 | credit_card_no | semmle.label | credit_card_no | -| test.rs:33:9:33:34 | ...::digest | semmle.label | ...::digest | -| test.rs:33:36:33:43 | password | semmle.label | password | -| test.rs:39:9:39:30 | ...::digest | semmle.label | ...::digest | -| test.rs:39:32:39:39 | password | semmle.label | password | -| test.rs:60:9:60:24 | ...::digest | semmle.label | ...::digest | -| test.rs:60:26:60:37 | password_str | semmle.label | password_str | -| test.rs:62:9:62:24 | ...::digest | semmle.label | ...::digest | -| test.rs:62:26:62:37 | password_arr | semmle.label | password_arr | -| test.rs:64:9:64:24 | ...::digest | semmle.label | ...::digest | -| test.rs:64:26:64:37 | password_vec | semmle.label | password_vec | -| test.rs:77:9:77:33 | ...::new_with_prefix | semmle.label | ...::new_with_prefix | -| test.rs:77:35:77:42 | password | semmle.label | password | -| test.rs:81:9:81:24 | ...::digest | semmle.label | ...::digest | -| test.rs:81:26:81:33 | password | semmle.label | password | -| test.rs:81:26:81:40 | password.trim() [&ref] | semmle.label | password.trim() [&ref] | -| test.rs:83:9:83:24 | ...::digest | semmle.label | ...::digest | -| test.rs:83:26:83:33 | password | semmle.label | password | -| test.rs:83:26:83:44 | password.as_bytes() | semmle.label | password.as_bytes() | subpaths diff --git a/rust/ql/test/query-tests/security/CWE-328/test.rs b/rust/ql/test/query-tests/security/CWE-328/test.rs index 56b6fe7821d..a7e17404df1 100644 --- a/rust/ql/test/query-tests/security/CWE-328/test.rs +++ b/rust/ql/test/query-tests/security/CWE-328/test.rs @@ -11,8 +11,8 @@ fn test_hash_algorithms( // MD5 _ = md5::Md5::digest(harmless); - _ = md5::Md5::digest(credit_card_no); // $ Alert[rust/weak-sensitive-data-hashing] - _ = md5::Md5::digest(password); // $ Alert[rust/weak-sensitive-data-hashing] + _ = md5::Md5::digest(credit_card_no); // $ MISSING: Alert[rust/weak-sensitive-data-hashing] + _ = md5::Md5::digest(password); // $ MISSING: Alert[rust/weak-sensitive-data-hashing] _ = md5::Md5::digest(encrypted_password); // MD5 (alternative / older library) @@ -23,20 +23,20 @@ fn test_hash_algorithms( // SHA-1 _ = sha1::Sha1::digest(harmless); - _ = sha1::Sha1::digest(credit_card_no); // $ Alert[rust/weak-sensitive-data-hashing] - _ = sha1::Sha1::digest(password); // $ Alert[rust/weak-sensitive-data-hashing] + _ = sha1::Sha1::digest(credit_card_no); // $ MISSING: Alert[rust/weak-sensitive-data-hashing] + _ = sha1::Sha1::digest(password); // $ MISSING: Alert[rust/weak-sensitive-data-hashing] _ = sha1::Sha1::digest(encrypted_password); // SHA-1 checked _ = sha1_checked::Sha1::digest(harmless); - _ = sha1_checked::Sha1::digest(credit_card_no); // $ Alert[rust/weak-sensitive-data-hashing] - _ = sha1_checked::Sha1::digest(password); // $ Alert[rust/weak-sensitive-data-hashing] + _ = sha1_checked::Sha1::digest(credit_card_no); // $ MISSING: Alert[rust/weak-sensitive-data-hashing] + _ = sha1_checked::Sha1::digest(password); // $ MISSING: Alert[rust/weak-sensitive-data-hashing] _ = sha1_checked::Sha1::digest(encrypted_password); // SHA-256 (appropriate for sensitive data hashing) _ = sha3::Sha3_256::digest(harmless); _ = sha3::Sha3_256::digest(credit_card_no); - _ = sha3::Sha3_256::digest(password); // $ Alert[rust/weak-sensitive-data-hashing] + _ = sha3::Sha3_256::digest(password); // $ MISSING: Alert[rust/weak-sensitive-data-hashing] _ = sha3::Sha3_256::digest(encrypted_password); // Argon2 (appropriate for password hashing) @@ -57,11 +57,11 @@ fn test_hash_code_patterns( // hash different types of data _ = md5::Md5::digest(harmless_str); - _ = md5::Md5::digest(password_str); // $ Alert[rust/weak-sensitive-data-hashing] + _ = md5::Md5::digest(password_str); // $ MISSING: Alert[rust/weak-sensitive-data-hashing] _ = md5::Md5::digest(harmless_arr); - _ = md5::Md5::digest(password_arr); // $ Alert[rust/weak-sensitive-data-hashing] + _ = md5::Md5::digest(password_arr); // $ MISSING: Alert[rust/weak-sensitive-data-hashing] _ = md5::Md5::digest(harmless_vec); - _ = md5::Md5::digest(password_vec); // $ Alert[rust/weak-sensitive-data-hashing] + _ = md5::Md5::digest(password_vec); // $ MISSING: Alert[rust/weak-sensitive-data-hashing] // hash through a hasher object let mut md5_hasher = md5::Md5::new(); @@ -74,13 +74,13 @@ fn test_hash_code_patterns( _ = md5::Md5::new().chain_update(harmless).chain_update(password).chain_update(harmless).finalize(); // $ MISSING: Alert[rust/weak-sensitive-data-hashing] _ = md5::Md5::new_with_prefix(harmless).finalize(); - _ = md5::Md5::new_with_prefix(password).finalize(); // $ Alert[rust/weak-sensitive-data-hashing] + _ = md5::Md5::new_with_prefix(password).finalize(); // $ MISSING: Alert[rust/weak-sensitive-data-hashing] // hash transformed data _ = md5::Md5::digest(harmless.trim()); - _ = md5::Md5::digest(password.trim()); // $ Alert[rust/weak-sensitive-data-hashing] + _ = md5::Md5::digest(password.trim()); // $ MISSING: Alert[rust/weak-sensitive-data-hashing] _ = md5::Md5::digest(harmless.as_bytes()); - _ = md5::Md5::digest(password.as_bytes()); // $ Alert[rust/weak-sensitive-data-hashing] + _ = md5::Md5::digest(password.as_bytes()); // $ MISSING: Alert[rust/weak-sensitive-data-hashing] _ = md5::Md5::digest(std::str::from_utf8(harmless_arr).unwrap()); _ = md5::Md5::digest(std::str::from_utf8(password_arr).unwrap()); // $ MISSING: Alert[rust/weak-sensitive-data-hashing] } From d1b4172486960613b91421183d5f7e32d9ae76c2 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 1 Jul 2025 14:08:48 +0200 Subject: [PATCH 009/199] Shared: Factor out some helper predicates in alert filtering --- shared/util/codeql/util/AlertFiltering.qll | 23 ++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/shared/util/codeql/util/AlertFiltering.qll b/shared/util/codeql/util/AlertFiltering.qll index 1bc366c0416..f264c20aeda 100644 --- a/shared/util/codeql/util/AlertFiltering.qll +++ b/shared/util/codeql/util/AlertFiltering.qll @@ -75,19 +75,30 @@ extensible predicate restrictAlertsToExactLocation( /** Module for applying alert location filtering. */ module AlertFilteringImpl { + pragma[nomagic] + private predicate restrictAlertsToEntireFile(string filePath) { restrictAlertsTo(filePath, 0, 0) } + + pragma[nomagic] + private predicate restrictAlertsToStartLine(string filePath, int line) { + exists(int startLineStart, int startLineEnd | + restrictAlertsTo(filePath, startLineStart, startLineEnd) and + line = [startLineStart .. startLineEnd] + ) + } + /** Applies alert filtering to the given location. */ bindingset[location] predicate filterByLocation(Location location) { not restrictAlertsTo(_, _, _) and not restrictAlertsToExactLocation(_, _, _, _, _) or - exists(string filePath, int startLineStart, int startLineEnd | - restrictAlertsTo(filePath, startLineStart, startLineEnd) - | - startLineStart = 0 and - startLineEnd = 0 and + exists(string filePath | + restrictAlertsToEntireFile(filePath) and location.hasLocationInfo(filePath, _, _, _, _) or - location.hasLocationInfo(filePath, [startLineStart .. startLineEnd], _, _, _) + exists(int line | + restrictAlertsToStartLine(filePath, line) and + location.hasLocationInfo(filePath, line, _, _, _) + ) ) or exists(string filePath, int startLine, int startColumn, int endLine, int endColumn | From 8b345518f4f2dc3cdcdcb9a9339a0b3ea2175536 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 1 Jul 2025 14:54:41 +0200 Subject: [PATCH 010/199] Shared: Add approximate version of getASelected{Source,Sink}Location --- shared/dataflow/codeql/dataflow/DataFlow.qll | 36 +++++++++++++++++++ .../codeql/dataflow/internal/DataFlowImpl.qll | 4 +++ .../dataflow/internal/DataFlowImplStage1.qll | 8 +++-- shared/util/codeql/util/AlertFiltering.qll | 36 +++++++++++++++++++ 4 files changed, 82 insertions(+), 2 deletions(-) diff --git a/shared/dataflow/codeql/dataflow/DataFlow.qll b/shared/dataflow/codeql/dataflow/DataFlow.qll index 3483287e3b3..93803af552b 100644 --- a/shared/dataflow/codeql/dataflow/DataFlow.qll +++ b/shared/dataflow/codeql/dataflow/DataFlow.qll @@ -459,6 +459,15 @@ module Configs Lang> { */ default Location getASelectedSourceLocation(Node source) { result = source.getLocation() } + /** + * Like `getASelectedSourceLocation`, but only has to get a location _containing_ the + * actual location associated with `source`. + * + * This prunes fewer sources than `getASelectedSourceLocation` but leaves room for the possibility + * that a more precise location can be selected in the query. + */ + default Location getASelectedSourceLocationApprox(Node source) { none() } + /** * Gets a location that will be associated with the given `sink` in a * diff-informed query that uses this configuration (see @@ -469,6 +478,15 @@ module Configs Lang> { * report the sink at all, this predicate can be `none()`. */ default Location getASelectedSinkLocation(Node sink) { result = sink.getLocation() } + + /** + * Like `getASelectedSinkLocation`, but only has to get a location _containing_ the + * actual location associated with `sink`. + * + * This prunes fewer sinks than `getASelectedSinkLocation` but leaves room for the possibility + * that a more precise location can be selected in the query. + */ + default Location getASelectedSinkLocationApprox(Node sink) { none() } } /** An input configuration for data flow using flow state. */ @@ -608,6 +626,15 @@ module Configs Lang> { */ default Location getASelectedSourceLocation(Node source) { result = source.getLocation() } + /** + * Like `getASelectedSourceLocation`, but only has to get a location _containing_ the + * actual location associated with `source`. + * + * This prunes fewer sources than `getASelectedSourceLocation` but leaves room for the possibility + * that a more precise location can be selected in the query. + */ + default Location getASelectedSourceLocationApprox(Node source) { none() } + /** * Gets a location that will be associated with the given `sink` in a * diff-informed query that uses this configuration (see @@ -618,6 +645,15 @@ module Configs Lang> { * report the sink at all, this predicate can be `none()`. */ default Location getASelectedSinkLocation(Node sink) { result = sink.getLocation() } + + /** + * Like `getASelectedSinkLocation`, but only has to get a location _containing_ the + * actual location associated with `sink`. + * + * This prunes fewer sinks than `getASelectedSinkLocation` but leaves room for the possibility + * that a more precise location can be selected in the query. + */ + default Location getASelectedSinkLocationApprox(Node sink) { none() } } } diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index a7e0736432a..b90512bdb23 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -145,7 +145,11 @@ module MakeImpl Lang> { Location getASelectedSourceLocation(Node source); + Location getASelectedSourceLocationApprox(Node source); + Location getASelectedSinkLocation(Node sink); + + Location getASelectedSinkLocationApprox(Node sink); } /** diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll index c7883df0de1..5e85cab00d9 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll @@ -133,7 +133,9 @@ module MakeImplStage1 Lang> { private predicate isFilteredSource(Node source) { Config::isSource(source, _) and if Config::observeDiffInformedIncrementalMode() - then AlertFiltering::filterByLocation(Config::getASelectedSourceLocation(source)) + then + AlertFiltering::filterByLocation(Config::getASelectedSourceLocation(source)) or + AlertFiltering::filterByLocationApprox(Config::getASelectedSourceLocationApprox(source)) else any() } @@ -144,7 +146,9 @@ module MakeImplStage1 Lang> { Config::isSink(sink) ) and if Config::observeDiffInformedIncrementalMode() - then AlertFiltering::filterByLocation(Config::getASelectedSinkLocation(sink)) + then + AlertFiltering::filterByLocation(Config::getASelectedSinkLocation(sink)) or + AlertFiltering::filterByLocationApprox(Config::getASelectedSinkLocationApprox(sink)) else any() } diff --git a/shared/util/codeql/util/AlertFiltering.qll b/shared/util/codeql/util/AlertFiltering.qll index f264c20aeda..97e6198a16c 100644 --- a/shared/util/codeql/util/AlertFiltering.qll +++ b/shared/util/codeql/util/AlertFiltering.qll @@ -107,4 +107,40 @@ module AlertFilteringImpl { location.hasLocationInfo(filePath, startLine, startColumn, endLine, endColumn) ) } + + /** + * Holds if some subrange within `location` would be accepted by alert filtering. + * + * There does not need to exist a `Location` corresponding to that subrange. + */ + bindingset[location] + predicate filterByLocationApprox(Location location) { + not restrictAlertsTo(_, _, _) and not restrictAlertsToExactLocation(_, _, _, _, _) + or + exists(string filePath | + restrictAlertsToEntireFile(filePath) and + location.hasLocationInfo(filePath, _, _, _, _) + or + exists(int locStartLine, int locEndLine | + location.hasLocationInfo(filePath, locStartLine, _, locEndLine, _) + | + restrictAlertsToStartLine(filePath, [locStartLine .. locEndLine]) + ) + ) + or + // Check if an exact filter-location is fully contained in `location`. + // This is slow but only used for testing. + exists( + string filePath, int startLine, int startColumn, int endLine, int endColumn, + int filterStartLine, int filterStartColumn, int filterEndLine, int filterEndColumn + | + location.hasLocationInfo(filePath, startLine, startColumn, endLine, endColumn) and + restrictAlertsToExactLocation(filePath, filterStartLine, filterStartColumn, filterEndLine, + filterEndColumn) and + startLine <= filterStartLine and + (startLine != filterStartLine or startColumn <= filterStartColumn) and + endLine >= filterEndLine and + (endLine != filterEndLine or endColumn >= filterEndColumn) + ) + } } From d65da1f8a1bc92966c5ac1e6a67cc9a2d4f59233 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 1 Jul 2025 15:52:37 +0200 Subject: [PATCH 011/199] Ruby: enable for PolyReDos but document why it still doesnt work --- .../ruby/security/regexp/PolynomialReDoSQuery.qll | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSQuery.qll b/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSQuery.qll index 98a42fcf5e7..0d955d1eb24 100644 --- a/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSQuery.qll +++ b/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSQuery.qll @@ -18,6 +18,18 @@ private module PolynomialReDoSConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { sink instanceof Sink } predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } + + // Diff-informedness is disabled because of RegExpTerms having incorrect locations when + // the regexp is parsed from a string arising from constant folding. + predicate observeDiffInformedIncrementalMode() { none() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + result = sink.(Sink).getHighlight().getLocation() + } + + Location getASelectedSinkLocationApprox(DataFlow::Node sink) { + result = sink.(Sink).getRegExp().getRootTerm().getLocation() + } } /** From a46b5f9529e7cffb7cd1ceacdbbc766c7630362c Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 1 Jul 2025 16:05:22 +0200 Subject: [PATCH 012/199] Python: enable diff-informedness for poly redos using approximate related locations --- .../security/dataflow/PolynomialReDoSQuery.qll | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSQuery.qll b/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSQuery.qll index 0e52764c195..a6602b30b16 100644 --- a/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSQuery.qll +++ b/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSQuery.qll @@ -18,21 +18,13 @@ private module PolynomialReDoSConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } - // Diff-informed incremental mode is currently disabled for this query due to - // API limitations. The query exposes sink.getABacktrackingTerm() as an alert - // location, but there is no way to express that information through - // getASelectedSinkLocation() because there is no @location in the CodeQL - // database that corresponds to a term inside a regular expression. As a - // result, this query could miss alerts in diff-informed incremental mode. - // - // To address this problem, we need to have a version of - // getASelectedSinkLocation() that uses hasLocationInfo() instead of - // returning Location objects. - predicate observeDiffInformedIncrementalMode() { none() } + predicate observeDiffInformedIncrementalMode() { any() } Location getASelectedSinkLocation(DataFlow::Node sink) { result = sink.(Sink).getHighlight().getLocation() - or + } + + Location getASelectedSinkLocationApprox(DataFlow::Node sink) { result = sink.(Sink).getABacktrackingTerm().getLocation() } } From 82d190f4bf298423b26bf9f2729e534d275638f4 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 1 Jul 2025 16:17:24 +0200 Subject: [PATCH 013/199] Java: use approximate related sink locations in polynomial redos --- .../security/regexp/PolynomialReDoSQuery.qll | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll b/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll index ba65e13dd61..f5d0190068b 100644 --- a/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll +++ b/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll @@ -47,6 +47,24 @@ module PolynomialRedosConfig implements DataFlow::ConfigSig { node instanceof SimpleTypeSanitizer or node.asExpr().(MethodCall).getMethod() instanceof LengthRestrictedMethod } + + predicate observeDiffInformedIncrementalMode() { any() } + + Location getASelectedSinkLocation(DataFlow::Node sink) { + exists(SuperlinearBackTracking::PolynomialBackTrackingTerm regexp | + regexp.getRootTerm() = sink.(PolynomialRedosSink).getRegExp() + | + result = sink.getLocation() + ) + } + + Location getASelectedSinkLocationApprox(DataFlow::Node sink) { + exists(SuperlinearBackTracking::PolynomialBackTrackingTerm regexp | + regexp.getRootTerm() = sink.(PolynomialRedosSink).getRegExp() + | + result = regexp.getLocation() + ) + } } module PolynomialRedosFlow = TaintTracking::Global; From 4a2d7950760f783441057970f2b1f62b6c029336 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 2 Jul 2025 14:38:10 +0200 Subject: [PATCH 014/199] Shared: Make approximate location filtering the default behaviour --- .../security/regexp/PolynomialReDoSQuery.qll | 8 +---- .../dataflow/PolynomialReDoSQuery.qll | 4 +-- .../security/regexp/PolynomialReDoSQuery.qll | 4 +-- shared/dataflow/codeql/dataflow/DataFlow.qll | 36 ------------------- .../codeql/dataflow/internal/DataFlowImpl.qll | 4 --- .../dataflow/internal/DataFlowImplStage1.qll | 8 ++--- shared/util/codeql/util/AlertFiltering.qll | 26 -------------- 7 files changed, 5 insertions(+), 85 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll b/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll index f5d0190068b..767ebc97437 100644 --- a/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll +++ b/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll @@ -55,13 +55,7 @@ module PolynomialRedosConfig implements DataFlow::ConfigSig { regexp.getRootTerm() = sink.(PolynomialRedosSink).getRegExp() | result = sink.getLocation() - ) - } - - Location getASelectedSinkLocationApprox(DataFlow::Node sink) { - exists(SuperlinearBackTracking::PolynomialBackTrackingTerm regexp | - regexp.getRootTerm() = sink.(PolynomialRedosSink).getRegExp() - | + or result = regexp.getLocation() ) } diff --git a/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSQuery.qll b/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSQuery.qll index a6602b30b16..89aa4961e6e 100644 --- a/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSQuery.qll +++ b/python/ql/lib/semmle/python/security/dataflow/PolynomialReDoSQuery.qll @@ -22,9 +22,7 @@ private module PolynomialReDoSConfig implements DataFlow::ConfigSig { Location getASelectedSinkLocation(DataFlow::Node sink) { result = sink.(Sink).getHighlight().getLocation() - } - - Location getASelectedSinkLocationApprox(DataFlow::Node sink) { + or result = sink.(Sink).getABacktrackingTerm().getLocation() } } diff --git a/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSQuery.qll b/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSQuery.qll index 0d955d1eb24..81179717e01 100644 --- a/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSQuery.qll +++ b/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSQuery.qll @@ -25,9 +25,7 @@ private module PolynomialReDoSConfig implements DataFlow::ConfigSig { Location getASelectedSinkLocation(DataFlow::Node sink) { result = sink.(Sink).getHighlight().getLocation() - } - - Location getASelectedSinkLocationApprox(DataFlow::Node sink) { + or result = sink.(Sink).getRegExp().getRootTerm().getLocation() } } diff --git a/shared/dataflow/codeql/dataflow/DataFlow.qll b/shared/dataflow/codeql/dataflow/DataFlow.qll index 93803af552b..3483287e3b3 100644 --- a/shared/dataflow/codeql/dataflow/DataFlow.qll +++ b/shared/dataflow/codeql/dataflow/DataFlow.qll @@ -459,15 +459,6 @@ module Configs Lang> { */ default Location getASelectedSourceLocation(Node source) { result = source.getLocation() } - /** - * Like `getASelectedSourceLocation`, but only has to get a location _containing_ the - * actual location associated with `source`. - * - * This prunes fewer sources than `getASelectedSourceLocation` but leaves room for the possibility - * that a more precise location can be selected in the query. - */ - default Location getASelectedSourceLocationApprox(Node source) { none() } - /** * Gets a location that will be associated with the given `sink` in a * diff-informed query that uses this configuration (see @@ -478,15 +469,6 @@ module Configs Lang> { * report the sink at all, this predicate can be `none()`. */ default Location getASelectedSinkLocation(Node sink) { result = sink.getLocation() } - - /** - * Like `getASelectedSinkLocation`, but only has to get a location _containing_ the - * actual location associated with `sink`. - * - * This prunes fewer sinks than `getASelectedSinkLocation` but leaves room for the possibility - * that a more precise location can be selected in the query. - */ - default Location getASelectedSinkLocationApprox(Node sink) { none() } } /** An input configuration for data flow using flow state. */ @@ -626,15 +608,6 @@ module Configs Lang> { */ default Location getASelectedSourceLocation(Node source) { result = source.getLocation() } - /** - * Like `getASelectedSourceLocation`, but only has to get a location _containing_ the - * actual location associated with `source`. - * - * This prunes fewer sources than `getASelectedSourceLocation` but leaves room for the possibility - * that a more precise location can be selected in the query. - */ - default Location getASelectedSourceLocationApprox(Node source) { none() } - /** * Gets a location that will be associated with the given `sink` in a * diff-informed query that uses this configuration (see @@ -645,15 +618,6 @@ module Configs Lang> { * report the sink at all, this predicate can be `none()`. */ default Location getASelectedSinkLocation(Node sink) { result = sink.getLocation() } - - /** - * Like `getASelectedSinkLocation`, but only has to get a location _containing_ the - * actual location associated with `sink`. - * - * This prunes fewer sinks than `getASelectedSinkLocation` but leaves room for the possibility - * that a more precise location can be selected in the query. - */ - default Location getASelectedSinkLocationApprox(Node sink) { none() } } } diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll index b90512bdb23..a7e0736432a 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll @@ -145,11 +145,7 @@ module MakeImpl Lang> { Location getASelectedSourceLocation(Node source); - Location getASelectedSourceLocationApprox(Node source); - Location getASelectedSinkLocation(Node sink); - - Location getASelectedSinkLocationApprox(Node sink); } /** diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll index 5e85cab00d9..c7883df0de1 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImplStage1.qll @@ -133,9 +133,7 @@ module MakeImplStage1 Lang> { private predicate isFilteredSource(Node source) { Config::isSource(source, _) and if Config::observeDiffInformedIncrementalMode() - then - AlertFiltering::filterByLocation(Config::getASelectedSourceLocation(source)) or - AlertFiltering::filterByLocationApprox(Config::getASelectedSourceLocationApprox(source)) + then AlertFiltering::filterByLocation(Config::getASelectedSourceLocation(source)) else any() } @@ -146,9 +144,7 @@ module MakeImplStage1 Lang> { Config::isSink(sink) ) and if Config::observeDiffInformedIncrementalMode() - then - AlertFiltering::filterByLocation(Config::getASelectedSinkLocation(sink)) or - AlertFiltering::filterByLocationApprox(Config::getASelectedSinkLocationApprox(sink)) + then AlertFiltering::filterByLocation(Config::getASelectedSinkLocation(sink)) else any() } diff --git a/shared/util/codeql/util/AlertFiltering.qll b/shared/util/codeql/util/AlertFiltering.qll index 97e6198a16c..091c2a89d00 100644 --- a/shared/util/codeql/util/AlertFiltering.qll +++ b/shared/util/codeql/util/AlertFiltering.qll @@ -89,32 +89,6 @@ module AlertFilteringImpl { /** Applies alert filtering to the given location. */ bindingset[location] predicate filterByLocation(Location location) { - not restrictAlertsTo(_, _, _) and not restrictAlertsToExactLocation(_, _, _, _, _) - or - exists(string filePath | - restrictAlertsToEntireFile(filePath) and - location.hasLocationInfo(filePath, _, _, _, _) - or - exists(int line | - restrictAlertsToStartLine(filePath, line) and - location.hasLocationInfo(filePath, line, _, _, _) - ) - ) - or - exists(string filePath, int startLine, int startColumn, int endLine, int endColumn | - restrictAlertsToExactLocation(filePath, startLine, startColumn, endLine, endColumn) - | - location.hasLocationInfo(filePath, startLine, startColumn, endLine, endColumn) - ) - } - - /** - * Holds if some subrange within `location` would be accepted by alert filtering. - * - * There does not need to exist a `Location` corresponding to that subrange. - */ - bindingset[location] - predicate filterByLocationApprox(Location location) { not restrictAlertsTo(_, _, _) and not restrictAlertsToExactLocation(_, _, _, _, _) or exists(string filePath | From cce17743bb0e88808e02fd4b25753992daed13f8 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 30 Jun 2025 14:12:36 +0200 Subject: [PATCH 015/199] Ql4Ql: Re-factor the ql/mising-security-metadata query. --- ql/ql/src/codeql_ql/ast/Ast.qll | 26 ++++++++-- .../queries/style/MissingSecurityMetadata.ql | 49 +++++++------------ .../MissingSecurityMetadata.expected | 2 +- 3 files changed, 40 insertions(+), 37 deletions(-) diff --git a/ql/ql/src/codeql_ql/ast/Ast.qll b/ql/ql/src/codeql_ql/ast/Ast.qll index 89bdf14d4b2..5713e21592b 100644 --- a/ql/ql/src/codeql_ql/ast/Ast.qll +++ b/ql/ql/src/codeql_ql/ast/Ast.qll @@ -202,25 +202,43 @@ class QueryDoc extends QLDoc { override string getAPrimaryQlClass() { result = "QueryDoc" } - /** Gets the @kind for the query */ + /** Gets the @kind for the query. */ string getQueryKind() { result = this.getContents().regexpCapture("(?s).*@kind ([\\w-]+)\\s.*", 1) } - /** Gets the @name for the query */ + /** Gets the @name for the query. */ string getQueryName() { result = this.getContents().regexpCapture("(?s).*@name (.+?)(?=\\n).*", 1) } - /** Gets the id part (without language) of the @id */ + /** Gets the id part (without language) of the @id. */ string getQueryId() { result = this.getContents().regexpCapture("(?s).*@id (\\w+)/([\\w\\-/]+)\\s.*", 2) } - /** Gets the language of the @id */ + /** Gets the language of the @id. */ string getQueryLanguage() { result = this.getContents().regexpCapture("(?s).*@id (\\w+)/([\\w\\-/]+)\\s.*", 1) } + + /** Gets the @precision for the query. */ + string getQueryPrecision() { + result = this.getContents().regexpCapture("(?s).*@precision ([\\w\\-]+)\\s.*", 1) + } + + /** Gets the @security-severity for the query. */ + string getQuerySecuritySeverity() { + result = this.getContents().regexpCapture("(?s).*@security\\-severity ([\\d\\.]+)\\s.*", 1) + } + + /** Gets the individual @tags for the query. */ + string getQueryTags() { + exists(string tags | tags = this.getContents().regexpCapture("(?s).*@tags ([^@]+)", 1) | + result = tags.splitAt("*").trim() and + result.regexpMatch("[\\w\\s\\-]+") + ) + } } class BlockComment extends TBlockComment, Comment { diff --git a/ql/ql/src/queries/style/MissingSecurityMetadata.ql b/ql/ql/src/queries/style/MissingSecurityMetadata.ql index 10f50fb3f99..fea75d36302 100644 --- a/ql/ql/src/queries/style/MissingSecurityMetadata.ql +++ b/ql/ql/src/queries/style/MissingSecurityMetadata.ql @@ -10,45 +10,30 @@ import ql -predicate missingSecuritySeverity(QLDoc doc) { - exists(string s | s = doc.getContents() | - exists(string securityTag | securityTag = s.splitAt("@") | - securityTag.matches("tags%security%") - ) and - exists(string precisionTag | precisionTag = s.splitAt("@") | - precisionTag.matches("precision %") - ) and - not exists(string securitySeverity | securitySeverity = s.splitAt("@") | - securitySeverity.matches("security-severity %") - ) - ) +private predicate unInterestingLocation(File f) { + f.getRelativePath().matches("%/" + ["experimental", "examples", "test"] + "/%") } -predicate missingSecurityTag(QLDoc doc) { - exists(string s | s = doc.getContents() | - exists(string securitySeverity | securitySeverity = s.splitAt("@") | - securitySeverity.matches("security-severity %") - ) and - exists(string precisionTag | precisionTag = s.splitAt("@") | - precisionTag.matches("precision %") - ) and - not exists(string securityTag | securityTag = s.splitAt("@") | - securityTag.matches("tags%security%") - ) - ) +predicate missingSecuritySeverity(QueryDoc doc) { + doc.getQueryTags() = "security" and + exists(doc.getQueryPrecision()) and + not exists(doc.getQuerySecuritySeverity()) } -from TopLevel t, string msg +predicate missingSecurityTag(QueryDoc doc) { + exists(doc.getQuerySecuritySeverity()) and + exists(doc.getQueryPrecision()) and + not doc.getQueryTags() = "security" +} + +from TopLevel t, QueryDoc doc, string msg where - t.getLocation().getFile().getBaseName().matches("%.ql") and - not t.getLocation() - .getFile() - .getRelativePath() - .matches("%/" + ["experimental", "examples", "test"] + "/%") and + doc = t.getQLDoc() and + not unInterestingLocation(t.getLocation().getFile()) and ( - missingSecuritySeverity(t.getQLDoc()) and + missingSecuritySeverity(doc) and msg = "This query file is missing a `@security-severity` tag." or - missingSecurityTag(t.getQLDoc()) and msg = "This query file is missing a `@tag security`." + missingSecurityTag(doc) and msg = "This query file is missing a `@tags security`." ) select t, msg diff --git a/ql/ql/test/queries/style/MissingSecurityMetadata/MissingSecurityMetadata.expected b/ql/ql/test/queries/style/MissingSecurityMetadata/MissingSecurityMetadata.expected index 28421838ae3..af2fbd54acb 100644 --- a/ql/ql/test/queries/style/MissingSecurityMetadata/MissingSecurityMetadata.expected +++ b/ql/ql/test/queries/style/MissingSecurityMetadata/MissingSecurityMetadata.expected @@ -1,2 +1,2 @@ -| testcases/BadNoSecurity.ql:1:1:16:9 | TopLevel | This query file is missing a `@tag security`. | +| testcases/BadNoSecurity.ql:1:1:16:9 | TopLevel | This query file is missing a `@tags security`. | | testcases/BadNoSeverity.ql:1:1:16:9 | TopLevel | This query file is missing a `@security-severity` tag. | From c46b528c0505cc1c3237b4af0490f16f14b65f89 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 30 Jun 2025 16:20:50 +0200 Subject: [PATCH 016/199] Ql4Ql: Add some quality tag testcases. --- ...QualityMaintainabilityWrongToplevel.expected | 0 .../BadQualityMaintainabilityWrongToplevel.ql | 17 +++++++++++++++++ .../BadQualityMultipleTopLevel.expected | 0 .../testcases/BadQualityMultipleTopLevel.ql | 17 +++++++++++++++++ .../testcases/BadQualityNoToplevel.expected | 0 .../testcases/BadQualityNoToplevel.ql | 16 ++++++++++++++++ .../BadQualityReliabilityWrongToplevel.expected | 0 .../BadQualityReliabilityWrongToplevel.ql | 17 +++++++++++++++++ .../testcases/GoodNotQuality.expected | 0 .../testcases/GoodNotQuality.ql | 16 ++++++++++++++++ .../GoodQualityMaintainability.expected | 0 .../testcases/GoodQualityMaintainability.ql | 17 +++++++++++++++++ .../GoodQualityMaintainabilityWithSub.expected | 0 .../GoodQualityMaintainabilityWithSub.ql | 17 +++++++++++++++++ .../testcases/GoodQualityReliability.expected | 0 .../testcases/GoodQualityReliability.ql | 16 ++++++++++++++++ .../GoodQualityReliabilityWithSub.expected | 0 .../testcases/GoodQualityReliabilityWithSub.ql | 17 +++++++++++++++++ 18 files changed, 150 insertions(+) create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityMaintainabilityWrongToplevel.expected create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityMaintainabilityWrongToplevel.ql create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityMultipleTopLevel.expected create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityMultipleTopLevel.ql create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityNoToplevel.expected create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityNoToplevel.ql create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityReliabilityWrongToplevel.expected create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityReliabilityWrongToplevel.ql create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodNotQuality.expected create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodNotQuality.ql create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainability.expected create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainability.ql create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainabilityWithSub.expected create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainabilityWithSub.ql create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliability.expected create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliability.ql create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliabilityWithSub.expected create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliabilityWithSub.ql diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityMaintainabilityWrongToplevel.expected b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityMaintainabilityWrongToplevel.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityMaintainabilityWrongToplevel.ql b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityMaintainabilityWrongToplevel.ql new file mode 100644 index 00000000000..3dd18771f95 --- /dev/null +++ b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityMaintainabilityWrongToplevel.ql @@ -0,0 +1,17 @@ +/** + * @name Some query + * @description Some description + * @kind problem + * @problem.severity warning + * @precision very-high + * @id ql/quality-query-test + * @tags quality + * maintainability + * error-handling + */ + +import ql + +from Class c +where none() +select c, "" diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityMultipleTopLevel.expected b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityMultipleTopLevel.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityMultipleTopLevel.ql b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityMultipleTopLevel.ql new file mode 100644 index 00000000000..a9a7b48b76c --- /dev/null +++ b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityMultipleTopLevel.ql @@ -0,0 +1,17 @@ +/** + * @name Some query + * @description Some description + * @kind problem + * @problem.severity warning + * @precision very-high + * @id ql/quality-query-test + * @tags quality + * maintainability + * reliability + */ + +import ql + +from Class c +where none() +select c, "" diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityNoToplevel.expected b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityNoToplevel.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityNoToplevel.ql b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityNoToplevel.ql new file mode 100644 index 00000000000..ad2ab5c1fb5 --- /dev/null +++ b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityNoToplevel.ql @@ -0,0 +1,16 @@ +/** + * @name Some query + * @description Some description + * @kind problem + * @problem.severity warning + * @precision very-high + * @id ql/quality-query-test + * @tags quality + * someothertag + */ + +import ql + +from Class c +where none() +select c, "" diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityReliabilityWrongToplevel.expected b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityReliabilityWrongToplevel.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityReliabilityWrongToplevel.ql b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityReliabilityWrongToplevel.ql new file mode 100644 index 00000000000..53e84fb8a19 --- /dev/null +++ b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/BadQualityReliabilityWrongToplevel.ql @@ -0,0 +1,17 @@ +/** + * @name Some query + * @description Some description + * @kind problem + * @problem.severity warning + * @precision very-high + * @id ql/quality-query-test + * @tags quality + * reliability + * readability + */ + +import ql + +from Class c +where none() +select c, "" diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodNotQuality.expected b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodNotQuality.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodNotQuality.ql b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodNotQuality.ql new file mode 100644 index 00000000000..60b72291831 --- /dev/null +++ b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodNotQuality.ql @@ -0,0 +1,16 @@ +/** + * @name Some query + * @description Some description + * @kind problem + * @problem.severity warning + * @security-severity 10.0 + * @precision very-high + * @id ql/quality-query-test + * @tags security + */ + +import ql + +from Class c +where none() +select c, "" diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainability.expected b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainability.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainability.ql b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainability.ql new file mode 100644 index 00000000000..9e152b90d45 --- /dev/null +++ b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainability.ql @@ -0,0 +1,17 @@ +/** + * @name Some query + * @description Some description + * @kind problem + * @problem.severity warning + * @security-severity 10.0 + * @precision very-high + * @id ql/quality-query-test + * @tags quality + * maintainability + */ + +import ql + +from Class c +where none() +select c, "" diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainabilityWithSub.expected b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainabilityWithSub.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainabilityWithSub.ql b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainabilityWithSub.ql new file mode 100644 index 00000000000..7d70c856403 --- /dev/null +++ b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainabilityWithSub.ql @@ -0,0 +1,17 @@ +/** + * @name Some query + * @description Some description + * @kind problem + * @problem.severity warning + * @precision very-high + * @id ql/quality-query-test + * @tags quality + * maintainability + * readability + */ + +import ql + +from Class c +where none() +select c, "" diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliability.expected b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliability.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliability.ql b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliability.ql new file mode 100644 index 00000000000..f3979922b0d --- /dev/null +++ b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliability.ql @@ -0,0 +1,16 @@ +/** + * @name Some query + * @description Some description + * @kind problem + * @problem.severity warning + * @precision very-high + * @id ql/quality-query-test + * @tags quality + * reliability + */ + +import ql + +from Class c +where none() +select c, "" diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliabilityWithSub.expected b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliabilityWithSub.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliabilityWithSub.ql b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliabilityWithSub.ql new file mode 100644 index 00000000000..ec9c4136e86 --- /dev/null +++ b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliabilityWithSub.ql @@ -0,0 +1,17 @@ +/** + * @name Some query + * @description Some description + * @kind problem + * @problem.severity warning + * @precision very-high + * @id ql/quality-query-test + * @tags quality + * reliability + * correctness + */ + +import ql + +from Class c +where none() +select c, "" From e00b5351a42dfe4b3d60e32796b86f53a1b2a3bf Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 30 Jun 2025 16:43:20 +0200 Subject: [PATCH 017/199] Ql4Ql: Add a check for quality tag consistency. --- .../queries/style/MissingQualityMetadata.ql | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 ql/ql/src/queries/style/MissingQualityMetadata.ql diff --git a/ql/ql/src/queries/style/MissingQualityMetadata.ql b/ql/ql/src/queries/style/MissingQualityMetadata.ql new file mode 100644 index 00000000000..a01b2028e57 --- /dev/null +++ b/ql/ql/src/queries/style/MissingQualityMetadata.ql @@ -0,0 +1,51 @@ +/** + * @name Missing quality metadata + * @description Quality queries should have exactly one top-level category and if sub-categories are used, the appropriate top-level category should be used. + * @kind problem + * @problem.severity warning + * @precision very-high + * @id ql/missing-quality-metadata + * @tags correctness + */ + +import ql + +private predicate unInterestingLocation(File f) { + f.getRelativePath().matches("%/" + ["experimental", "examples", "test"] + "/%") +} + +private predicate hasQualityTag(QueryDoc doc) { doc.getQueryTags() = "quality" } + +private predicate incorrectTopLevelCategorisation(QueryDoc doc) { + count(string s | s = doc.getQueryTags() and s = ["maintainability", "reliability"]) != 1 +} + +private predicate reliabilitySubCategory(QueryDoc doc) { + doc.getQueryTags() = ["correctness", "performance", "concurrency", "error-handling"] +} + +private predicate maintainabilitySubCategory(QueryDoc doc) { + doc.getQueryTags() = ["readability", "useless-code", "complexity"] +} + +from TopLevel t, QueryDoc doc, string msg +where + doc = t.getQLDoc() and + not unInterestingLocation(t.getLocation().getFile()) and + hasQualityTag(doc) and + ( + incorrectTopLevelCategorisation(doc) and + msg = + "This query file has incorrect top-level categorisation. It should have exactly one top-level category, either `@tags maintainability` or `@tags reliability`." + or + maintainabilitySubCategory(doc) and + not doc.getQueryTags() = "maintainability" and + msg = + "This query file has a sub-category of maintainability but is missing the `@tags maintainability` tag." + or + reliabilitySubCategory(doc) and + not doc.getQueryTags() = "reliability" and + msg = + "This query file has a sub-category of reliability but is missing the `@tags reliability` tag." + ) +select t, msg From 60a1d02357f423ad777132a70a4d03dd6ab50934 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 30 Jun 2025 16:44:29 +0200 Subject: [PATCH 018/199] Ql4Ql: Add MissingQualityMetadata test. --- .../MissingQualityMetadata/MissingQualityMetadata.expected | 4 ++++ .../style/MissingQualityMetadata/MissingQualityMetadata.qlref | 1 + 2 files changed, 5 insertions(+) create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.expected create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.qlref diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.expected b/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.expected new file mode 100644 index 00000000000..6eabd28445b --- /dev/null +++ b/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.expected @@ -0,0 +1,4 @@ +| testcases/BadQualityMaintainabilityWrongToplevel.ql:1:1:17:13 | TopLevel | This query file has a sub-category of reliability but is missing the `@tags reliability` tag. | +| testcases/BadQualityMultipleTopLevel.ql:1:1:17:13 | TopLevel | This query file has incorrect top-level categorisation. It should have exactly one top-level category, either `@tags maintainability` or `@tags reliability`. | +| testcases/BadQualityNoToplevel.ql:1:1:16:13 | TopLevel | This query file has incorrect top-level categorisation. It should have exactly one top-level category, either `@tags maintainability` or `@tags reliability`. | +| testcases/BadQualityReliabilityWrongToplevel.ql:1:1:17:13 | TopLevel | This query file has a sub-category of maintainability but is missing the `@tags maintainability` tag. | diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.qlref b/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.qlref new file mode 100644 index 00000000000..6d7eb26bede --- /dev/null +++ b/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.qlref @@ -0,0 +1 @@ +queries/style/MissingQualityMetadata.ql From af1c4e0896095fa28dddc05bcc4a14d64e00124d Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 1 Jul 2025 09:42:20 +0200 Subject: [PATCH 019/199] Ql4Ql: Share the definition of TestFile between multiple tests. --- ql/ql/src/codeql/files/FileSystem.qll | 5 +++++ ql/ql/src/queries/style/MissingQualityMetadata.ql | 6 +----- ql/ql/src/queries/style/MissingSecurityMetadata.ql | 6 +----- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/ql/ql/src/codeql/files/FileSystem.qll b/ql/ql/src/codeql/files/FileSystem.qll index 5a219f3b7f0..7f64ed00b03 100644 --- a/ql/ql/src/codeql/files/FileSystem.qll +++ b/ql/ql/src/codeql/files/FileSystem.qll @@ -61,3 +61,8 @@ class File extends Container, Impl::File { /** Holds if this file was extracted from ordinary source code. */ predicate fromSource() { any() } } + +/** A test file. */ +class TestFile extends File { + TestFile() { this.getRelativePath().matches("%/" + ["experimental", "examples", "test"] + "/%") } +} diff --git a/ql/ql/src/queries/style/MissingQualityMetadata.ql b/ql/ql/src/queries/style/MissingQualityMetadata.ql index a01b2028e57..ceed39cf717 100644 --- a/ql/ql/src/queries/style/MissingQualityMetadata.ql +++ b/ql/ql/src/queries/style/MissingQualityMetadata.ql @@ -10,10 +10,6 @@ import ql -private predicate unInterestingLocation(File f) { - f.getRelativePath().matches("%/" + ["experimental", "examples", "test"] + "/%") -} - private predicate hasQualityTag(QueryDoc doc) { doc.getQueryTags() = "quality" } private predicate incorrectTopLevelCategorisation(QueryDoc doc) { @@ -31,7 +27,7 @@ private predicate maintainabilitySubCategory(QueryDoc doc) { from TopLevel t, QueryDoc doc, string msg where doc = t.getQLDoc() and - not unInterestingLocation(t.getLocation().getFile()) and + not t.getLocation().getFile() instanceof TestFile and hasQualityTag(doc) and ( incorrectTopLevelCategorisation(doc) and diff --git a/ql/ql/src/queries/style/MissingSecurityMetadata.ql b/ql/ql/src/queries/style/MissingSecurityMetadata.ql index fea75d36302..1618bed02ea 100644 --- a/ql/ql/src/queries/style/MissingSecurityMetadata.ql +++ b/ql/ql/src/queries/style/MissingSecurityMetadata.ql @@ -10,10 +10,6 @@ import ql -private predicate unInterestingLocation(File f) { - f.getRelativePath().matches("%/" + ["experimental", "examples", "test"] + "/%") -} - predicate missingSecuritySeverity(QueryDoc doc) { doc.getQueryTags() = "security" and exists(doc.getQueryPrecision()) and @@ -29,7 +25,7 @@ predicate missingSecurityTag(QueryDoc doc) { from TopLevel t, QueryDoc doc, string msg where doc = t.getQLDoc() and - not unInterestingLocation(t.getLocation().getFile()) and + not t.getLocation().getFile() instanceof TestFile and ( missingSecuritySeverity(doc) and msg = "This query file is missing a `@security-severity` tag." From f58064e119500396b54182d5fe91050f5350571e Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 2 Jul 2025 12:01:36 +0200 Subject: [PATCH 020/199] Ql4Ql: Address review comments. --- ql/ql/src/codeql_ql/ast/Ast.qll | 4 ++-- .../queries/style/MissingQualityMetadata.ql | 18 +++++++++--------- .../queries/style/MissingSecurityMetadata.ql | 8 ++++---- .../MissingQualityMetadata.expected | 8 ++++---- .../MissingSecurityMetadata.expected | 4 ++-- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/ql/ql/src/codeql_ql/ast/Ast.qll b/ql/ql/src/codeql_ql/ast/Ast.qll index 5713e21592b..a7c3709ff22 100644 --- a/ql/ql/src/codeql_ql/ast/Ast.qll +++ b/ql/ql/src/codeql_ql/ast/Ast.qll @@ -232,8 +232,8 @@ class QueryDoc extends QLDoc { result = this.getContents().regexpCapture("(?s).*@security\\-severity ([\\d\\.]+)\\s.*", 1) } - /** Gets the individual @tags for the query. */ - string getQueryTags() { + /** Gets the individual @tags for the query, if any. */ + string getAQueryTag() { exists(string tags | tags = this.getContents().regexpCapture("(?s).*@tags ([^@]+)", 1) | result = tags.splitAt("*").trim() and result.regexpMatch("[\\w\\s\\-]+") diff --git a/ql/ql/src/queries/style/MissingQualityMetadata.ql b/ql/ql/src/queries/style/MissingQualityMetadata.ql index ceed39cf717..547590c01ee 100644 --- a/ql/ql/src/queries/style/MissingQualityMetadata.ql +++ b/ql/ql/src/queries/style/MissingQualityMetadata.ql @@ -10,18 +10,18 @@ import ql -private predicate hasQualityTag(QueryDoc doc) { doc.getQueryTags() = "quality" } +private predicate hasQualityTag(QueryDoc doc) { doc.getAQueryTag() = "quality" } -private predicate incorrectTopLevelCategorisation(QueryDoc doc) { - count(string s | s = doc.getQueryTags() and s = ["maintainability", "reliability"]) != 1 +private predicate correctTopLevelCategorisation(QueryDoc doc) { + strictcount(string s | s = doc.getAQueryTag() and s = ["maintainability", "reliability"]) = 1 } private predicate reliabilitySubCategory(QueryDoc doc) { - doc.getQueryTags() = ["correctness", "performance", "concurrency", "error-handling"] + doc.getAQueryTag() = ["correctness", "performance", "concurrency", "error-handling"] } private predicate maintainabilitySubCategory(QueryDoc doc) { - doc.getQueryTags() = ["readability", "useless-code", "complexity"] + doc.getAQueryTag() = ["readability", "useless-code", "complexity"] } from TopLevel t, QueryDoc doc, string msg @@ -30,18 +30,18 @@ where not t.getLocation().getFile() instanceof TestFile and hasQualityTag(doc) and ( - incorrectTopLevelCategorisation(doc) and + not correctTopLevelCategorisation(doc) and msg = "This query file has incorrect top-level categorisation. It should have exactly one top-level category, either `@tags maintainability` or `@tags reliability`." or maintainabilitySubCategory(doc) and - not doc.getQueryTags() = "maintainability" and + not doc.getAQueryTag() = "maintainability" and msg = "This query file has a sub-category of maintainability but is missing the `@tags maintainability` tag." or reliabilitySubCategory(doc) and - not doc.getQueryTags() = "reliability" and + not doc.getAQueryTag() = "reliability" and msg = "This query file has a sub-category of reliability but is missing the `@tags reliability` tag." ) -select t, msg +select doc, msg diff --git a/ql/ql/src/queries/style/MissingSecurityMetadata.ql b/ql/ql/src/queries/style/MissingSecurityMetadata.ql index 1618bed02ea..5ab2cd98bbe 100644 --- a/ql/ql/src/queries/style/MissingSecurityMetadata.ql +++ b/ql/ql/src/queries/style/MissingSecurityMetadata.ql @@ -1,6 +1,6 @@ /** * @name Missing security metadata - * @description Security queries should have both a `@tag security` and a `@security-severity` tag. + * @description Security queries should have both a `@tags security` and a `@security-severity` tag. * @kind problem * @problem.severity warning * @precision very-high @@ -11,7 +11,7 @@ import ql predicate missingSecuritySeverity(QueryDoc doc) { - doc.getQueryTags() = "security" and + doc.getAQueryTag() = "security" and exists(doc.getQueryPrecision()) and not exists(doc.getQuerySecuritySeverity()) } @@ -19,7 +19,7 @@ predicate missingSecuritySeverity(QueryDoc doc) { predicate missingSecurityTag(QueryDoc doc) { exists(doc.getQuerySecuritySeverity()) and exists(doc.getQueryPrecision()) and - not doc.getQueryTags() = "security" + not doc.getAQueryTag() = "security" } from TopLevel t, QueryDoc doc, string msg @@ -32,4 +32,4 @@ where or missingSecurityTag(doc) and msg = "This query file is missing a `@tags security`." ) -select t, msg +select doc, msg diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.expected b/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.expected index 6eabd28445b..ec4939b9c4e 100644 --- a/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.expected +++ b/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.expected @@ -1,4 +1,4 @@ -| testcases/BadQualityMaintainabilityWrongToplevel.ql:1:1:17:13 | TopLevel | This query file has a sub-category of reliability but is missing the `@tags reliability` tag. | -| testcases/BadQualityMultipleTopLevel.ql:1:1:17:13 | TopLevel | This query file has incorrect top-level categorisation. It should have exactly one top-level category, either `@tags maintainability` or `@tags reliability`. | -| testcases/BadQualityNoToplevel.ql:1:1:16:13 | TopLevel | This query file has incorrect top-level categorisation. It should have exactly one top-level category, either `@tags maintainability` or `@tags reliability`. | -| testcases/BadQualityReliabilityWrongToplevel.ql:1:1:17:13 | TopLevel | This query file has a sub-category of maintainability but is missing the `@tags maintainability` tag. | +| testcases/BadQualityMaintainabilityWrongToplevel.ql:1:1:11:3 | QueryDoc | This query file has a sub-category of reliability but is missing the `@tags reliability` tag. | +| testcases/BadQualityMultipleTopLevel.ql:1:1:11:3 | QueryDoc | This query file has incorrect top-level categorisation. It should have exactly one top-level category, either `@tags maintainability` or `@tags reliability`. | +| testcases/BadQualityNoToplevel.ql:1:1:10:3 | QueryDoc | This query file has incorrect top-level categorisation. It should have exactly one top-level category, either `@tags maintainability` or `@tags reliability`. | +| testcases/BadQualityReliabilityWrongToplevel.ql:1:1:11:3 | QueryDoc | This query file has a sub-category of maintainability but is missing the `@tags maintainability` tag. | diff --git a/ql/ql/test/queries/style/MissingSecurityMetadata/MissingSecurityMetadata.expected b/ql/ql/test/queries/style/MissingSecurityMetadata/MissingSecurityMetadata.expected index af2fbd54acb..bc241f3f0b4 100644 --- a/ql/ql/test/queries/style/MissingSecurityMetadata/MissingSecurityMetadata.expected +++ b/ql/ql/test/queries/style/MissingSecurityMetadata/MissingSecurityMetadata.expected @@ -1,2 +1,2 @@ -| testcases/BadNoSecurity.ql:1:1:16:9 | TopLevel | This query file is missing a `@tags security`. | -| testcases/BadNoSeverity.ql:1:1:16:9 | TopLevel | This query file is missing a `@security-severity` tag. | +| testcases/BadNoSecurity.ql:1:1:10:3 | QueryDoc | This query file is missing a `@tags security`. | +| testcases/BadNoSeverity.ql:1:1:10:3 | QueryDoc | This query file is missing a `@security-severity` tag. | From b79e2dd0baaa1c68f9507aeb1f37f9132ffd82dc Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 3 Jul 2025 11:13:57 +0200 Subject: [PATCH 021/199] Ql4Ql: Add some more quality tag testcases. --- .../MissingQualityMetadata.expected | 2 ++ ...QualityMaintainabilityWithCrossSub.expected | 0 .../GoodQualityMaintainabilityWithCrossSub.ql | 18 ++++++++++++++++++ ...GoodQualityReliabilityWithCrossSub.expected | 0 .../GoodQualityReliabilityWithCrossSub.ql | 18 ++++++++++++++++++ 5 files changed, 38 insertions(+) create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainabilityWithCrossSub.expected create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainabilityWithCrossSub.ql create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliabilityWithCrossSub.expected create mode 100644 ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliabilityWithCrossSub.ql diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.expected b/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.expected index ec4939b9c4e..9ee4bd78576 100644 --- a/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.expected +++ b/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.expected @@ -2,3 +2,5 @@ | testcases/BadQualityMultipleTopLevel.ql:1:1:11:3 | QueryDoc | This query file has incorrect top-level categorisation. It should have exactly one top-level category, either `@tags maintainability` or `@tags reliability`. | | testcases/BadQualityNoToplevel.ql:1:1:10:3 | QueryDoc | This query file has incorrect top-level categorisation. It should have exactly one top-level category, either `@tags maintainability` or `@tags reliability`. | | testcases/BadQualityReliabilityWrongToplevel.ql:1:1:11:3 | QueryDoc | This query file has a sub-category of maintainability but is missing the `@tags maintainability` tag. | +| testcases/GoodQualityMaintainabilityWithCrossSub.ql:1:1:12:3 | QueryDoc | This query file has a sub-category of reliability but is missing the `@tags reliability` tag. | +| testcases/GoodQualityReliabilityWithCrossSub.ql:1:1:12:3 | QueryDoc | This query file has a sub-category of maintainability but is missing the `@tags maintainability` tag. | diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainabilityWithCrossSub.expected b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainabilityWithCrossSub.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainabilityWithCrossSub.ql b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainabilityWithCrossSub.ql new file mode 100644 index 00000000000..fe1f511abff --- /dev/null +++ b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityMaintainabilityWithCrossSub.ql @@ -0,0 +1,18 @@ +/** + * @name Some query + * @description Some description + * @kind problem + * @problem.severity warning + * @precision very-high + * @id ql/quality-query-test + * @tags quality + * maintainability + * readability + * correctness + */ + +import ql + +from Class c +where none() +select c, "" diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliabilityWithCrossSub.expected b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliabilityWithCrossSub.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliabilityWithCrossSub.ql b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliabilityWithCrossSub.ql new file mode 100644 index 00000000000..78594e8f9c3 --- /dev/null +++ b/ql/ql/test/queries/style/MissingQualityMetadata/testcases/GoodQualityReliabilityWithCrossSub.ql @@ -0,0 +1,18 @@ +/** + * @name Some query + * @description Some description + * @kind problem + * @problem.severity warning + * @precision very-high + * @id ql/quality-query-test + * @tags quality + * reliability + * correctness + * readability + */ + +import ql + +from Class c +where none() +select c, "" From f810e17d9ee6956fe74bac548853aa3fa806e345 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 3 Jul 2025 11:26:11 +0200 Subject: [PATCH 022/199] Ql4Ql: Address review comments and update expected test output. --- .../queries/style/MissingQualityMetadata.ql | 23 +++++++++++-------- .../MissingQualityMetadata.expected | 6 ++--- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/ql/ql/src/queries/style/MissingQualityMetadata.ql b/ql/ql/src/queries/style/MissingQualityMetadata.ql index 547590c01ee..88c87718634 100644 --- a/ql/ql/src/queries/style/MissingQualityMetadata.ql +++ b/ql/ql/src/queries/style/MissingQualityMetadata.ql @@ -34,14 +34,19 @@ where msg = "This query file has incorrect top-level categorisation. It should have exactly one top-level category, either `@tags maintainability` or `@tags reliability`." or - maintainabilitySubCategory(doc) and - not doc.getAQueryTag() = "maintainability" and - msg = - "This query file has a sub-category of maintainability but is missing the `@tags maintainability` tag." - or - reliabilitySubCategory(doc) and - not doc.getAQueryTag() = "reliability" and - msg = - "This query file has a sub-category of reliability but is missing the `@tags reliability` tag." + correctTopLevelCategorisation(doc) and + ( + doc.getAQueryTag() = "reliability" and + not reliabilitySubCategory(doc) and + maintainabilitySubCategory(doc) and + msg = + "This query file has a sub-category of maintainability but has the `@tags reliability` tag." + or + doc.getAQueryTag() = "maintainability" and + not maintainabilitySubCategory(doc) and + reliabilitySubCategory(doc) and + msg = + "This query file has a sub-category of reliability but has the `@tags maintainability` tag." + ) ) select doc, msg diff --git a/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.expected b/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.expected index 9ee4bd78576..7904870bdf6 100644 --- a/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.expected +++ b/ql/ql/test/queries/style/MissingQualityMetadata/MissingQualityMetadata.expected @@ -1,6 +1,4 @@ -| testcases/BadQualityMaintainabilityWrongToplevel.ql:1:1:11:3 | QueryDoc | This query file has a sub-category of reliability but is missing the `@tags reliability` tag. | +| testcases/BadQualityMaintainabilityWrongToplevel.ql:1:1:11:3 | QueryDoc | This query file has a sub-category of reliability but has the `@tags maintainability` tag. | | testcases/BadQualityMultipleTopLevel.ql:1:1:11:3 | QueryDoc | This query file has incorrect top-level categorisation. It should have exactly one top-level category, either `@tags maintainability` or `@tags reliability`. | | testcases/BadQualityNoToplevel.ql:1:1:10:3 | QueryDoc | This query file has incorrect top-level categorisation. It should have exactly one top-level category, either `@tags maintainability` or `@tags reliability`. | -| testcases/BadQualityReliabilityWrongToplevel.ql:1:1:11:3 | QueryDoc | This query file has a sub-category of maintainability but is missing the `@tags maintainability` tag. | -| testcases/GoodQualityMaintainabilityWithCrossSub.ql:1:1:12:3 | QueryDoc | This query file has a sub-category of reliability but is missing the `@tags reliability` tag. | -| testcases/GoodQualityReliabilityWithCrossSub.ql:1:1:12:3 | QueryDoc | This query file has a sub-category of maintainability but is missing the `@tags maintainability` tag. | +| testcases/BadQualityReliabilityWrongToplevel.ql:1:1:11:3 | QueryDoc | This query file has a sub-category of maintainability but has the `@tags reliability` tag. | From aefd941135731333afe4081819ad668f867d4798 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 3 Jul 2025 11:48:56 +0200 Subject: [PATCH 023/199] Java/Javascript: Fix violations. --- java/ql/src/Language Abuse/TypeVariableHidesType.ql | 4 ++-- javascript/ql/src/Quality/UnhandledErrorInStreamPipeline.ql | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java/ql/src/Language Abuse/TypeVariableHidesType.ql b/java/ql/src/Language Abuse/TypeVariableHidesType.ql index 81da0e9703e..42d0a7bea2b 100644 --- a/java/ql/src/Language Abuse/TypeVariableHidesType.ql +++ b/java/ql/src/Language Abuse/TypeVariableHidesType.ql @@ -6,10 +6,10 @@ * @problem.severity warning * @precision medium * @id java/type-variable-hides-type - * @tags reliability + * @tags quality + * maintainability * readability * types - * quality */ import java diff --git a/javascript/ql/src/Quality/UnhandledErrorInStreamPipeline.ql b/javascript/ql/src/Quality/UnhandledErrorInStreamPipeline.ql index a6142a2e6e7..6500cd15777 100644 --- a/javascript/ql/src/Quality/UnhandledErrorInStreamPipeline.ql +++ b/javascript/ql/src/Quality/UnhandledErrorInStreamPipeline.ql @@ -6,7 +6,7 @@ * @problem.severity warning * @precision high * @tags quality - * maintainability + * reliability * error-handling * frameworks/nodejs */ From 11c4a638bc63f6ddc5861831967afa2073636672 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 3 Jul 2025 12:19:41 +0200 Subject: [PATCH 024/199] Quality tags: Clarify the quality sub-category tagging policy. --- docs/query-metadata-style-guide.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/query-metadata-style-guide.md b/docs/query-metadata-style-guide.md index 18fa5d1880f..f6cc6f883fc 100644 --- a/docs/query-metadata-style-guide.md +++ b/docs/query-metadata-style-guide.md @@ -157,7 +157,7 @@ Each code quality related query should have **one** of these two "top-level" cat * `@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. -In addition to the "top-level" categories, we will also add sub-categories to further group code quality related queries: +In addition to the "top-level" categories, we may also add sub-categories to further group code quality related queries: * `@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. @@ -171,6 +171,7 @@ In addition to the "top-level" categories, we will also add sub-categories to fu * `@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 +You may use sub-categories from both top-level categories on the same query. However, if you only use sub-categories from a single top-level category, then you must also tag the query with that top-level category. There are also more specific `@tags` that can be added. See, the following pages for examples of the low-level tags: From d10b9e665c845b302eedb8f7a38aac3842251726 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 4 Jul 2025 16:55:09 +0100 Subject: [PATCH 025/199] Fix linter warnings in Request Forgery tests --- .../Security/CWE-918/RequestForgery.expected | 12 ++++++------ .../test/query-tests/Security/CWE-918/websocket.go | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected index 76097b7a5c0..914d4c3c084 100644 --- a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected +++ b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected @@ -14,8 +14,8 @@ | websocket.go:129:3:129:62 | call to DialContext | websocket.go:126:21:126:31 | call to Referer | websocket.go:129:38:129:51 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:129:38:129:51 | untrustedInput | WebSocket URL | websocket.go:126:21:126:31 | call to Referer | user-provided value | | websocket.go:155:3:155:45 | call to Dial | websocket.go:154:21:154:31 | call to Referer | websocket.go:155:31:155:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:155:31:155:44 | untrustedInput | WebSocket URL | websocket.go:154:21:154:31 | call to Referer | user-provided value | | websocket.go:162:3:162:45 | call to Dial | websocket.go:160:21:160:31 | call to Referer | websocket.go:162:31:162:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:162:31:162:44 | untrustedInput | WebSocket URL | websocket.go:160:21:160:31 | call to Referer | user-provided value | -| websocket.go:197:3:197:32 | call to BuildProxy | websocket.go:195:21:195:31 | call to Referer | websocket.go:197:18:197:31 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:197:18:197:31 | untrustedInput | WebSocket URL | websocket.go:195:21:195:31 | call to Referer | user-provided value | -| websocket.go:204:3:204:25 | call to New | websocket.go:202:21:202:31 | call to Referer | websocket.go:204:11:204:24 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:204:11:204:24 | untrustedInput | WebSocket URL | websocket.go:202:21:202:31 | call to Referer | user-provided value | +| websocket.go:197:7:197:36 | call to BuildProxy | websocket.go:195:21:195:31 | call to Referer | websocket.go:197:22:197:35 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:197:22:197:35 | untrustedInput | WebSocket URL | websocket.go:195:21:195:31 | call to Referer | user-provided value | +| websocket.go:204:7:204:29 | call to New | websocket.go:202:21:202:31 | call to Referer | websocket.go:204:15:204:28 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:204:15:204:28 | untrustedInput | WebSocket URL | websocket.go:202:21:202:31 | call to Referer | user-provided value | edges | RequestForgery.go:8:12:8:34 | call to FormValue | RequestForgery.go:11:24:11:65 | ...+... | provenance | Src:MaD:1 | | tst.go:10:13:10:35 | call to FormValue | tst.go:14:11:14:17 | tainted | provenance | Src:MaD:1 | @@ -42,8 +42,8 @@ edges | websocket.go:126:21:126:31 | call to Referer | websocket.go:129:38:129:51 | untrustedInput | provenance | Src:MaD:2 | | websocket.go:154:21:154:31 | call to Referer | websocket.go:155:31:155:44 | untrustedInput | provenance | Src:MaD:2 | | websocket.go:160:21:160:31 | call to Referer | websocket.go:162:31:162:44 | untrustedInput | provenance | Src:MaD:2 | -| websocket.go:195:21:195:31 | call to Referer | websocket.go:197:18:197:31 | untrustedInput | provenance | Src:MaD:2 | -| websocket.go:202:21:202:31 | call to Referer | websocket.go:204:11:204:24 | untrustedInput | provenance | Src:MaD:2 | +| websocket.go:195:21:195:31 | call to Referer | websocket.go:197:22:197:35 | untrustedInput | provenance | Src:MaD:2 | +| websocket.go:202:21:202:31 | call to Referer | websocket.go:204:15:204:28 | untrustedInput | provenance | Src:MaD:2 | models | 1 | Source: net/http; Request; true; FormValue; ; ; ReturnValue; remote; manual | | 2 | Source: net/http; Request; true; Referer; ; ; ReturnValue; remote; manual | @@ -80,7 +80,7 @@ nodes | websocket.go:160:21:160:31 | call to Referer | semmle.label | call to Referer | | websocket.go:162:31:162:44 | untrustedInput | semmle.label | untrustedInput | | websocket.go:195:21:195:31 | call to Referer | semmle.label | call to Referer | -| websocket.go:197:18:197:31 | untrustedInput | semmle.label | untrustedInput | +| websocket.go:197:22:197:35 | untrustedInput | semmle.label | untrustedInput | | websocket.go:202:21:202:31 | call to Referer | semmle.label | call to Referer | -| websocket.go:204:11:204:24 | untrustedInput | semmle.label | untrustedInput | +| websocket.go:204:15:204:28 | untrustedInput | semmle.label | untrustedInput | subpaths diff --git a/go/ql/test/query-tests/Security/CWE-918/websocket.go b/go/ql/test/query-tests/Security/CWE-918/websocket.go index 328200770ae..fb3882000ff 100644 --- a/go/ql/test/query-tests/Security/CWE-918/websocket.go +++ b/go/ql/test/query-tests/Security/CWE-918/websocket.go @@ -166,7 +166,7 @@ func test() { http.HandleFunc("/ex12", func(w http.ResponseWriter, r *http.Request) { untrustedInput := r.Referer() - if "localhost" == untrustedInput { + if untrustedInput == "localhost" { dialer := gobwas.Dialer{} dialer.Dial(context.TODO(), untrustedInput) } @@ -176,8 +176,8 @@ func test() { http.HandleFunc("/ex13", func(w http.ResponseWriter, r *http.Request) { untrustedInput := r.Referer() - if "localhost" == untrustedInput { - sac.New(untrustedInput) + if untrustedInput == "localhost" { + _ = sac.New(untrustedInput) } }) @@ -185,8 +185,8 @@ func test() { http.HandleFunc("/ex14", func(w http.ResponseWriter, r *http.Request) { untrustedInput := r.Referer() - if "localhost" == untrustedInput { - sac.BuildProxy(untrustedInput) + if untrustedInput == "localhost" { + _ = sac.BuildProxy(untrustedInput) } }) @@ -194,14 +194,14 @@ func test() { http.HandleFunc("/ex15", func(w http.ResponseWriter, r *http.Request) { untrustedInput := r.Referer() - sac.BuildProxy(untrustedInput) + _ = sac.BuildProxy(untrustedInput) }) // sac007 websocket New bad http.HandleFunc("/ex16", func(w http.ResponseWriter, r *http.Request) { untrustedInput := r.Referer() - sac.New(untrustedInput) + _ = sac.New(untrustedInput) }) log.Println(http.ListenAndServe(":80", nil)) From 0788a90d886ca66d8e3817bd691962fa85ee7d96 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 4 Jul 2025 16:56:05 +0100 Subject: [PATCH 026/199] Convert RequestForgery test to inline expectations --- .../Security/CWE-918/RequestForgery.go | 4 +- .../Security/CWE-918/RequestForgery.qlref | 4 +- .../test/query-tests/Security/CWE-918/tst.go | 20 +++++----- .../query-tests/Security/CWE-918/websocket.go | 38 +++++++++---------- 4 files changed, 34 insertions(+), 32 deletions(-) diff --git a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.go b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.go index c88e9dc5f74..ab8f907c58b 100644 --- a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.go +++ b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.go @@ -5,10 +5,10 @@ import ( ) func handler(w http.ResponseWriter, req *http.Request) { - target := req.FormValue("target") + target := req.FormValue("target") // $ Source // BAD: `target` is controlled by the attacker - resp, err := http.Get("https://" + target + ".example.com/data/") + resp, err := http.Get("https://" + target + ".example.com/data/") // $ Alert if err != nil { // error handling } diff --git a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.qlref b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.qlref index 061679da228..760862973f1 100644 --- a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.qlref +++ b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.qlref @@ -1,2 +1,4 @@ query: Security/CWE-918/RequestForgery.ql -postprocess: utils/test/PrettyPrintModels.ql +postprocess: + - utils/test/PrettyPrintModels.ql + - utils/test/InlineExpectationsTestQuery.ql diff --git a/go/ql/test/query-tests/Security/CWE-918/tst.go b/go/ql/test/query-tests/Security/CWE-918/tst.go index 0e04429580c..00a09fef0f7 100644 --- a/go/ql/test/query-tests/Security/CWE-918/tst.go +++ b/go/ql/test/query-tests/Security/CWE-918/tst.go @@ -7,26 +7,26 @@ import ( ) func handler2(w http.ResponseWriter, req *http.Request) { - tainted := req.FormValue("target") + tainted := req.FormValue("target") // $ Source http.Get("example.com") // OK - http.Get(tainted) // Not OK + http.Get(tainted) // $ Alert http.Head(tainted) // OK - http.Post(tainted, "text/basic", nil) // Not OK + http.Post(tainted, "text/basic", nil) // $ Alert client := &http.Client{} - rq, _ := http.NewRequest("GET", tainted, nil) - client.Do(rq) // Not OK + rq, _ := http.NewRequest("GET", tainted, nil) // $ Sink + client.Do(rq) // $ Alert - rq, _ = http.NewRequestWithContext(context.Background(), "GET", tainted, nil) - client.Do(rq) // Not OK + rq, _ = http.NewRequestWithContext(context.Background(), "GET", tainted, nil) // $ Sink + client.Do(rq) // $ Alert - http.Get("http://" + tainted) // Not OK + http.Get("http://" + tainted) // $ Alert - http.Get("http://example.com" + tainted) // Not OK + http.Get("http://example.com" + tainted) // $ Alert http.Get("http://example.com/" + tainted) // OK @@ -34,7 +34,7 @@ func handler2(w http.ResponseWriter, req *http.Request) { u, _ := url.Parse("http://example.com/relative-path") u.Host = tainted - http.Get(u.String()) // Not OK + http.Get(u.String()) // $ Alert } func main() { diff --git a/go/ql/test/query-tests/Security/CWE-918/websocket.go b/go/ql/test/query-tests/Security/CWE-918/websocket.go index fb3882000ff..15edef6b6cc 100644 --- a/go/ql/test/query-tests/Security/CWE-918/websocket.go +++ b/go/ql/test/query-tests/Security/CWE-918/websocket.go @@ -57,12 +57,12 @@ func test() { // x net websocket dial bad http.HandleFunc("/ex2", func(w http.ResponseWriter, r *http.Request) { - untrustedInput := r.Referer() + untrustedInput := r.Referer() // $ Source origin := "http://localhost/" // bad as input is directly passed to dial function - ws, _ := websocket.Dial(untrustedInput, "", origin) + ws, _ := websocket.Dial(untrustedInput, "", origin) // $ Alert var msg = make([]byte, 512) var n int n, _ = ws.Read(msg) @@ -71,12 +71,12 @@ func test() { // x net websocket dialConfig bad http.HandleFunc("/ex3", func(w http.ResponseWriter, r *http.Request) { - untrustedInput := r.Referer() + untrustedInput := r.Referer() // $ Source origin := "http://localhost/" // bad as input is directly used - config, _ := websocket.NewConfig(untrustedInput, origin) // good - ws2, _ := websocket.DialConfig(config) + config, _ := websocket.NewConfig(untrustedInput, origin) // $ Sink + ws2, _ := websocket.DialConfig(config) // $ Alert var msg = make([]byte, 512) var n int n, _ = ws2.Read(msg) @@ -85,10 +85,10 @@ func test() { // nhooyr websocket dial bad http.HandleFunc("/ex4", func(w http.ResponseWriter, r *http.Request) { - untrustedInput := r.Referer() + untrustedInput := r.Referer() // $ Source // bad as input is used directly - nhooyr.Dial(context.TODO(), untrustedInput, nil) + nhooyr.Dial(context.TODO(), untrustedInput, nil) // $ Alert w.WriteHeader(500) }) @@ -104,10 +104,10 @@ func test() { // gorilla websocket Dialer.Dial bad http.HandleFunc("/ex6", func(w http.ResponseWriter, r *http.Request) { - untrustedInput := r.Referer() + untrustedInput := r.Referer() // $ Source dialer := gorilla.Dialer{} - dialer.Dial(untrustedInput, r.Header) + dialer.Dial(untrustedInput, r.Header) // $ Alert }) // gorilla websocket Dialer.Dial good @@ -123,10 +123,10 @@ func test() { // gorilla websocket Dialer.DialContext bad http.HandleFunc("/ex8", func(w http.ResponseWriter, r *http.Request) { - untrustedInput := r.Referer() + untrustedInput := r.Referer() // $ Source dialer := gorilla.Dialer{} - dialer.DialContext(context.TODO(), untrustedInput, r.Header) + dialer.DialContext(context.TODO(), untrustedInput, r.Header) // $ Alert }) // gorilla websocket Dialer.DialContext good @@ -151,15 +151,15 @@ func test() { // gobwas websocket Dial bad http.HandleFunc("/ex11", func(w http.ResponseWriter, r *http.Request) { - untrustedInput := r.Referer() - gobwas.Dial(context.TODO(), untrustedInput) + untrustedInput := r.Referer() // $ Source + gobwas.Dial(context.TODO(), untrustedInput) // $ Alert }) // gobwas websocket Dialer.Dial bad http.HandleFunc("/ex12", func(w http.ResponseWriter, r *http.Request) { - untrustedInput := r.Referer() + untrustedInput := r.Referer() // $ Source dialer := gobwas.Dialer{} - dialer.Dial(context.TODO(), untrustedInput) + dialer.Dial(context.TODO(), untrustedInput) // $ Alert }) // gobwas websocket Dialer.Dial good @@ -192,16 +192,16 @@ func test() { // sac007 websocket BuildProxy bad http.HandleFunc("/ex15", func(w http.ResponseWriter, r *http.Request) { - untrustedInput := r.Referer() + untrustedInput := r.Referer() // $ Source - _ = sac.BuildProxy(untrustedInput) + _ = sac.BuildProxy(untrustedInput) // $ Alert }) // sac007 websocket New bad http.HandleFunc("/ex16", func(w http.ResponseWriter, r *http.Request) { - untrustedInput := r.Referer() + untrustedInput := r.Referer() // $ Source - _ = sac.New(untrustedInput) + _ = sac.New(untrustedInput) // $ Alert }) log.Println(http.ListenAndServe(":80", nil)) From a486549956ce75a7a1a1df56f14849820123c634 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 7 Jul 2025 14:01:00 +0100 Subject: [PATCH 027/199] Update rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml Co-authored-by: Arthur Baars --- rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml b/rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml index d5e91afa663..ae58b2a077a 100644 --- a/rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/tokio/io.model.yml @@ -14,7 +14,7 @@ extensions: - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_exact ", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["<_ as tokio::io::util::async_read_ext::AsyncReadExt>::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - ["<_ as tokio::io::util::async_buf_read_ext::AsyncBufReadExt>::read_line", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - ["<_ as tokio::io::util::async_buf_read_ext::AsyncBufReadExt>::read_until", "Argument[self]", "Argument[1].Reference", "taint", "manual"] - ["<_ as tokio::io::util::async_buf_read_ext::AsyncBufReadExt>::split", "Argument[self]", "ReturnValue", "taint", "manual"] From a25330e6ed15ca68e14ab087e7d56a4d44cee535 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 7 Jul 2025 15:10:59 +0100 Subject: [PATCH 028/199] Rust: Update rustcrypto models. --- .../rust/frameworks/rustcrypto/rustcrypto.model.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/rustcrypto/rustcrypto.model.yml b/rust/ql/lib/codeql/rust/frameworks/rustcrypto/rustcrypto.model.yml index d1aefe5b983..f29973e377c 100644 --- a/rust/ql/lib/codeql/rust/frameworks/rustcrypto/rustcrypto.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/rustcrypto/rustcrypto.model.yml @@ -3,8 +3,8 @@ extensions: pack: codeql/rust-all extensible: sinkModel data: - - ["::new_with_prefix", "Argument[0]", "hasher-input", "manual"] - - ["::update", "Argument[0]", "hasher-input", "manual"] - - ["::chain_update", "Argument[0]", "hasher-input", "manual"] - - ["::digest", "Argument[0]", "hasher-input", "manual"] + - ["<_ as digest::digest::Digest>::new_with_prefix::new_with_prefix", "Argument[0]", "hasher-input", "manual"] + - ["<_ as digest::digest::Digest>::new_with_prefix::update", "Argument[0]", "hasher-input", "manual"] + - ["<_ as digest::digest::Digest>::new_with_prefix::chain_update", "Argument[0]", "hasher-input", "manual"] + - ["<_ as digest::digest::Digest>::new_with_prefix::digest", "Argument[0]", "hasher-input", "manual"] - ["md5::compute", "Argument[0]", "hasher-input", "manual"] From a1e9a4eddfd0263916b579668c9c35a3eeb9bbe3 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 3 Jul 2025 15:52:48 +0100 Subject: [PATCH 029/199] Rust: Accept test .expected changes. --- .../dataflow/global/inline-flow.expected | 2 +- .../dataflow/sources/TaintSources.expected | 1 - .../library-tests/dataflow/sources/test.rs | 2 +- .../dataflow/sources/test_futures_io.rs | 28 +-- .../UncontrolledAllocationSize.expected | 201 ++++++++---------- .../test/query-tests/security/CWE-770/main.rs | 10 +- .../CWE-825/AccessInvalidPointer.expected | 7 - .../security/CWE-825/deallocation.rs | 4 +- 8 files changed, 107 insertions(+), 148 deletions(-) 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 da5840528f5..30b39421ac2 100644 --- a/rust/ql/test/library-tests/dataflow/global/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/global/inline-flow.expected @@ -1,5 +1,5 @@ models -| 1 | Summary: repo:https://github.com/rust-lang/futures-rs:futures-executor; crate::local_pool::block_on; Argument[0]; ReturnValue; value | +| 1 | Summary: futures_executor::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 | | diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected index 4d95b9bb61b..0e170f5f44c 100644 --- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -75,7 +75,6 @@ | test.rs:779:22:779:50 | ...::new | Flow source 'RemoteSource' of type remote (DEFAULT). | | test.rs:806:16:806:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | | test.rs:806:16:806:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | -| test_futures_io.rs:19:15:19:32 | ...::connect | Flow source 'RemoteSource' of type remote (DEFAULT). | | web_frameworks.rs:11:31:11:31 | a | Flow source 'RemoteSource' of type remote (DEFAULT). | | web_frameworks.rs:11:31:11:31 | a | Flow source 'RemoteSource' of type remote (DEFAULT). | | web_frameworks.rs:22:14:22:18 | TuplePat | Flow source 'RemoteSource' of type remote (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index f0154c57014..0ee8ac2e45b 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -214,7 +214,7 @@ fn test_io_stdin() -> std::io::Result<()> { { let mut buffer = Vec::::new(); let _bytes = std::io::stdin().read_to_end(&mut buffer)?; // $ Alert[rust/summary/taint-sources] - sink(&buffer); // $ hasTaintFlow -- @hvitved: works in CI, but not for me locally + sink(&buffer); // $ MISSING: hasTaintFlow } { diff --git a/rust/ql/test/library-tests/dataflow/sources/test_futures_io.rs b/rust/ql/test/library-tests/dataflow/sources/test_futures_io.rs index 67dce4b21cc..4cff19432a4 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test_futures_io.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test_futures_io.rs @@ -16,21 +16,21 @@ use std::task::{Context, Poll}; async fn test_futures_rustls_futures_io() -> io::Result<()> { let url = "www.example.com:443"; - let tcp = TcpStream::connect(url).await?; // $ Alert[rust/summary/taint-sources] - sink(&tcp); // $ hasTaintFlow=url + let tcp = TcpStream::connect(url).await?; // $ MISSING: Alert[rust/summary/taint-sources] + sink(&tcp); // $ MISSING: hasTaintFlow=url let config = rustls::ClientConfig::builder() .with_root_certificates(rustls::RootCertStore::empty()) .with_no_client_auth(); let connector = TlsConnector::from(Arc::new(config)); let server_name = rustls::pki_types::ServerName::try_from("www.example.com").unwrap(); let mut reader = connector.connect(server_name, tcp).await?; - sink(&reader); // $ hasTaintFlow=url + sink(&reader); // $ MISSING: hasTaintFlow=url { // using the `AsyncRead` trait (low-level) let mut buffer = [0u8; 64]; let mut pinned = Pin::new(&mut reader); - sink(&pinned); // $ hasTaintFlow=url + sink(&pinned); // $ MISSING: hasTaintFlow=url let mut cx = Context::from_waker(futures::task::noop_waker_ref()); let bytes_read = pinned.poll_read(&mut cx, &mut buffer); // we cannot correctly resolve this call, since it relies on `Deref` if let Poll::Ready(Ok(n)) = bytes_read { @@ -43,7 +43,7 @@ async fn test_futures_rustls_futures_io() -> io::Result<()> { // using the `AsyncReadExt::read` extension method (higher-level) let mut buffer1 = [0u8; 64]; let bytes_read1 = futures::io::AsyncReadExt::read(&mut reader, &mut buffer1).await?; - sink(&buffer1[..bytes_read1]); // $ hasTaintFlow=url + sink(&buffer1[..bytes_read1]); // $ MISSING: hasTaintFlow=url let mut buffer2 = [0u8; 64]; let bytes_read2 = reader.read(&mut buffer2).await?; // we cannot resolve the `read` call, which comes from `impl AsyncReadExt for R {}` in `async_read_ext.rs` @@ -52,16 +52,16 @@ async fn test_futures_rustls_futures_io() -> io::Result<()> { } let mut reader2 = futures::io::BufReader::new(reader); - sink(&reader2); // $ hasTaintFlow=url + sink(&reader2); // $ MISSING: hasTaintFlow=url { // using the `AsyncBufRead` trait (low-level) let mut pinned = Pin::new(&mut reader2); - sink(&pinned); // $ hasTaintFlow=url + sink(&pinned); // $ MISSING: hasTaintFlow=url let mut cx = Context::from_waker(futures::task::noop_waker_ref()); let buffer = pinned.poll_fill_buf(&mut cx); if let Poll::Ready(Ok(buf)) = buffer { - sink(&buffer); // $ hasTaintFlow=url + sink(&buffer); // $ MISSING: hasTaintFlow=url sink(buf); // $ MISSING: hasTaintFlow=url } @@ -69,8 +69,8 @@ async fn test_futures_rustls_futures_io() -> io::Result<()> { let buffer2 = Pin::new(&mut reader2).poll_fill_buf(&mut cx); match (buffer2) { Poll::Ready(Ok(buf)) => { - sink(&buffer2); // $ hasTaintFlow=url - sink(buf); // $ hasTaintFlow=url + sink(&buffer2); // $ MISSING: hasTaintFlow=url + sink(buf); // $ MISSING: hasTaintFlow=url } _ => { // ... @@ -88,7 +88,7 @@ async fn test_futures_rustls_futures_io() -> io::Result<()> { // using the `AsyncRead` trait (low-level) let mut buffer = [0u8; 64]; let mut pinned = Pin::new(&mut reader2); - sink(&pinned); // $ hasTaintFlow=url + sink(&pinned); // $ MISSING: hasTaintFlow=url let mut cx = Context::from_waker(futures::task::noop_waker_ref()); let bytes_read = pinned.poll_read(&mut cx, &mut buffer); sink(&buffer); // $ MISSING: hasTaintFlow=url @@ -101,7 +101,7 @@ async fn test_futures_rustls_futures_io() -> io::Result<()> { // using the `AsyncReadExt::read` extension method (higher-level) let mut buffer1 = [0u8; 64]; let bytes_read1 = futures::io::AsyncReadExt::read(&mut reader2, &mut buffer1).await?; - sink(&buffer1[..bytes_read1]); // $ hasTaintFlow=url + sink(&buffer1[..bytes_read1]); // $ MISSING: hasTaintFlow=url let mut buffer2 = [0u8; 64]; let bytes_read2 = reader2.read(&mut buffer2).await?; // we cannot resolve the `read` call, which comes from `impl AsyncReadExt for R {}` in `async_read_ext.rs` @@ -111,10 +111,10 @@ async fn test_futures_rustls_futures_io() -> io::Result<()> { { // using the `AsyncBufRead` trait (low-level) let mut pinned = Pin::new(&mut reader2); - sink(&pinned); // $ hasTaintFlow=url + sink(&pinned); // $ MISSING: hasTaintFlow=url let mut cx = Context::from_waker(futures::task::noop_waker_ref()); let buffer = pinned.poll_fill_buf(&mut cx); - sink(&buffer); // $ hasTaintFlow=url + sink(&buffer); // $ MISSING: hasTaintFlow=url if let Poll::Ready(Ok(buf)) = buffer { sink(buf); // $ MISSING: hasTaintFlow=url } 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 9dfda11b524..3eafac92b13 100644 --- a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected +++ b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected @@ -49,11 +49,6 @@ | 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: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:213:36:213:41 | shrink | main.rs:317:13:317:26 | ...::args | main.rs:213:36:213:41 | shrink | 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: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: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:230:13:230:44 | ...::try_with_capacity_in | main.rs:317:13:317:26 | ...::args | main.rs:230:13:230:44 | ...::try_with_capacity_in | 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:231:13:231:40 | ...::with_capacity_in | main.rs:317:13:317:26 | ...::args | main.rs:231:13:231:40 | ...::with_capacity_in | 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 | @@ -67,43 +62,43 @@ edges | main.rs:18:41:18:41 | v | main.rs:35:9:35:10 | s6 | provenance | | | main.rs:18:41:18:41 | v | main.rs:35:49:35:49 | v | 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:35 | +| 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:44 | +| main.rs:20:50:20:50 | v | main.rs:20:14:20:54 | ...::from_size_align(...) [Ok] | provenance | MaD:40 | | main.rs:21:31:21:32 | l2 | main.rs:21:13:21:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | -| main.rs:21:31:21:32 | l2 | main.rs:22:31:22:44 | l2.align_to(...) [Ok] | provenance | MaD:40 | -| main.rs:21:31:21:32 | l2 | main.rs:23:31:23:44 | l2.align_to(...) [Ok] | provenance | MaD:40 | +| main.rs:21:31:21:32 | l2 | main.rs:22:31:22:44 | l2.align_to(...) [Ok] | provenance | MaD:36 | +| main.rs:21:31:21:32 | l2 | main.rs:23:31:23:44 | l2.align_to(...) [Ok] | provenance | MaD:36 | | 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:35 | +| 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:17 Sink:MaD:17 | -| main.rs:23:31:23:44 | l2.align_to(...) [Ok] | main.rs:23:31:23:53 | ... .unwrap() | provenance | MaD:35 | -| main.rs:23:31:23:53 | ... .unwrap() | main.rs:23:31:23:68 | ... .pad_to_align() | provenance | MaD:46 | +| 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:42 | | main.rs:23:31:23:68 | ... .pad_to_align() | main.rs:23:13:23:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | main.rs:24:38:24:39 | l2 | main.rs:24:13:24:36 | ...::alloc_zeroed | provenance | MaD:18 Sink:MaD:18 | | 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:45 | +| main.rs:29:60:29:60 | v | main.rs:29:14:29:64 | ...::from_size_align_unchecked(...) | provenance | MaD:41 | | main.rs:30:31:30:32 | l4 | main.rs:30:13:30:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | 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:60 | v | main.rs:32:60:32:89 | ... * ... | provenance | MaD:37 | -| main.rs:32:60:32:89 | ... * ... | main.rs:32:14:32:118 | ...::from_size_align_unchecked(...) | provenance | MaD:45 | +| main.rs:32:60:32:60 | v | main.rs:32:60:32:89 | ... * ... | provenance | MaD:33 | +| main.rs:32:60:32:89 | ... * ... | main.rs:32:14:32:118 | ...::from_size_align_unchecked(...) | provenance | MaD:41 | | main.rs:33:31:33:32 | l5 | main.rs:33:13:33:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | main.rs:35:9:35:10 | s6 | main.rs:36:60:36:61 | s6 | provenance | | | main.rs:35:15:35:49 | ... * ... | main.rs:35:9:35:10 | s6 | provenance | | -| main.rs:35:49:35:49 | v | main.rs:35:15:35:49 | ... * ... | provenance | MaD:36 | +| main.rs:35:49:35:49 | v | main.rs:35:15:35:49 | ... * ... | provenance | MaD:32 | | main.rs:36:9:36:10 | l6 | main.rs:37:31:37:32 | l6 | provenance | | | main.rs:36:9:36:10 | l6 [Layout.size] | main.rs:37:31:37:32 | l6 [Layout.size] | provenance | | | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | main.rs:36:9:36:10 | l6 | provenance | | | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) [Layout.size] | main.rs:36:9:36:10 | l6 [Layout.size] | provenance | | -| main.rs:36:60:36:61 | s6 | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | provenance | MaD:45 | -| main.rs:36:60:36:61 | s6 | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) [Layout.size] | provenance | MaD:31 | +| main.rs:36:60:36:61 | s6 | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | provenance | MaD:41 | +| main.rs:36:60:36:61 | s6 | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) [Layout.size] | provenance | MaD:27 | | main.rs:37:31:37:32 | l6 | main.rs:37:13:37:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | -| main.rs:37:31:37:32 | l6 | main.rs:39:60:39:68 | l6.size() | provenance | MaD:49 | -| main.rs:37:31:37:32 | l6 [Layout.size] | main.rs:39:60:39:68 | l6.size() | provenance | MaD:32 | +| main.rs:37:31:37:32 | l6 | main.rs:39:60:39:68 | l6.size() | provenance | MaD:45 | +| main.rs:37:31:37:32 | l6 [Layout.size] | 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:45 | +| main.rs:39:60:39:68 | l6.size() | main.rs:39:14:39:72 | ...::from_size_align_unchecked(...) | provenance | MaD:41 | | main.rs:40:31:40:32 | l7 | main.rs:40:13:40:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | 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 | | @@ -111,47 +106,47 @@ edges | 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:35 | +| 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:17 Sink:MaD:17 | -| main.rs:50:41:50:41 | v | main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:47 | -| main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | main.rs:51:31:51:55 | ... .unwrap() [tuple.0] | provenance | MaD:35 | +| main.rs:50:41:50:41 | v | main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:43 | +| 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:17 Sink:MaD:17 | -| main.rs:51:41:51:45 | ... + ... | main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:47 | -| main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | main.rs:53:31:53:58 | ... .unwrap() | provenance | MaD:35 | +| main.rs:51:41:51:45 | ... + ... | main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:43 | +| 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:17 Sink:MaD:17 | -| main.rs:53:48:53:48 | v | main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | provenance | MaD:48 | -| main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | main.rs:54:31:54:63 | ... .unwrap() | provenance | MaD:35 | +| main.rs:53:48:53:48 | v | main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | provenance | MaD:44 | +| 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:17 Sink:MaD:17 | -| main.rs:54:48:54:53 | ... * ... | main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | provenance | MaD:48 | +| main.rs:54:48:54:53 | ... * ... | main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | provenance | MaD:44 | | 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:34 | +| 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:47 | +| main.rs:58:34:58:34 | v | main.rs:58:24:58:35 | l3.repeat(...) [Ok, tuple.0] | provenance | MaD:43 | | main.rs:59:31:59:32 | k1 | main.rs:59:13:59:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | main.rs:59:31:59:32 | k1 | main.rs:60:34:60:35 | k1 | provenance | | | main.rs:59:31:59:32 | k1 | main.rs:64:48:64:49 | k1 | provenance | | | 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:35 | +| 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:42 | +| main.rs:60:34:60:35 | k1 | main.rs:60:24:60:36 | l3.extend(...) [Ok, tuple.0] | provenance | MaD:38 | | main.rs:61:31:61:32 | k2 | main.rs:61:13:61:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | -| main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | main.rs:64:31:64:59 | ... .unwrap() | provenance | MaD:35 | +| 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:17 Sink:MaD:17 | -| main.rs:64:48:64:49 | k1 | main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | provenance | MaD:43 | +| main.rs:64:48:64:49 | k1 | main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | provenance | MaD:39 | | 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:35 | +| 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:41 | +| main.rs:67:46:67:46 | v | main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | provenance | MaD:37 | | main.rs:68:31:68:32 | l4 | main.rs:68:13:68:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | 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:35 | +| 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:44 | +| main.rs:87:54:87:54 | v | main.rs:87:18:87:58 | ...::from_size_align(...) [Ok] | provenance | MaD:40 | | main.rs:88:31:88:36 | layout | main.rs:88:13:88:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | main.rs:91:38:91:45 | ...: usize | main.rs:92:47:92:47 | v | provenance | | | main.rs:91:38:91:45 | ...: usize | main.rs:101:51:101:51 | v | provenance | | @@ -162,16 +157,16 @@ edges | main.rs:91:38:91:45 | ...: usize | main.rs:161:55:161:55 | 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:35 | +| 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:41 | +| main.rs:92:47:92:47 | v | main.rs:92:14:92:48 | ...::array::<...>(...) [Ok] | provenance | MaD:37 | | main.rs:96:35:96:36 | l1 | main.rs:96:17:96:33 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | 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: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:35 | +| 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:41 | +| main.rs:101:51:101:51 | v | main.rs:101:18:101:52 | ...::array::<...>(...) [Ok] | provenance | MaD:37 | | main.rs:102:35:102:36 | l1 | main.rs:102:17:102:33 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | 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 | | @@ -182,28 +177,28 @@ edges | main.rs:111:35:111:36 | l1 | main.rs:111:17:111:33 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | main.rs:111:35:111:36 | l1 | main.rs:146:35:146:36 | l1 | provenance | | | 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:35 | +| 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:41 | +| main.rs:145:51:145:51 | v | main.rs:145:18:145:52 | ...::array::<...>(...) [Ok] | provenance | MaD:37 | | main.rs:146:35:146:36 | l1 | main.rs:146:17:146:33 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | main.rs:146:35:146:36 | l1 | main.rs:177:31:177:32 | l1 | provenance | | | main.rs:148:35:148:36 | l9 | main.rs:148:17:148:33 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | 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:35 | +| 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:41 | -| main.rs:151:62:151:62 | v | main.rs:151:48:151:68 | ...::min(...) | provenance | MaD:39 | +| main.rs:151:48:151:68 | ...::min(...) | main.rs:151:15:151:69 | ...::array::<...>(...) [Ok] | provenance | MaD:37 | +| main.rs:151:62:151:62 | v | main.rs:151:48:151:68 | ...::min(...) | provenance | MaD:35 | | main.rs:152:31:152:33 | l10 | main.rs:152:13:152:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | 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:35 | +| 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:41 | -| main.rs:154:62:154:62 | v | main.rs:154:48:154:68 | ...::max(...) | provenance | MaD:38 | +| main.rs:154:48:154:68 | ...::max(...) | main.rs:154:15:154:69 | ...::array::<...>(...) [Ok] | provenance | MaD:37 | +| main.rs:154:62:154:62 | v | main.rs:154:48:154:68 | ...::max(...) | provenance | MaD:34 | | main.rs:155:31:155:33 | l11 | main.rs:155:13:155:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | 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:35 | +| 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:44 | +| main.rs:161:55:161:55 | v | main.rs:161:19:161:59 | ...::from_size_align(...) [Ok] | provenance | MaD:40 | | main.rs:162:35:162:37 | l13 | main.rs:162:17:162:33 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | main.rs:162:35:162:37 | l13 | main.rs:169:35:169:37 | l13 | provenance | | | main.rs:169:35:169:37 | l13 | main.rs:169:17:169:33 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | @@ -211,9 +206,9 @@ edges | main.rs:183:29:183:36 | ...: usize | main.rs:192:46:192:46 | v | provenance | | | main.rs:183:29:183:36 | ...: usize | main.rs:202:48:202:48 | 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:35 | +| 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:41 | +| main.rs:192:46:192:46 | v | main.rs:192:14:192:47 | ...::array::<...>(...) [Ok] | provenance | MaD:37 | | main.rs:193:38:193:39 | l2 | main.rs:193:32:193:36 | alloc | provenance | MaD:24 Sink:MaD:24 | | 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 | | @@ -242,52 +237,40 @@ edges | main.rs:210:60:210:61 | l2 | main.rs:210:40:210:50 | grow_zeroed | provenance | MaD:23 Sink:MaD:23 | | main.rs:210:60:210:61 | l2 | main.rs:210:40:210:50 | grow_zeroed | provenance | MaD:8 Sink:MaD:8 | | main.rs:213:51:213:52 | l2 | main.rs:213:36:213:41 | shrink | 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:28 Sink:MaD:28 | -| 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:26 Sink:MaD:26 | -| 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:27 Sink:MaD:27 | -| 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:27 Sink:MaD:27 | -| 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:29 Sink:MaD:29 | | main.rs:227:24:227:31 | ...: usize | main.rs:230:46:230:46 | v | provenance | | | main.rs:230:46:230:46 | v | main.rs:230:13:230:44 | ...::try_with_capacity_in | provenance | MaD:3 Sink:MaD:3 | | main.rs:230:46:230:46 | v | main.rs:231:42:231:42 | v | provenance | | | main.rs:231:42:231:42 | v | main.rs:231:13:231:40 | ...::with_capacity_in | provenance | MaD:4 Sink:MaD:4 | -| main.rs:279:24:279:41 | ...: String | main.rs:280:21:280:47 | user_input.parse() [Ok] | provenance | MaD:50 | +| main.rs:279:24:279:41 | ...: String | main.rs:280:21:280:47 | user_input.parse() [Ok] | provenance | MaD:46 | | 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:280:21:280:48 | TryExpr | main.rs:280:21:280:77 | ... * ... | provenance | MaD:37 | +| main.rs:280:21:280:48 | TryExpr | main.rs:280:21:280:77 | ... * ... | provenance | MaD:33 | | main.rs:280:21:280:77 | ... * ... | 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:35 | +| 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:44 | +| main.rs:282:54:282:62 | num_bytes | main.rs:282:18:282:66 | ...::from_size_align(...) [Ok] | provenance | MaD:40 | | main.rs:284:40:284:45 | layout | main.rs:284:22:284:38 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | -| main.rs:308:25:308:38 | ...::args | main.rs:308:25:308:40 | ...::args(...) [element] | provenance | Src:MaD:30 | -| main.rs:308:25:308:40 | ...::args(...) [element] | main.rs:308:25:308:47 | ... .nth(...) [Some] | provenance | MaD:51 | -| main.rs:308:25:308:47 | ... .nth(...) [Some] | main.rs:308:25:308:74 | ... .unwrap_or(...) | provenance | MaD:33 | +| main.rs:308:25:308:38 | ...::args | main.rs:308:25:308:40 | ...::args(...) [element] | provenance | Src:MaD:26 | +| main.rs:308:25:308:40 | ...::args(...) [element] | main.rs:308:25:308:47 | ... .nth(...) [Some] | provenance | MaD:47 | +| 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: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:9:317:9 | v | main.rs:325:22:325:22 | v | provenance | | -| main.rs:317:13:317:26 | ...::args | main.rs:317:13:317:28 | ...::args(...) [element] | provenance | Src:MaD:30 | -| main.rs:317:13:317:28 | ...::args(...) [element] | main.rs:317:13:317:35 | ... .nth(...) [Some] | provenance | MaD:51 | -| main.rs:317:13:317:35 | ... .nth(...) [Some] | main.rs:317:13:317:65 | ... .unwrap_or(...) | provenance | MaD:33 | -| main.rs:317:13:317:65 | ... .unwrap_or(...) | main.rs:317:13:317:82 | ... .parse() [Ok] | provenance | MaD:50 | -| main.rs:317:13:317:82 | ... .parse() [Ok] | main.rs:317:13:317:91 | ... .unwrap() | provenance | MaD:35 | +| main.rs:317:13:317:26 | ...::args | main.rs:317:13:317:28 | ...::args(...) [element] | provenance | Src:MaD:26 | +| main.rs:317:13:317:28 | ...::args(...) [element] | main.rs:317:13:317:35 | ... .nth(...) [Some] | provenance | MaD:47 | +| 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:46 | +| 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 | | | main.rs:325:22:325:22 | v | main.rs:227:24:227:31 | ...: usize | provenance | | models | 1 | Sink: ::allocate; Argument[0]; alloc-layout | @@ -315,32 +298,28 @@ models | 23 | Sink: lang:std; ::grow_zeroed; Argument[2]; alloc-layout | | 24 | Sink: lang:std; ::alloc; Argument[0]; alloc-layout | | 25 | Sink: lang:std; ::alloc_zeroed; Argument[0]; alloc-layout | -| 26 | Sink: repo:https://github.com/rust-lang/libc:libc; ::aligned_alloc; Argument[1]; alloc-size | -| 27 | Sink: repo:https://github.com/rust-lang/libc:libc; ::calloc; Argument[0,1]; alloc-size | -| 28 | Sink: repo:https://github.com/rust-lang/libc:libc; ::malloc; Argument[0]; alloc-size | -| 29 | Sink: repo:https://github.com/rust-lang/libc:libc; ::realloc; Argument[1]; alloc-size | -| 30 | Source: std::env::args; ReturnValue.Element; commandargs | -| 31 | Summary: ::from_size_align_unchecked; Argument[0]; ReturnValue.Field[core::alloc::layout::Layout::size]; value | -| 32 | Summary: ::size; Argument[self].Field[core::alloc::layout::Layout::size]; ReturnValue; value | -| 33 | Summary: ::unwrap_or; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value | -| 34 | Summary: ::expect; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value | -| 35 | Summary: ::unwrap; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value | -| 36 | Summary: ::mul; Argument[0]; ReturnValue; taint | -| 37 | Summary: ::mul; Argument[self]; ReturnValue; taint | -| 38 | Summary: core::cmp::max; Argument[0]; ReturnValue; value | -| 39 | Summary: core::cmp::min; Argument[0]; ReturnValue; value | -| 40 | Summary: lang:core; ::align_to; Argument[self]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | -| 41 | Summary: lang:core; ::array; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | -| 42 | Summary: lang:core; ::extend; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)].Field[0]; taint | -| 43 | Summary: lang:core; ::extend_packed; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | -| 44 | Summary: lang:core; ::from_size_align; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | -| 45 | Summary: lang:core; ::from_size_align_unchecked; Argument[0]; ReturnValue; taint | -| 46 | Summary: lang:core; ::pad_to_align; Argument[self]; ReturnValue; taint | -| 47 | Summary: lang:core; ::repeat; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)].Field[0]; taint | -| 48 | Summary: lang:core; ::repeat_packed; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | -| 49 | Summary: lang:core; ::size; Argument[self]; ReturnValue; taint | -| 50 | Summary: lang:core; ::parse; Argument[self]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | -| 51 | Summary: lang:core; crate::iter::traits::iterator::Iterator::nth; Argument[self].Element; ReturnValue.Field[core::option::Option::Some(0)]; value | +| 26 | Source: std::env::args; ReturnValue.Element; commandargs | +| 27 | Summary: ::from_size_align_unchecked; Argument[0]; ReturnValue.Field[core::alloc::layout::Layout::size]; value | +| 28 | Summary: ::size; Argument[self].Field[core::alloc::layout::Layout::size]; ReturnValue; value | +| 29 | Summary: ::unwrap_or; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value | +| 30 | Summary: ::expect; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value | +| 31 | Summary: ::unwrap; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value | +| 32 | Summary: ::mul; Argument[0]; ReturnValue; taint | +| 33 | Summary: ::mul; Argument[self]; ReturnValue; taint | +| 34 | Summary: core::cmp::max; Argument[0]; ReturnValue; value | +| 35 | Summary: core::cmp::min; Argument[0]; ReturnValue; value | +| 36 | Summary: lang:core; ::align_to; Argument[self]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | +| 37 | Summary: lang:core; ::array; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | +| 38 | Summary: lang:core; ::extend; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)].Field[0]; taint | +| 39 | Summary: lang:core; ::extend_packed; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | +| 40 | Summary: lang:core; ::from_size_align; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | +| 41 | Summary: lang:core; ::from_size_align_unchecked; Argument[0]; ReturnValue; taint | +| 42 | Summary: lang:core; ::pad_to_align; Argument[self]; ReturnValue; taint | +| 43 | Summary: lang:core; ::repeat; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)].Field[0]; taint | +| 44 | Summary: lang:core; ::repeat_packed; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | +| 45 | Summary: lang:core; ::size; Argument[self]; ReturnValue; taint | +| 46 | Summary: lang:core; ::parse; Argument[self]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | +| 47 | Summary: lang:core; crate::iter::traits::iterator::Iterator::nth; Argument[self].Element; ReturnValue.Field[core::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 | @@ -524,17 +503,6 @@ nodes | main.rs:210:60:210:61 | l2 | semmle.label | l2 | | main.rs:213:36:213:41 | shrink | semmle.label | shrink | | main.rs:213:51:213:52 | 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:26:219:26 | v | semmle.label | v | -| 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:30:222:30 | v | semmle.label | v | -| 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:31:224:31 | v | semmle.label | v | | main.rs:227:24:227:31 | ...: usize | semmle.label | ...: usize | | main.rs:230:13:230:44 | ...::try_with_capacity_in | semmle.label | ...::try_with_capacity_in | | main.rs:230:46:230:46 | v | semmle.label | v | @@ -566,6 +534,5 @@ nodes | 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 | | main.rs:325:22:325:22 | v | semmle.label | v | subpaths 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 0b39862ef32..d71f7bd0e39 100644 --- a/rust/ql/test/query-tests/security/CWE-770/main.rs +++ b/rust/ql/test/query-tests/security/CWE-770/main.rs @@ -216,12 +216,12 @@ unsafe fn test_system_alloc(v: usize) { unsafe fn test_libc_alloc(v: usize) { let m1 = libc::malloc(256); - let _ = libc::malloc(v); // $ Alert[rust/uncontrolled-allocation-size]=arg1 - let _ = libc::aligned_alloc(8, v); // $ Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = libc::malloc(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = libc::aligned_alloc(8, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]=arg1 let _ = libc::aligned_alloc(v, 8); - 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 + let _ = libc::calloc(64, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = libc::calloc(v, std::mem::size_of::()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]=arg1 + let _ = libc::realloc(m1, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]=arg1 } unsafe fn test_vectors(v: usize) { 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 f0c67e6f5d8..399c8f76316 100644 --- a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected +++ b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected @@ -8,7 +8,6 @@ | deallocation.rs:86:7:86:8 | m2 | deallocation.rs:70:3:70:21 | ...::dealloc | deallocation.rs:86:7:86:8 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:70:3:70:21 | ...::dealloc | invalid | | deallocation.rs:90:7:90:8 | m2 | deallocation.rs:70:3:70:21 | ...::dealloc | deallocation.rs:90:7:90:8 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:70:3:70:21 | ...::dealloc | invalid | | deallocation.rs:95:5:95:31 | ...::write::<...> | deallocation.rs:70:3:70:21 | ...::dealloc | deallocation.rs:95:5:95:31 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:70:3:70:21 | ...::dealloc | invalid | -| deallocation.rs:115:13:115:18 | my_ptr | deallocation.rs:112:3:112:12 | ...::free | deallocation.rs:115:13:115:18 | my_ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:112:3:112:12 | ...::free | 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: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 | @@ -32,8 +31,6 @@ edges | deallocation.rs:70:23:70:35 | [post] m2 as ... | deallocation.rs:90:7:90:8 | m2 | provenance | | | deallocation.rs:70:23:70:35 | [post] m2 as ... | 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:3:112:12 | ...::free | deallocation.rs:112:14:112:40 | [post] my_ptr as ... | provenance | Src:MaD:10 MaD:10 | -| deallocation.rs:112:14:112:40 | [post] my_ptr as ... | 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:6 MaD:6 | | deallocation.rs:123:23:123:40 | ...::dangling | deallocation.rs:123:23:123:42 | ...::dangling(...) | provenance | Src:MaD:3 MaD:3 | @@ -60,7 +57,6 @@ models | 7 | Source: lang:core; crate::ptr::dangling_mut; ReturnValue; pointer-invalidate | | 8 | Source: lang:core; crate::ptr::drop_in_place; Argument[0]; pointer-invalidate | | 9 | Source: lang:core; crate::ptr::null; ReturnValue; pointer-invalidate | -| 10 | Source: repo:https://github.com/rust-lang/libc:libc; ::free; Argument[0]; pointer-invalidate | nodes | deallocation.rs:20:3:20:21 | ...::dealloc | semmle.label | ...::dealloc | | deallocation.rs:20:23:20:24 | [post] m1 | semmle.label | [post] m1 | @@ -78,9 +74,6 @@ nodes | 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:3:112:12 | ...::free | semmle.label | ...::free | -| deallocation.rs:112:14:112:40 | [post] my_ptr as ... | semmle.label | [post] my_ptr as ... | -| 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:40 | ...::dangling | semmle.label | ...::dangling | 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 89ef0470e99..0d8f977387b 100644 --- a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs +++ b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs @@ -109,10 +109,10 @@ pub fn test_libc() { let v1 = *my_ptr; // GOOD println!(" v1 = {v1}"); - libc::free(my_ptr as *mut libc::c_void); // $ Source[rust/access-invalid-pointer]=free + libc::free(my_ptr as *mut libc::c_void); // $ MISSING: Source[rust/access-invalid-pointer]=free // (my_ptr is now dangling) - let v2 = *my_ptr; // $ Alert[rust/access-invalid-pointer]=free + let v2 = *my_ptr; // $ MISSING: Alert[rust/access-invalid-pointer]=free println!(" v2 = {v2} (!)"); // corrupt in practice } } From c7de873a22216deb2eb652a0eb3a387f903d1a7e Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 7 Jul 2025 18:55:21 +0100 Subject: [PATCH 030/199] Rust: Update the libc models. --- .../lib/codeql/rust/frameworks/libc.model.yml | 15 +- .../UncontrolledAllocationSize.expected | 201 ++++++++++-------- .../test/query-tests/security/CWE-770/main.rs | 10 +- .../CWE-825/AccessInvalidPointer.expected | 7 + .../security/CWE-825/deallocation.rs | 4 +- 5 files changed, 141 insertions(+), 96 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/libc.model.yml b/rust/ql/lib/codeql/rust/frameworks/libc.model.yml index efce0df7ffb..314f1ca0ba9 100644 --- a/rust/ql/lib/codeql/rust/frameworks/libc.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/libc.model.yml @@ -3,12 +3,17 @@ extensions: pack: codeql/rust-all extensible: sourceModel data: - - ["libc::free", "Argument[0]", "pointer-invalidate", "manual"] + - ["libc::unix::free", "Argument[0]", "pointer-invalidate", "manual"] + - ["libc::windows::free", "Argument[0]", "pointer-invalidate", "manual"] - addsTo: pack: codeql/rust-all extensible: sinkModel data: - - ["libc::malloc", "Argument[0]", "alloc-size", "manual"] - - ["libc::aligned_alloc", "Argument[1]", "alloc-size", "manual"] - - ["libc::calloc", "Argument[0,1]", "alloc-size", "manual"] - - ["libc::realloc", "Argument[1]", "alloc-size", "manual"] + - ["libc::unix::malloc", "Argument[0]", "alloc-size", "manual"] + - ["libc::windows::malloc", "Argument[0]", "alloc-size", "manual"] + - ["libc::unix::aligned_alloc", "Argument[1]", "alloc-size", "manual"] + - ["libc::windows::aligned_alloc", "Argument[1]", "alloc-size", "manual"] + - ["libc::unix::calloc", "Argument[0,1]", "alloc-size", "manual"] + - ["libc::windows::calloc", "Argument[0,1]", "alloc-size", "manual"] + - ["libc::unix::realloc", "Argument[1]", "alloc-size", "manual"] + - ["libc::windows::realloc", "Argument[1]", "alloc-size", "manual"] 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 3eafac92b13..5e99e62b9d2 100644 --- a/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected +++ b/rust/ql/test/query-tests/security/CWE-770/UncontrolledAllocationSize.expected @@ -49,6 +49,11 @@ | 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: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:213:36:213:41 | shrink | main.rs:317:13:317:26 | ...::args | main.rs:213:36:213:41 | shrink | 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: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: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:230:13:230:44 | ...::try_with_capacity_in | main.rs:317:13:317:26 | ...::args | main.rs:230:13:230:44 | ...::try_with_capacity_in | 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:231:13:231:40 | ...::with_capacity_in | main.rs:317:13:317:26 | ...::args | main.rs:231:13:231:40 | ...::with_capacity_in | 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 | @@ -62,43 +67,43 @@ edges | main.rs:18:41:18:41 | v | main.rs:35:9:35:10 | s6 | provenance | | | main.rs:18:41:18:41 | v | main.rs:35:49:35:49 | v | 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:31 | +| main.rs:20:14:20:54 | ...::from_size_align(...) [Ok] | main.rs:20:14:20:63 | ... .unwrap() | provenance | MaD:35 | | 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:40 | +| main.rs:20:50:20:50 | v | main.rs:20:14:20:54 | ...::from_size_align(...) [Ok] | provenance | MaD:44 | | main.rs:21:31:21:32 | l2 | main.rs:21:13:21:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | -| main.rs:21:31:21:32 | l2 | main.rs:22:31:22:44 | l2.align_to(...) [Ok] | provenance | MaD:36 | -| main.rs:21:31:21:32 | l2 | main.rs:23:31:23:44 | l2.align_to(...) [Ok] | provenance | MaD:36 | +| main.rs:21:31:21:32 | l2 | main.rs:22:31:22:44 | l2.align_to(...) [Ok] | provenance | MaD:40 | +| main.rs:21:31:21:32 | l2 | main.rs:23:31:23:44 | l2.align_to(...) [Ok] | provenance | MaD:40 | | 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:44 | l2.align_to(...) [Ok] | main.rs:22:31:22:53 | ... .unwrap() | provenance | MaD:35 | | main.rs:22:31:22:53 | ... .unwrap() | main.rs:22:13:22:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | -| 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:42 | +| main.rs:23:31:23:44 | l2.align_to(...) [Ok] | main.rs:23:31:23:53 | ... .unwrap() | provenance | MaD:35 | +| main.rs:23:31:23:53 | ... .unwrap() | main.rs:23:31:23:68 | ... .pad_to_align() | provenance | MaD:46 | | main.rs:23:31:23:68 | ... .pad_to_align() | main.rs:23:13:23:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | main.rs:24:38:24:39 | l2 | main.rs:24:13:24:36 | ...::alloc_zeroed | provenance | MaD:18 Sink:MaD:18 | | 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:41 | +| main.rs:29:60:29:60 | v | main.rs:29:14:29:64 | ...::from_size_align_unchecked(...) | provenance | MaD:45 | | main.rs:30:31:30:32 | l4 | main.rs:30:13:30:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | 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:60 | v | main.rs:32:60:32:89 | ... * ... | provenance | MaD:33 | -| main.rs:32:60:32:89 | ... * ... | main.rs:32:14:32:118 | ...::from_size_align_unchecked(...) | provenance | MaD:41 | +| main.rs:32:60:32:60 | v | main.rs:32:60:32:89 | ... * ... | provenance | MaD:37 | +| main.rs:32:60:32:89 | ... * ... | main.rs:32:14:32:118 | ...::from_size_align_unchecked(...) | provenance | MaD:45 | | main.rs:33:31:33:32 | l5 | main.rs:33:13:33:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | main.rs:35:9:35:10 | s6 | main.rs:36:60:36:61 | s6 | provenance | | | main.rs:35:15:35:49 | ... * ... | main.rs:35:9:35:10 | s6 | provenance | | -| main.rs:35:49:35:49 | v | main.rs:35:15:35:49 | ... * ... | provenance | MaD:32 | +| main.rs:35:49:35:49 | v | main.rs:35:15:35:49 | ... * ... | provenance | MaD:36 | | main.rs:36:9:36:10 | l6 | main.rs:37:31:37:32 | l6 | provenance | | | main.rs:36:9:36:10 | l6 [Layout.size] | main.rs:37:31:37:32 | l6 [Layout.size] | provenance | | | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | main.rs:36:9:36:10 | l6 | provenance | | | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) [Layout.size] | main.rs:36:9:36:10 | l6 [Layout.size] | provenance | | -| main.rs:36:60:36:61 | s6 | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | provenance | MaD:41 | -| main.rs:36:60:36:61 | s6 | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) [Layout.size] | provenance | MaD:27 | +| main.rs:36:60:36:61 | s6 | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | provenance | MaD:45 | +| main.rs:36:60:36:61 | s6 | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) [Layout.size] | provenance | MaD:31 | | main.rs:37:31:37:32 | l6 | main.rs:37:13:37:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | -| main.rs:37:31:37:32 | l6 | main.rs:39:60:39:68 | l6.size() | provenance | MaD:45 | -| main.rs:37:31:37:32 | l6 [Layout.size] | main.rs:39:60:39:68 | l6.size() | provenance | MaD:28 | +| main.rs:37:31:37:32 | l6 | main.rs:39:60:39:68 | l6.size() | provenance | MaD:49 | +| main.rs:37:31:37:32 | l6 [Layout.size] | main.rs:39:60:39:68 | l6.size() | provenance | MaD:32 | | 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:41 | +| main.rs:39:60:39:68 | l6.size() | main.rs:39:14:39:72 | ...::from_size_align_unchecked(...) | provenance | MaD:45 | | main.rs:40:31:40:32 | l7 | main.rs:40:13:40:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | 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 | | @@ -106,47 +111,47 @@ edges | 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:31 | +| main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | main.rs:50:31:50:51 | ... .unwrap() [tuple.0] | provenance | MaD:35 | | 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:17 Sink:MaD:17 | -| main.rs:50:41:50:41 | v | main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:43 | -| 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:50:41:50:41 | v | main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:47 | +| main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | main.rs:51:31:51:55 | ... .unwrap() [tuple.0] | provenance | MaD:35 | | 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:17 Sink:MaD:17 | -| main.rs:51:41:51:45 | ... + ... | main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:43 | -| main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | main.rs:53:31:53:58 | ... .unwrap() | provenance | MaD:31 | +| main.rs:51:41:51:45 | ... + ... | main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:47 | +| main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | main.rs:53:31:53:58 | ... .unwrap() | provenance | MaD:35 | | main.rs:53:31:53:58 | ... .unwrap() | main.rs:53:13:53:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | -| main.rs:53:48:53:48 | v | main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | provenance | MaD:44 | -| main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | main.rs:54:31:54:63 | ... .unwrap() | provenance | MaD:31 | +| main.rs:53:48:53:48 | v | main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | provenance | MaD:48 | +| main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | main.rs:54:31:54:63 | ... .unwrap() | provenance | MaD:35 | | main.rs:54:31:54:63 | ... .unwrap() | main.rs:54:13:54:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | -| main.rs:54:48:54:53 | ... * ... | main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | provenance | MaD:44 | +| main.rs:54:48:54:53 | ... * ... | main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | provenance | MaD:48 | | 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:30 | +| main.rs:58:24:58:35 | l3.repeat(...) [Ok, tuple.0] | main.rs:58:24:58:66 | ... .expect(...) [tuple.0] | provenance | MaD:34 | | 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:43 | +| main.rs:58:34:58:34 | v | main.rs:58:24:58:35 | l3.repeat(...) [Ok, tuple.0] | provenance | MaD:47 | | main.rs:59:31:59:32 | k1 | main.rs:59:13:59:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | main.rs:59:31:59:32 | k1 | main.rs:60:34:60:35 | k1 | provenance | | | main.rs:59:31:59:32 | k1 | main.rs:64:48:64:49 | k1 | provenance | | | 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:31 | +| main.rs:60:24:60:36 | l3.extend(...) [Ok, tuple.0] | main.rs:60:24:60:45 | ... .unwrap() [tuple.0] | provenance | MaD:35 | | 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:38 | +| main.rs:60:34:60:35 | k1 | main.rs:60:24:60:36 | l3.extend(...) [Ok, tuple.0] | provenance | MaD:42 | | main.rs:61:31:61:32 | k2 | main.rs:61:13:61:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | -| 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:50 | l3.extend_packed(...) [Ok] | main.rs:64:31:64:59 | ... .unwrap() | provenance | MaD:35 | | main.rs:64:31:64:59 | ... .unwrap() | main.rs:64:13:64:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | -| main.rs:64:48:64:49 | k1 | main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | provenance | MaD:39 | +| main.rs:64:48:64:49 | k1 | main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | provenance | MaD:43 | | 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:31 | +| main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | main.rs:67:14:67:56 | ... .unwrap() | provenance | MaD:35 | | 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:37 | +| main.rs:67:46:67:46 | v | main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | provenance | MaD:41 | | main.rs:68:31:68:32 | l4 | main.rs:68:13:68:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | 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:58 | ...::from_size_align(...) [Ok] | main.rs:87:18:87:67 | ... .unwrap() | provenance | MaD:35 | | 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:40 | +| main.rs:87:54:87:54 | v | main.rs:87:18:87:58 | ...::from_size_align(...) [Ok] | provenance | MaD:44 | | main.rs:88:31:88:36 | layout | main.rs:88:13:88:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | main.rs:91:38:91:45 | ...: usize | main.rs:92:47:92:47 | v | provenance | | | main.rs:91:38:91:45 | ...: usize | main.rs:101:51:101:51 | v | provenance | | @@ -157,16 +162,16 @@ edges | main.rs:91:38:91:45 | ...: usize | main.rs:161:55:161:55 | 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:48 | ...::array::<...>(...) [Ok] | main.rs:92:14:92:57 | ... .unwrap() | provenance | MaD:35 | | 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:37 | +| main.rs:92:47:92:47 | v | main.rs:92:14:92:48 | ...::array::<...>(...) [Ok] | provenance | MaD:41 | | main.rs:96:35:96:36 | l1 | main.rs:96:17:96:33 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | 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: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:52 | ...::array::<...>(...) [Ok] | main.rs:101:18:101:61 | ... .unwrap() | provenance | MaD:35 | | 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:37 | +| main.rs:101:51:101:51 | v | main.rs:101:18:101:52 | ...::array::<...>(...) [Ok] | provenance | MaD:41 | | main.rs:102:35:102:36 | l1 | main.rs:102:17:102:33 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | 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 | | @@ -177,28 +182,28 @@ edges | main.rs:111:35:111:36 | l1 | main.rs:111:17:111:33 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | main.rs:111:35:111:36 | l1 | main.rs:146:35:146:36 | l1 | provenance | | | 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:52 | ...::array::<...>(...) [Ok] | main.rs:145:18:145:61 | ... .unwrap() | provenance | MaD:35 | | 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:37 | +| main.rs:145:51:145:51 | v | main.rs:145:18:145:52 | ...::array::<...>(...) [Ok] | provenance | MaD:41 | | main.rs:146:35:146:36 | l1 | main.rs:146:17:146:33 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | main.rs:146:35:146:36 | l1 | main.rs:177:31:177:32 | l1 | provenance | | | main.rs:148:35:148:36 | l9 | main.rs:148:17:148:33 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | 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:69 | ...::array::<...>(...) [Ok] | main.rs:151:15:151:78 | ... .unwrap() | provenance | MaD:35 | | 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:37 | -| main.rs:151:62:151:62 | v | main.rs:151:48:151:68 | ...::min(...) | provenance | MaD:35 | +| main.rs:151:48:151:68 | ...::min(...) | main.rs:151:15:151:69 | ...::array::<...>(...) [Ok] | provenance | MaD:41 | +| main.rs:151:62:151:62 | v | main.rs:151:48:151:68 | ...::min(...) | provenance | MaD:39 | | main.rs:152:31:152:33 | l10 | main.rs:152:13:152:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | 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:69 | ...::array::<...>(...) [Ok] | main.rs:154:15:154:78 | ... .unwrap() | provenance | MaD:35 | | 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:37 | -| main.rs:154:62:154:62 | v | main.rs:154:48:154:68 | ...::max(...) | provenance | MaD:34 | +| main.rs:154:48:154:68 | ...::max(...) | main.rs:154:15:154:69 | ...::array::<...>(...) [Ok] | provenance | MaD:41 | +| main.rs:154:62:154:62 | v | main.rs:154:48:154:68 | ...::max(...) | provenance | MaD:38 | | main.rs:155:31:155:33 | l11 | main.rs:155:13:155:29 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | 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:59 | ...::from_size_align(...) [Ok] | main.rs:161:19:161:68 | ... .unwrap() | provenance | MaD:35 | | 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:40 | +| main.rs:161:55:161:55 | v | main.rs:161:19:161:59 | ...::from_size_align(...) [Ok] | provenance | MaD:44 | | main.rs:162:35:162:37 | l13 | main.rs:162:17:162:33 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | | main.rs:162:35:162:37 | l13 | main.rs:169:35:169:37 | l13 | provenance | | | main.rs:169:35:169:37 | l13 | main.rs:169:17:169:33 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | @@ -206,9 +211,9 @@ edges | main.rs:183:29:183:36 | ...: usize | main.rs:192:46:192:46 | v | provenance | | | main.rs:183:29:183:36 | ...: usize | main.rs:202:48:202:48 | 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:47 | ...::array::<...>(...) [Ok] | main.rs:192:14:192:56 | ... .unwrap() | provenance | MaD:35 | | 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:37 | +| main.rs:192:46:192:46 | v | main.rs:192:14:192:47 | ...::array::<...>(...) [Ok] | provenance | MaD:41 | | main.rs:193:38:193:39 | l2 | main.rs:193:32:193:36 | alloc | provenance | MaD:24 Sink:MaD:24 | | 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 | | @@ -237,40 +242,52 @@ edges | main.rs:210:60:210:61 | l2 | main.rs:210:40:210:50 | grow_zeroed | provenance | MaD:23 Sink:MaD:23 | | main.rs:210:60:210:61 | l2 | main.rs:210:40:210:50 | grow_zeroed | provenance | MaD:8 Sink:MaD:8 | | main.rs:213:51:213:52 | l2 | main.rs:213:36:213:41 | shrink | 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:28 Sink:MaD:28 | +| 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:26 Sink:MaD:26 | +| 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:27 Sink:MaD:27 | +| 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:27 Sink:MaD:27 | +| 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:29 Sink:MaD:29 | | main.rs:227:24:227:31 | ...: usize | main.rs:230:46:230:46 | v | provenance | | | main.rs:230:46:230:46 | v | main.rs:230:13:230:44 | ...::try_with_capacity_in | provenance | MaD:3 Sink:MaD:3 | | main.rs:230:46:230:46 | v | main.rs:231:42:231:42 | v | provenance | | | main.rs:231:42:231:42 | v | main.rs:231:13:231:40 | ...::with_capacity_in | provenance | MaD:4 Sink:MaD:4 | -| main.rs:279:24:279:41 | ...: String | main.rs:280:21:280:47 | user_input.parse() [Ok] | provenance | MaD:46 | +| main.rs:279:24:279:41 | ...: String | main.rs:280:21:280:47 | user_input.parse() [Ok] | provenance | MaD:50 | | 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:280:21:280:48 | TryExpr | main.rs:280:21:280:77 | ... * ... | provenance | MaD:33 | +| main.rs:280:21:280:48 | TryExpr | main.rs:280:21:280:77 | ... * ... | provenance | MaD:37 | | main.rs:280:21:280:77 | ... * ... | 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:66 | ...::from_size_align(...) [Ok] | main.rs:282:18:282:75 | ... .unwrap() | provenance | MaD:35 | | 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:40 | +| main.rs:282:54:282:62 | num_bytes | main.rs:282:18:282:66 | ...::from_size_align(...) [Ok] | provenance | MaD:44 | | main.rs:284:40:284:45 | layout | main.rs:284:22:284:38 | ...::alloc | provenance | MaD:17 Sink:MaD:17 | -| main.rs:308:25:308:38 | ...::args | main.rs:308:25:308:40 | ...::args(...) [element] | provenance | Src:MaD:26 | -| main.rs:308:25:308:40 | ...::args(...) [element] | main.rs:308:25:308:47 | ... .nth(...) [Some] | provenance | MaD:47 | -| main.rs:308:25:308:47 | ... .nth(...) [Some] | main.rs:308:25:308:74 | ... .unwrap_or(...) | provenance | MaD:29 | +| main.rs:308:25:308:38 | ...::args | main.rs:308:25:308:40 | ...::args(...) [element] | provenance | Src:MaD:30 | +| main.rs:308:25:308:40 | ...::args(...) [element] | main.rs:308:25:308:47 | ... .nth(...) [Some] | provenance | MaD:51 | +| main.rs:308:25:308:47 | ... .nth(...) [Some] | main.rs:308:25:308:74 | ... .unwrap_or(...) | provenance | MaD:33 | | main.rs:308:25:308:74 | ... .unwrap_or(...) | main.rs:279:24:279:41 | ...: 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:9:317:9 | v | main.rs:325:22:325:22 | v | provenance | | -| main.rs:317:13:317:26 | ...::args | main.rs:317:13:317:28 | ...::args(...) [element] | provenance | Src:MaD:26 | -| main.rs:317:13:317:28 | ...::args(...) [element] | main.rs:317:13:317:35 | ... .nth(...) [Some] | provenance | MaD:47 | -| 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:46 | -| main.rs:317:13:317:82 | ... .parse() [Ok] | main.rs:317:13:317:91 | ... .unwrap() | provenance | MaD:31 | +| main.rs:317:13:317:26 | ...::args | main.rs:317:13:317:28 | ...::args(...) [element] | provenance | Src:MaD:30 | +| main.rs:317:13:317:28 | ...::args(...) [element] | main.rs:317:13:317:35 | ... .nth(...) [Some] | provenance | MaD:51 | +| main.rs:317:13:317:35 | ... .nth(...) [Some] | main.rs:317:13:317:65 | ... .unwrap_or(...) | provenance | MaD:33 | +| main.rs:317:13:317:65 | ... .unwrap_or(...) | main.rs:317:13:317:82 | ... .parse() [Ok] | provenance | MaD:50 | +| main.rs:317:13:317:82 | ... .parse() [Ok] | main.rs:317:13:317:91 | ... .unwrap() | provenance | MaD:35 | | 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 | | | main.rs:325:22:325:22 | v | main.rs:227:24:227:31 | ...: usize | provenance | | models | 1 | Sink: ::allocate; Argument[0]; alloc-layout | @@ -298,28 +315,32 @@ models | 23 | Sink: lang:std; ::grow_zeroed; Argument[2]; alloc-layout | | 24 | Sink: lang:std; ::alloc; Argument[0]; alloc-layout | | 25 | Sink: lang:std; ::alloc_zeroed; Argument[0]; alloc-layout | -| 26 | Source: std::env::args; ReturnValue.Element; commandargs | -| 27 | Summary: ::from_size_align_unchecked; Argument[0]; ReturnValue.Field[core::alloc::layout::Layout::size]; value | -| 28 | Summary: ::size; Argument[self].Field[core::alloc::layout::Layout::size]; ReturnValue; value | -| 29 | Summary: ::unwrap_or; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value | -| 30 | Summary: ::expect; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value | -| 31 | Summary: ::unwrap; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value | -| 32 | Summary: ::mul; Argument[0]; ReturnValue; taint | -| 33 | Summary: ::mul; Argument[self]; ReturnValue; taint | -| 34 | Summary: core::cmp::max; Argument[0]; ReturnValue; value | -| 35 | Summary: core::cmp::min; Argument[0]; ReturnValue; value | -| 36 | Summary: lang:core; ::align_to; Argument[self]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | -| 37 | Summary: lang:core; ::array; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | -| 38 | Summary: lang:core; ::extend; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)].Field[0]; taint | -| 39 | Summary: lang:core; ::extend_packed; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | -| 40 | Summary: lang:core; ::from_size_align; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | -| 41 | Summary: lang:core; ::from_size_align_unchecked; Argument[0]; ReturnValue; taint | -| 42 | Summary: lang:core; ::pad_to_align; Argument[self]; ReturnValue; taint | -| 43 | Summary: lang:core; ::repeat; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)].Field[0]; taint | -| 44 | Summary: lang:core; ::repeat_packed; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | -| 45 | Summary: lang:core; ::size; Argument[self]; ReturnValue; taint | -| 46 | Summary: lang:core; ::parse; Argument[self]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | -| 47 | Summary: lang:core; crate::iter::traits::iterator::Iterator::nth; Argument[self].Element; ReturnValue.Field[core::option::Option::Some(0)]; value | +| 26 | Sink: libc::unix::aligned_alloc; Argument[1]; alloc-size | +| 27 | Sink: libc::unix::calloc; Argument[0,1]; alloc-size | +| 28 | Sink: libc::unix::malloc; Argument[0]; alloc-size | +| 29 | Sink: libc::unix::realloc; Argument[1]; alloc-size | +| 30 | Source: std::env::args; ReturnValue.Element; commandargs | +| 31 | Summary: ::from_size_align_unchecked; Argument[0]; ReturnValue.Field[core::alloc::layout::Layout::size]; value | +| 32 | Summary: ::size; Argument[self].Field[core::alloc::layout::Layout::size]; ReturnValue; value | +| 33 | Summary: ::unwrap_or; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value | +| 34 | Summary: ::expect; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value | +| 35 | Summary: ::unwrap; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value | +| 36 | Summary: ::mul; Argument[0]; ReturnValue; taint | +| 37 | Summary: ::mul; Argument[self]; ReturnValue; taint | +| 38 | Summary: core::cmp::max; Argument[0]; ReturnValue; value | +| 39 | Summary: core::cmp::min; Argument[0]; ReturnValue; value | +| 40 | Summary: lang:core; ::align_to; Argument[self]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | +| 41 | Summary: lang:core; ::array; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | +| 42 | Summary: lang:core; ::extend; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)].Field[0]; taint | +| 43 | Summary: lang:core; ::extend_packed; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | +| 44 | Summary: lang:core; ::from_size_align; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | +| 45 | Summary: lang:core; ::from_size_align_unchecked; Argument[0]; ReturnValue; taint | +| 46 | Summary: lang:core; ::pad_to_align; Argument[self]; ReturnValue; taint | +| 47 | Summary: lang:core; ::repeat; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)].Field[0]; taint | +| 48 | Summary: lang:core; ::repeat_packed; Argument[0]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | +| 49 | Summary: lang:core; ::size; Argument[self]; ReturnValue; taint | +| 50 | Summary: lang:core; ::parse; Argument[self]; ReturnValue.Field[core::result::Result::Ok(0)]; taint | +| 51 | Summary: lang:core; crate::iter::traits::iterator::Iterator::nth; Argument[self].Element; ReturnValue.Field[core::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 | @@ -503,6 +524,17 @@ nodes | main.rs:210:60:210:61 | l2 | semmle.label | l2 | | main.rs:213:36:213:41 | shrink | semmle.label | shrink | | main.rs:213:51:213:52 | 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:26:219:26 | v | semmle.label | v | +| 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:30:222:30 | v | semmle.label | v | +| 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:31:224:31 | v | semmle.label | v | | main.rs:227:24:227:31 | ...: usize | semmle.label | ...: usize | | main.rs:230:13:230:44 | ...::try_with_capacity_in | semmle.label | ...::try_with_capacity_in | | main.rs:230:46:230:46 | v | semmle.label | v | @@ -534,5 +566,6 @@ nodes | 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 | | main.rs:325:22:325:22 | v | semmle.label | v | subpaths 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 d71f7bd0e39..0b39862ef32 100644 --- a/rust/ql/test/query-tests/security/CWE-770/main.rs +++ b/rust/ql/test/query-tests/security/CWE-770/main.rs @@ -216,12 +216,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]=arg1 - let _ = libc::aligned_alloc(8, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]=arg1 + 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]=arg1 - let _ = libc::calloc(v, std::mem::size_of::()); // $ MISSING: Alert[rust/uncontrolled-allocation-size]=arg1 - let _ = libc::realloc(m1, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]=arg1 + 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) { 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 399c8f76316..2bd8de26923 100644 --- a/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected +++ b/rust/ql/test/query-tests/security/CWE-825/AccessInvalidPointer.expected @@ -8,6 +8,7 @@ | deallocation.rs:86:7:86:8 | m2 | deallocation.rs:70:3:70:21 | ...::dealloc | deallocation.rs:86:7:86:8 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:70:3:70:21 | ...::dealloc | invalid | | deallocation.rs:90:7:90:8 | m2 | deallocation.rs:70:3:70:21 | ...::dealloc | deallocation.rs:90:7:90:8 | m2 | This operation dereferences a pointer that may be $@. | deallocation.rs:70:3:70:21 | ...::dealloc | invalid | | deallocation.rs:95:5:95:31 | ...::write::<...> | deallocation.rs:70:3:70:21 | ...::dealloc | deallocation.rs:95:5:95:31 | ...::write::<...> | This operation dereferences a pointer that may be $@. | deallocation.rs:70:3:70:21 | ...::dealloc | invalid | +| deallocation.rs:115:13:115:18 | my_ptr | deallocation.rs:112:3:112:12 | ...::free | deallocation.rs:115:13:115:18 | my_ptr | This operation dereferences a pointer that may be $@. | deallocation.rs:112:3:112:12 | ...::free | 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: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 | @@ -31,6 +32,8 @@ edges | deallocation.rs:70:23:70:35 | [post] m2 as ... | deallocation.rs:90:7:90:8 | m2 | provenance | | | deallocation.rs:70:23:70:35 | [post] m2 as ... | 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:3:112:12 | ...::free | deallocation.rs:112:14:112:40 | [post] my_ptr as ... | provenance | Src:MaD:10 MaD:10 | +| deallocation.rs:112:14:112:40 | [post] my_ptr as ... | 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:6 MaD:6 | | deallocation.rs:123:23:123:40 | ...::dangling | deallocation.rs:123:23:123:42 | ...::dangling(...) | provenance | Src:MaD:3 MaD:3 | @@ -57,6 +60,7 @@ models | 7 | Source: lang:core; crate::ptr::dangling_mut; ReturnValue; pointer-invalidate | | 8 | Source: lang:core; crate::ptr::drop_in_place; Argument[0]; pointer-invalidate | | 9 | Source: lang:core; crate::ptr::null; ReturnValue; pointer-invalidate | +| 10 | Source: libc::unix::free; Argument[0]; pointer-invalidate | nodes | deallocation.rs:20:3:20:21 | ...::dealloc | semmle.label | ...::dealloc | | deallocation.rs:20:23:20:24 | [post] m1 | semmle.label | [post] m1 | @@ -74,6 +78,9 @@ nodes | 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:3:112:12 | ...::free | semmle.label | ...::free | +| deallocation.rs:112:14:112:40 | [post] my_ptr as ... | semmle.label | [post] my_ptr as ... | +| 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:40 | ...::dangling | semmle.label | ...::dangling | 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 0d8f977387b..89ef0470e99 100644 --- a/rust/ql/test/query-tests/security/CWE-825/deallocation.rs +++ b/rust/ql/test/query-tests/security/CWE-825/deallocation.rs @@ -109,10 +109,10 @@ pub fn test_libc() { let v1 = *my_ptr; // GOOD println!(" v1 = {v1}"); - libc::free(my_ptr as *mut libc::c_void); // $ MISSING: Source[rust/access-invalid-pointer]=free + libc::free(my_ptr as *mut libc::c_void); // $ Source[rust/access-invalid-pointer]=free // (my_ptr is now dangling) - let v2 = *my_ptr; // $ MISSING: Alert[rust/access-invalid-pointer]=free + let v2 = *my_ptr; // $ Alert[rust/access-invalid-pointer]=free println!(" v2 = {v2} (!)"); // corrupt in practice } } From f57d691424fc8256947a71fa6c510884c89609c5 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 8 Jul 2025 09:33:50 +0100 Subject: [PATCH 031/199] Rust: Fix typo in model. --- .../codeql/rust/frameworks/async-rs.model.yml | 2 +- .../dataflow/sources/TaintSources.expected | 1 + .../dataflow/sources/test_futures_io.rs | 16 ++++++++-------- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/async-rs.model.yml b/rust/ql/lib/codeql/rust/frameworks/async-rs.model.yml index d90504d77c8..9e65ba1b196 100644 --- a/rust/ql/lib/codeql/rust/frameworks/async-rs.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/async-rs.model.yml @@ -3,4 +3,4 @@ extensions: pack: codeql/rust-all extensible: sourceModel data: - - ["::connect", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "remote", "manual"] + - ["::connect", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "remote", "manual"] diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected index 0e170f5f44c..4d95b9bb61b 100644 --- a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -75,6 +75,7 @@ | test.rs:779:22:779:50 | ...::new | Flow source 'RemoteSource' of type remote (DEFAULT). | | test.rs:806:16:806:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | | test.rs:806:16:806:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). | +| test_futures_io.rs:19:15:19:32 | ...::connect | Flow source 'RemoteSource' of type remote (DEFAULT). | | web_frameworks.rs:11:31:11:31 | a | Flow source 'RemoteSource' of type remote (DEFAULT). | | web_frameworks.rs:11:31:11:31 | a | Flow source 'RemoteSource' of type remote (DEFAULT). | | web_frameworks.rs:22:14:22:18 | TuplePat | Flow source 'RemoteSource' of type remote (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/test_futures_io.rs b/rust/ql/test/library-tests/dataflow/sources/test_futures_io.rs index 4cff19432a4..0174c2045fe 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test_futures_io.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test_futures_io.rs @@ -16,21 +16,21 @@ use std::task::{Context, Poll}; async fn test_futures_rustls_futures_io() -> io::Result<()> { let url = "www.example.com:443"; - let tcp = TcpStream::connect(url).await?; // $ MISSING: Alert[rust/summary/taint-sources] - sink(&tcp); // $ MISSING: hasTaintFlow=url + let tcp = TcpStream::connect(url).await?; // $ Alert[rust/summary/taint-sources] + sink(&tcp); // $ hasTaintFlow=url let config = rustls::ClientConfig::builder() .with_root_certificates(rustls::RootCertStore::empty()) .with_no_client_auth(); let connector = TlsConnector::from(Arc::new(config)); let server_name = rustls::pki_types::ServerName::try_from("www.example.com").unwrap(); let mut reader = connector.connect(server_name, tcp).await?; - sink(&reader); // $ MISSING: hasTaintFlow=url + sink(&reader); // $ hasTaintFlow=url { // using the `AsyncRead` trait (low-level) let mut buffer = [0u8; 64]; let mut pinned = Pin::new(&mut reader); - sink(&pinned); // $ MISSING: hasTaintFlow=url + sink(&pinned); // $ hasTaintFlow=url let mut cx = Context::from_waker(futures::task::noop_waker_ref()); let bytes_read = pinned.poll_read(&mut cx, &mut buffer); // we cannot correctly resolve this call, since it relies on `Deref` if let Poll::Ready(Ok(n)) = bytes_read { @@ -52,12 +52,12 @@ async fn test_futures_rustls_futures_io() -> io::Result<()> { } let mut reader2 = futures::io::BufReader::new(reader); - sink(&reader2); // $ MISSING: hasTaintFlow=url + sink(&reader2); // $ hasTaintFlow=url { // using the `AsyncBufRead` trait (low-level) let mut pinned = Pin::new(&mut reader2); - sink(&pinned); // $ MISSING: hasTaintFlow=url + sink(&pinned); // $ hasTaintFlow=url let mut cx = Context::from_waker(futures::task::noop_waker_ref()); let buffer = pinned.poll_fill_buf(&mut cx); if let Poll::Ready(Ok(buf)) = buffer { @@ -88,7 +88,7 @@ async fn test_futures_rustls_futures_io() -> io::Result<()> { // using the `AsyncRead` trait (low-level) let mut buffer = [0u8; 64]; let mut pinned = Pin::new(&mut reader2); - sink(&pinned); // $ MISSING: hasTaintFlow=url + sink(&pinned); // $ hasTaintFlow=url let mut cx = Context::from_waker(futures::task::noop_waker_ref()); let bytes_read = pinned.poll_read(&mut cx, &mut buffer); sink(&buffer); // $ MISSING: hasTaintFlow=url @@ -111,7 +111,7 @@ async fn test_futures_rustls_futures_io() -> io::Result<()> { { // using the `AsyncBufRead` trait (low-level) let mut pinned = Pin::new(&mut reader2); - sink(&pinned); // $ MISSING: hasTaintFlow=url + sink(&pinned); // $ hasTaintFlow=url let mut cx = Context::from_waker(futures::task::noop_waker_ref()); let buffer = pinned.poll_fill_buf(&mut cx); sink(&buffer); // $ MISSING: hasTaintFlow=url From 3dabd51cf73e190089aea6b104dfa1b9f9b9f49f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 8 Jul 2025 11:24:57 +0100 Subject: [PATCH 032/199] Rust: Fix a summaryModelDeprecated that was causing problems. --- rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml | 4 ++-- rust/ql/test/library-tests/dataflow/sources/test.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml b/rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml index fc86d2fb908..7aca1a852d9 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/io.model.yml @@ -19,8 +19,8 @@ extensions: - ["lang:std", "::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - ["lang:std", "::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - ["lang:std", "crate::io::Read::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", ":::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - - ["lang:std", ":::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["lang:std", "::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] + - ["lang:std", "::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - ["lang:std", "::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - ["lang:std", "crate::io::Read::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"] - ["lang:std", "::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"] diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs index 0ee8ac2e45b..16c0798a107 100644 --- a/rust/ql/test/library-tests/dataflow/sources/test.rs +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -214,7 +214,7 @@ fn test_io_stdin() -> std::io::Result<()> { { let mut buffer = Vec::::new(); let _bytes = std::io::stdin().read_to_end(&mut buffer)?; // $ Alert[rust/summary/taint-sources] - sink(&buffer); // $ MISSING: hasTaintFlow + sink(&buffer); // $ hasTaintFlow } { From b51940d1e2b40c500bb82265a106c1154ead9e8d Mon Sep 17 00:00:00 2001 From: Nick Rolfe Date: Wed, 18 Jun 2025 15:32:41 +0100 Subject: [PATCH 033/199] Ruby: add overlay[local] annotations to AST/CFG/SSA layers --- ql/ql/src/codeql/Locations.qll | 2 ++ ql/ql/src/codeql/files/FileSystem.qll | 2 ++ ql/ql/src/codeql_ql/StructuredLogs.qll | 5 +++++ ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll | 12 ++++-------- ql/ql/src/experimental/RA.qll | 5 ++--- ql/ql/src/queries/performance/LargeTupleSum.ql | 1 + ql/ql/test/experimental/raparser.ql | 1 + ruby/ql/lib/codeql/Locations.qll | 2 ++ ruby/ql/lib/codeql/files/FileSystem.qll | 2 ++ ruby/ql/lib/codeql/ruby/AST.qll | 3 +++ ruby/ql/lib/codeql/ruby/Diagnostics.qll | 2 ++ ruby/ql/lib/codeql/ruby/ast/Call.qll | 5 +++++ ruby/ql/lib/codeql/ruby/ast/Constant.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/Control.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/Erb.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/Expr.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/Literal.qll | 4 ++++ ruby/ql/lib/codeql/ruby/ast/Method.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/Module.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/Operation.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/Parameter.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/Pattern.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/Scope.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/Statement.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/Variable.qll | 2 ++ ruby/ql/lib/codeql/ruby/ast/internal/AST.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/internal/Call.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/internal/Constant.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/internal/Control.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/internal/Erb.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/internal/Literal.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/internal/Method.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/internal/Module.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/internal/Operation.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/internal/Pattern.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/internal/Scope.qll | 3 +++ ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll | 2 ++ ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll | 6 ++---- ruby/ql/lib/codeql/ruby/ast/internal/Variable.qll | 3 +++ ruby/ql/lib/codeql/ruby/controlflow/BasicBlocks.qll | 2 ++ ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll | 2 ++ .../lib/codeql/ruby/controlflow/ControlFlowGraph.qll | 2 ++ .../codeql/ruby/controlflow/internal/Completion.qll | 2 ++ .../controlflow/internal/ControlFlowGraphImpl.qll | 2 ++ .../lib/codeql/ruby/controlflow/internal/Guards.qll | 3 +++ .../ruby/controlflow/internal/NonReturning.qll | 2 ++ .../codeql/ruby/controlflow/internal/Splitting.qll | 2 ++ ruby/ql/lib/codeql/ruby/dataflow/SSA.qll | 2 ++ .../ql/lib/codeql/ruby/dataflow/internal/SsaImpl.qll | 4 ++++ shared/tree-sitter-extractor/src/generator/mod.rs | 1 + shared/tree-sitter-extractor/src/generator/ql.rs | 9 +++++++++ shared/tree-sitter-extractor/src/generator/ql_gen.rs | 4 ++-- 54 files changed, 151 insertions(+), 17 deletions(-) diff --git a/ql/ql/src/codeql/Locations.qll b/ql/ql/src/codeql/Locations.qll index ae8058c916d..e03c84f98fa 100644 --- a/ql/ql/src/codeql/Locations.qll +++ b/ql/ql/src/codeql/Locations.qll @@ -1,4 +1,6 @@ /** Provides classes for working with locations. */ +overlay[local] +module; import files.FileSystem diff --git a/ql/ql/src/codeql/files/FileSystem.qll b/ql/ql/src/codeql/files/FileSystem.qll index 5a219f3b7f0..52174250af0 100644 --- a/ql/ql/src/codeql/files/FileSystem.qll +++ b/ql/ql/src/codeql/files/FileSystem.qll @@ -1,4 +1,6 @@ /** Provides classes for working with files and folders. */ +overlay[local?] +module; private import codeql_ql.ast.internal.TreeSitter private import codeql.Locations diff --git a/ql/ql/src/codeql_ql/StructuredLogs.qll b/ql/ql/src/codeql_ql/StructuredLogs.qll index 4c0ef69fd55..87527eae1d2 100644 --- a/ql/ql/src/codeql_ql/StructuredLogs.qll +++ b/ql/ql/src/codeql_ql/StructuredLogs.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import ql private import codeql_ql.ast.internal.TreeSitter private import experimental.RA @@ -23,6 +26,7 @@ private float stringToTimestamp(string str) { } bindingset[s] +overlay[global] private Predicate getPredicateFromPosition(string s) { exists(string r, string filepath, int startline | r = "(.*):(\\d+),(\\d+)-(\\d+),(\\d+)" | filepath = s.regexpCapture(r, 1) and @@ -397,6 +401,7 @@ module KindPredicatesLog { string getPosition() { result = this.getString("position") } + overlay[global] Predicate getPredicate() { result = getPredicateFromPosition(this.getPosition()) } /** diff --git a/ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll b/ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll index 2d4a9d65465..c81830e1d59 100644 --- a/ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll +++ b/ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll @@ -23,6 +23,7 @@ private predicate discardLocation(@location_default loc) { ) } +overlay[local] module QL { /** The base class for all AST nodes */ class AstNode extends @ql_ast_node { @@ -67,7 +68,6 @@ module QL { } /** Gets the file containing the given `node`. */ - overlay[local] private @file getNodeFile(@ql_ast_node node) { exists(@location_default loc | ql_ast_node_location(node, loc) | locations_default(loc, result, _, _, _, _) @@ -75,7 +75,6 @@ module QL { } /** Holds if `node` is in the `file` and is part of the overlay base database. */ - overlay[local] private predicate discardableAstNode(@file file, @ql_ast_node node) { not isOverlay() and file = getNodeFile(node) } @@ -1315,6 +1314,7 @@ module QL { } } +overlay[local] module Dbscheme { /** The base class for all AST nodes */ class AstNode extends @dbscheme_ast_node { @@ -1359,7 +1359,6 @@ module Dbscheme { } /** Gets the file containing the given `node`. */ - overlay[local] private @file getNodeFile(@dbscheme_ast_node node) { exists(@location_default loc | dbscheme_ast_node_location(node, loc) | locations_default(loc, result, _, _, _, _) @@ -1367,7 +1366,6 @@ module Dbscheme { } /** Holds if `node` is in the `file` and is part of the overlay base database. */ - overlay[local] private predicate discardableAstNode(@file file, @dbscheme_ast_node node) { not isOverlay() and file = getNodeFile(node) } @@ -1673,6 +1671,7 @@ module Dbscheme { } } +overlay[local] module Blame { /** The base class for all AST nodes */ class AstNode extends @blame_ast_node { @@ -1717,7 +1716,6 @@ module Blame { } /** Gets the file containing the given `node`. */ - overlay[local] private @file getNodeFile(@blame_ast_node node) { exists(@location_default loc | blame_ast_node_location(node, loc) | locations_default(loc, result, _, _, _, _) @@ -1725,7 +1723,6 @@ module Blame { } /** Holds if `node` is in the `file` and is part of the overlay base database. */ - overlay[local] private predicate discardableAstNode(@file file, @blame_ast_node node) { not isOverlay() and file = getNodeFile(node) } @@ -1808,6 +1805,7 @@ module Blame { } } +overlay[local] module JSON { /** The base class for all AST nodes */ class AstNode extends @json_ast_node { @@ -1852,7 +1850,6 @@ module JSON { } /** Gets the file containing the given `node`. */ - overlay[local] private @file getNodeFile(@json_ast_node node) { exists(@location_default loc | json_ast_node_location(node, loc) | locations_default(loc, result, _, _, _, _) @@ -1860,7 +1857,6 @@ module JSON { } /** Holds if `node` is in the `file` and is part of the overlay base database. */ - overlay[local] private predicate discardableAstNode(@file file, @json_ast_node node) { not isOverlay() and file = getNodeFile(node) } diff --git a/ql/ql/src/experimental/RA.qll b/ql/ql/src/experimental/RA.qll index 7187ebfc8c7..5eb80455562 100644 --- a/ql/ql/src/experimental/RA.qll +++ b/ql/ql/src/experimental/RA.qll @@ -1,6 +1,5 @@ -/** - * Parses RA expressions. - */ +overlay[local] +module; /** * A predicate that contains RA. diff --git a/ql/ql/src/queries/performance/LargeTupleSum.ql b/ql/ql/src/queries/performance/LargeTupleSum.ql index e5bbed79bbd..4e5ca6622e8 100644 --- a/ql/ql/src/queries/performance/LargeTupleSum.ql +++ b/ql/ql/src/queries/performance/LargeTupleSum.ql @@ -6,6 +6,7 @@ import ql import codeql_ql.StructuredLogs import KindPredicatesLog +overlay[local] module SumCounts implements Fold { int base(PipeLineRun run) { result = sum(int i | | run.getCount(i)) } diff --git a/ql/ql/test/experimental/raparser.ql b/ql/ql/test/experimental/raparser.ql index 29489e2a968..5704b0facdb 100644 --- a/ql/ql/test/experimental/raparser.ql +++ b/ql/ql/test/experimental/raparser.ql @@ -1,5 +1,6 @@ import experimental.RA +overlay[local] class TestPredicate extends string { TestPredicate() { this = "p1" } diff --git a/ruby/ql/lib/codeql/Locations.qll b/ruby/ql/lib/codeql/Locations.qll index 148c6b01f2d..df52d6822a2 100644 --- a/ruby/ql/lib/codeql/Locations.qll +++ b/ruby/ql/lib/codeql/Locations.qll @@ -1,4 +1,6 @@ /** Provides classes for working with locations. */ +overlay[local] +module; import files.FileSystem diff --git a/ruby/ql/lib/codeql/files/FileSystem.qll b/ruby/ql/lib/codeql/files/FileSystem.qll index 528dde52fd9..6cc771fad9d 100644 --- a/ruby/ql/lib/codeql/files/FileSystem.qll +++ b/ruby/ql/lib/codeql/files/FileSystem.qll @@ -1,4 +1,6 @@ /** Provides classes for working with files and folders. */ +overlay[local] +module; private import codeql.Locations private import codeql.util.FileSystem diff --git a/ruby/ql/lib/codeql/ruby/AST.qll b/ruby/ql/lib/codeql/ruby/AST.qll index bd42696a8db..2c2dbdfa532 100644 --- a/ruby/ql/lib/codeql/ruby/AST.qll +++ b/ruby/ql/lib/codeql/ruby/AST.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import codeql.Locations import ast.Call import ast.Control diff --git a/ruby/ql/lib/codeql/ruby/Diagnostics.qll b/ruby/ql/lib/codeql/ruby/Diagnostics.qll index 58de14b8fcf..5b55eec3809 100644 --- a/ruby/ql/lib/codeql/ruby/Diagnostics.qll +++ b/ruby/ql/lib/codeql/ruby/Diagnostics.qll @@ -1,4 +1,6 @@ /** Provides classes relating to extraction diagnostics. */ +overlay[local] +module; private import codeql.Locations diff --git a/ruby/ql/lib/codeql/ruby/ast/Call.qll b/ruby/ql/lib/codeql/ruby/ast/Call.qll index 8a69ebd36fb..3a82d0d39b3 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Call.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Call.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.AST private import internal.Call @@ -52,6 +55,7 @@ class Call extends Expr instanceof CallImpl { final int getNumberOfArguments() { result = super.getNumberOfArgumentsImpl() } /** Gets a potential target of this call, if any. */ + overlay[global] final Callable getATarget() { exists(DataFlowCall c | this = c.asCall().getExpr() and @@ -153,6 +157,7 @@ class MethodCall extends Call instanceof MethodCallImpl { * TODO: When API Graphs is able to resolve calls to methods like `Kernel.send` * this class is no longer necessary and should be removed. */ +overlay[global] class UnknownMethodCall extends MethodCall { UnknownMethodCall() { not exists(this.(Call).getATarget()) } } diff --git a/ruby/ql/lib/codeql/ruby/ast/Constant.qll b/ruby/ql/lib/codeql/ruby/ast/Constant.qll index fef057bc88e..9c7ac62e542 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Constant.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Constant.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.AST private import internal.Constant diff --git a/ruby/ql/lib/codeql/ruby/ast/Control.qll b/ruby/ql/lib/codeql/ruby/ast/Control.qll index 18182d8268a..5d83e7a62fd 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Control.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Control.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.AST private import internal.Control diff --git a/ruby/ql/lib/codeql/ruby/ast/Erb.qll b/ruby/ql/lib/codeql/ruby/ast/Erb.qll index 4dbcca73425..4def19f7ceb 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Erb.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Erb.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.Erb private import internal.TreeSitter diff --git a/ruby/ql/lib/codeql/ruby/ast/Expr.qll b/ruby/ql/lib/codeql/ruby/ast/Expr.qll index 5f916fbec5c..8ab203aed87 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Expr.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Expr.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import codeql.ruby.CFG private import internal.AST diff --git a/ruby/ql/lib/codeql/ruby/ast/Literal.qll b/ruby/ql/lib/codeql/ruby/ast/Literal.qll index cdeae9e64a6..a32ca16e24c 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Literal.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Literal.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import codeql.ruby.Regexp as RE private import internal.AST @@ -387,6 +390,7 @@ class RegExpLiteral extends StringlikeLiteral instanceof RegExpLiteralImpl { final predicate hasFreeSpacingFlag() { this.getFlagString().charAt(_) = "x" } /** Returns the root node of the parse tree of this regular expression. */ + overlay[global] final RE::RegExpTerm getParsed() { result = RE::getParsedRegExp(this) } } diff --git a/ruby/ql/lib/codeql/ruby/ast/Method.qll b/ruby/ql/lib/codeql/ruby/ast/Method.qll index 61ee58019d1..60c0c705b31 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Method.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Method.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import codeql.ruby.controlflow.ControlFlowGraph private import internal.AST diff --git a/ruby/ql/lib/codeql/ruby/ast/Module.qll b/ruby/ql/lib/codeql/ruby/ast/Module.qll index 9e2ca31ee61..671910bfaef 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Module.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Module.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import codeql.ruby.CFG private import internal.AST diff --git a/ruby/ql/lib/codeql/ruby/ast/Operation.qll b/ruby/ql/lib/codeql/ruby/ast/Operation.qll index 2e005a207e3..b9046a930b3 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Operation.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Operation.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.AST private import internal.TreeSitter diff --git a/ruby/ql/lib/codeql/ruby/ast/Parameter.qll b/ruby/ql/lib/codeql/ruby/ast/Parameter.qll index c4b233b62b6..5b3994378c1 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Parameter.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Parameter.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.AST private import internal.Variable diff --git a/ruby/ql/lib/codeql/ruby/ast/Pattern.qll b/ruby/ql/lib/codeql/ruby/ast/Pattern.qll index ef778664031..f705bf28301 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Pattern.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Pattern.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.AST private import internal.Pattern diff --git a/ruby/ql/lib/codeql/ruby/ast/Scope.qll b/ruby/ql/lib/codeql/ruby/ast/Scope.qll index 3e8437f79b3..334b36b583f 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Scope.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Scope.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.AST private import internal.Scope diff --git a/ruby/ql/lib/codeql/ruby/ast/Statement.qll b/ruby/ql/lib/codeql/ruby/ast/Statement.qll index 24e18fe4c36..dcd51dbb327 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Statement.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Statement.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import codeql.ruby.CFG private import internal.AST diff --git a/ruby/ql/lib/codeql/ruby/ast/Variable.qll b/ruby/ql/lib/codeql/ruby/ast/Variable.qll index fa00cfb4cc7..f5fb4b60604 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Variable.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Variable.qll @@ -1,4 +1,6 @@ /** Provides classes for modeling program variables. */ +overlay[local] +module; private import codeql.ruby.AST private import internal.AST diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll b/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll index badcf1d6c6f..ee46fbe8b66 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import codeql.Locations private import TreeSitter private import codeql.ruby.ast.internal.Call diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Call.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Call.qll index 5bb34989a90..4f3c236f102 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Call.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Call.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import TreeSitter private import Variable private import codeql.ruby.AST diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Constant.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Constant.qll index a04efc1ec94..133cea315c3 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Constant.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Constant.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import codeql.ruby.ast.internal.AST private import codeql.ruby.ast.internal.Literal diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Control.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Control.qll index 7b95d67efc4..dd57a0d197d 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Control.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Control.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import TreeSitter private import codeql.ruby.AST private import codeql.ruby.ast.internal.AST diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Erb.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Erb.qll index 7a69bf5b783..29960486907 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Erb.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Erb.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import codeql.Locations private import TreeSitter private import codeql.ruby.ast.Erb diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll index ba4f9e51f4e..fdeec446a93 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import codeql.ruby.CFG private import AST diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Literal.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Literal.qll index 8af4673d916..6a2df06b349 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Literal.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Literal.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import AST private import Constant diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Method.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Method.qll index 075ac5fb8fa..c4dd1abbee0 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Method.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Method.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import AST private import TreeSitter diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll index 6905dd5ff2d..d222316bf26 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import Scope as Scope diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Operation.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Operation.qll index 54c763e24d3..eeec2198b62 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Operation.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Operation.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import AST private import TreeSitter diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll index dc7fb8c7695..8f07554fb0c 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import AST private import TreeSitter diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Pattern.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Pattern.qll index c59898d88ee..a30cce32c7c 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Pattern.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Pattern.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import codeql.ruby.ast.internal.Expr private import codeql.ruby.ast.internal.Parameter diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Scope.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Scope.qll index 8f5bde5aeec..9ec237012bc 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Scope.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Scope.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import TreeSitter private import codeql.ruby.AST private import codeql.ruby.ast.internal.AST diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll index 5d1ee81c013..f2be91a63e5 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll @@ -1,4 +1,6 @@ /** Provides predicates for synthesizing AST nodes. */ +overlay[local] +module; private import AST private import TreeSitter diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll b/ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll index 4d9cd901f23..dbc7b38b84e 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll @@ -23,6 +23,7 @@ private predicate discardLocation(@location_default loc) { ) } +overlay[local] module Ruby { /** The base class for all AST nodes */ class AstNode extends @ruby_ast_node { @@ -67,7 +68,6 @@ module Ruby { } /** Gets the file containing the given `node`. */ - overlay[local] private @file getNodeFile(@ruby_ast_node node) { exists(@location_default loc | ruby_ast_node_location(node, loc) | locations_default(loc, result, _, _, _, _) @@ -75,7 +75,6 @@ module Ruby { } /** Holds if `node` is in the `file` and is part of the overlay base database. */ - overlay[local] private predicate discardableAstNode(@file file, @ruby_ast_node node) { not isOverlay() and file = getNodeFile(node) } @@ -1967,6 +1966,7 @@ module Ruby { } } +overlay[local] module Erb { /** The base class for all AST nodes */ class AstNode extends @erb_ast_node { @@ -2011,7 +2011,6 @@ module Erb { } /** Gets the file containing the given `node`. */ - overlay[local] private @file getNodeFile(@erb_ast_node node) { exists(@location_default loc | erb_ast_node_location(node, loc) | locations_default(loc, result, _, _, _, _) @@ -2019,7 +2018,6 @@ module Erb { } /** Holds if `node` is in the `file` and is part of the overlay base database. */ - overlay[local] private predicate discardableAstNode(@file file, @erb_ast_node node) { not isOverlay() and file = getNodeFile(node) } diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Variable.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Variable.qll index bea1ddadbfb..7c130220a86 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Variable.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Variable.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import TreeSitter private import codeql.ruby.AST private import codeql.ruby.CFG diff --git a/ruby/ql/lib/codeql/ruby/controlflow/BasicBlocks.qll b/ruby/ql/lib/codeql/ruby/controlflow/BasicBlocks.qll index f70062ad24f..93253371198 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/BasicBlocks.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/BasicBlocks.qll @@ -1,4 +1,6 @@ /** Provides classes representing basic blocks. */ +overlay[local] +module; private import codeql.ruby.AST private import codeql.ruby.ast.internal.AST diff --git a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll index c822450bf89..16d0a69fcc3 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll @@ -1,4 +1,6 @@ /** Provides classes representing nodes in a control flow graph. */ +overlay[local] +module; private import codeql.ruby.AST private import codeql.ruby.controlflow.BasicBlocks diff --git a/ruby/ql/lib/codeql/ruby/controlflow/ControlFlowGraph.qll b/ruby/ql/lib/codeql/ruby/controlflow/ControlFlowGraph.qll index dee31d8e901..f3c5dcd08f3 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/ControlFlowGraph.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/ControlFlowGraph.qll @@ -1,4 +1,6 @@ /** Provides classes representing the control flow graph. */ +overlay[local] +module; private import codeql.ruby.AST private import codeql.ruby.controlflow.BasicBlocks diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll index 83ea11e9d23..b8edf83c20d 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll @@ -3,6 +3,8 @@ * * A completion represents how a statement or expression terminates. */ +overlay[local] +module; private import codeql.ruby.AST private import codeql.ruby.ast.internal.AST diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll index dd672ba982d..d0d418a839f 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll @@ -2,6 +2,8 @@ * Provides an implementation for constructing control-flow graphs (CFGs) from * abstract syntax trees (ASTs), using the shared library from `codeql.controlflow.Cfg`. */ +overlay[local] +module; private import codeql.controlflow.Cfg as CfgShared private import codeql.ruby.AST diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/Guards.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/Guards.qll index 1161a061581..a60102e017c 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/internal/Guards.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/Guards.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.CFG /** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */ diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/NonReturning.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/NonReturning.qll index e1927a0b1c9..45b299a5d2b 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/internal/NonReturning.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/NonReturning.qll @@ -1,4 +1,6 @@ /** Provides a simple analysis for identifying calls that will not return. */ +overlay[local] +module; private import codeql.ruby.AST private import Completion diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/Splitting.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/Splitting.qll index 5331a3d26b6..146d5927479 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/internal/Splitting.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/Splitting.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates relevant for splitting the control flow graph. */ +overlay[local] +module; private import codeql.ruby.AST as Ast private import Completion as Comp diff --git a/ruby/ql/lib/codeql/ruby/dataflow/SSA.qll b/ruby/ql/lib/codeql/ruby/dataflow/SSA.qll index 07721d33334..1478d9ed9d6 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/SSA.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/SSA.qll @@ -1,6 +1,8 @@ /** * Provides the module `Ssa` for working with static single assignment (SSA) form. */ +overlay[local] +module; /** * Provides classes for working with static single assignment (SSA) form. diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImpl.qll index adbec18be64..3e1d27a17ba 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImpl.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImpl.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ssa.Ssa as SsaImplCommon private import codeql.ruby.AST private import codeql.ruby.CFG as Cfg @@ -393,6 +396,7 @@ private module Cached { signature predicate guardChecksSig(Cfg::CfgNodes::AstCfgNode g, Cfg::CfgNode e, boolean branch); + overlay[global] cached // nothing is actually cached module BarrierGuard { private predicate guardChecksAdjTypes( diff --git a/shared/tree-sitter-extractor/src/generator/mod.rs b/shared/tree-sitter-extractor/src/generator/mod.rs index d9e6e00a121..5e58611092b 100644 --- a/shared/tree-sitter-extractor/src/generator/mod.rs +++ b/shared/tree-sitter-extractor/src/generator/mod.rs @@ -120,6 +120,7 @@ pub fn generate( qldoc: None, name: &language.name, body, + overlay: Some(ql::OverlayAnnotation::Local), })], )?; } diff --git a/shared/tree-sitter-extractor/src/generator/ql.rs b/shared/tree-sitter-extractor/src/generator/ql.rs index e4c87b61bdb..b1e319afb1e 100644 --- a/shared/tree-sitter-extractor/src/generator/ql.rs +++ b/shared/tree-sitter-extractor/src/generator/ql.rs @@ -95,6 +95,7 @@ pub struct Module<'a> { pub qldoc: Option, pub name: &'a str, pub body: Vec>, + pub overlay: Option, } impl fmt::Display for Module<'_> { @@ -102,6 +103,14 @@ impl fmt::Display for Module<'_> { if let Some(qldoc) = &self.qldoc { write!(f, "/** {} */", qldoc)?; } + if let Some(overlay_annotation) = &self.overlay { + write!(f, "overlay[")?; + match overlay_annotation { + OverlayAnnotation::Local => write!(f, "local")?, + OverlayAnnotation::DiscardEntity => write!(f, "discard_entity")?, + } + write!(f, "] ")?; + } writeln!(f, "module {} {{ ", self.name)?; for decl in &self.body { writeln!(f, " {}", decl)?; diff --git a/shared/tree-sitter-extractor/src/generator/ql_gen.rs b/shared/tree-sitter-extractor/src/generator/ql_gen.rs index 8b6c9c18c6f..2cfaf5715ca 100644 --- a/shared/tree-sitter-extractor/src/generator/ql_gen.rs +++ b/shared/tree-sitter-extractor/src/generator/ql_gen.rs @@ -286,7 +286,7 @@ pub fn create_get_node_file_predicate<'a>( overridden: false, is_private: true, is_final: false, - overlay: Some(ql::OverlayAnnotation::Local), + overlay: None, return_type: Some(ql::Type::At("file")), formal_parameters: vec![ql::FormalParameter { name: "node", @@ -327,7 +327,7 @@ pub fn create_discardable_ast_node_predicate(ast_node_name: &str) -> ql::Predica overridden: false, is_private: true, is_final: false, - overlay: Some(ql::OverlayAnnotation::Local), + overlay: None, return_type: None, formal_parameters: vec![ ql::FormalParameter { From d437a096f1063dd86f913cb4af08fe4cf02d9980 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 8 Jul 2025 13:20:04 +0100 Subject: [PATCH 034/199] Test more client request URL sinks --- .../Security/CWE-918/RequestForgery.expected | 74 +++++++++++-------- .../test/query-tests/Security/CWE-918/tst.go | 16 ++-- 2 files changed, 54 insertions(+), 36 deletions(-) diff --git a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected index 914d4c3c084..53b348c479f 100644 --- a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected +++ b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected @@ -2,11 +2,15 @@ | RequestForgery.go:11:15:11:66 | call to Get | RequestForgery.go:8:12:8:34 | call to FormValue | RequestForgery.go:11:24:11:65 | ...+... | The $@ of this request depends on a $@. | RequestForgery.go:11:24:11:65 | ...+... | URL | RequestForgery.go:8:12:8:34 | call to FormValue | user-provided value | | tst.go:14:2:14:18 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:14:11:14:17 | tainted | The $@ of this request depends on a $@. | tst.go:14:11:14:17 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | | tst.go:18:2:18:38 | call to Post | tst.go:10:13:10:35 | call to FormValue | tst.go:18:12:18:18 | tainted | The $@ of this request depends on a $@. | tst.go:18:12:18:18 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | -| tst.go:22:2:22:14 | call to Do | tst.go:10:13:10:35 | call to FormValue | tst.go:21:34:21:40 | tainted | The $@ of this request depends on a $@. | tst.go:21:34:21:40 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | -| tst.go:25:2:25:14 | call to Do | tst.go:10:13:10:35 | call to FormValue | tst.go:24:66:24:72 | tainted | The $@ of this request depends on a $@. | tst.go:24:66:24:72 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | -| tst.go:27:2:27:30 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:27:11:27:29 | ...+... | The $@ of this request depends on a $@. | tst.go:27:11:27:29 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | -| tst.go:29:2:29:41 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:29:11:29:40 | ...+... | The $@ of this request depends on a $@. | tst.go:29:11:29:40 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | -| tst.go:37:2:37:21 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:37:11:37:20 | call to String | The $@ of this request depends on a $@. | tst.go:37:11:37:20 | call to String | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | +| tst.go:20:2:20:28 | call to PostForm | tst.go:10:13:10:35 | call to FormValue | tst.go:20:16:20:22 | tainted | The $@ of this request depends on a $@. | tst.go:20:16:20:22 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | +| tst.go:24:2:24:15 | call to Do | tst.go:10:13:10:35 | call to FormValue | tst.go:23:35:23:41 | tainted | The $@ of this request depends on a $@. | tst.go:23:35:23:41 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | +| tst.go:27:2:27:15 | call to Do | tst.go:10:13:10:35 | call to FormValue | tst.go:26:68:26:74 | tainted | The $@ of this request depends on a $@. | tst.go:26:68:26:74 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | +| tst.go:29:2:29:20 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:29:13:29:19 | tainted | The $@ of this request depends on a $@. | tst.go:29:13:29:19 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | +| tst.go:30:2:30:40 | call to Post | tst.go:10:13:10:35 | call to FormValue | tst.go:30:14:30:20 | tainted | The $@ of this request depends on a $@. | tst.go:30:14:30:20 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | +| tst.go:31:2:31:30 | call to PostForm | tst.go:10:13:10:35 | call to FormValue | tst.go:31:18:31:24 | tainted | The $@ of this request depends on a $@. | tst.go:31:18:31:24 | tainted | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | +| tst.go:33:2:33:30 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:33:11:33:29 | ...+... | The $@ of this request depends on a $@. | tst.go:33:11:33:29 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | +| tst.go:35:2:35:41 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:35:11:35:40 | ...+... | The $@ of this request depends on a $@. | tst.go:35:11:35:40 | ...+... | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | +| tst.go:43:2:43:21 | call to Get | tst.go:10:13:10:35 | call to FormValue | tst.go:43:11:43:20 | call to String | The $@ of this request depends on a $@. | tst.go:43:11:43:20 | call to String | URL | tst.go:10:13:10:35 | call to FormValue | user-provided value | | websocket.go:65:12:65:53 | call to Dial | websocket.go:60:21:60:31 | call to Referer | websocket.go:65:27:65:40 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:65:27:65:40 | untrustedInput | WebSocket URL | websocket.go:60:21:60:31 | call to Referer | user-provided value | | websocket.go:79:13:79:40 | call to DialConfig | websocket.go:74:21:74:31 | call to Referer | websocket.go:78:36:78:49 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:78:36:78:49 | untrustedInput | WebSocket URL | websocket.go:74:21:74:31 | call to Referer | user-provided value | | websocket.go:91:3:91:50 | call to Dial | websocket.go:88:21:88:31 | call to Referer | websocket.go:91:31:91:44 | untrustedInput | The $@ of this request depends on a $@. | websocket.go:91:31:91:44 | untrustedInput | WebSocket URL | websocket.go:88:21:88:31 | call to Referer | user-provided value | @@ -20,21 +24,25 @@ edges | RequestForgery.go:8:12:8:34 | call to FormValue | RequestForgery.go:11:24:11:65 | ...+... | provenance | Src:MaD:1 | | tst.go:10:13:10:35 | call to FormValue | tst.go:14:11:14:17 | tainted | provenance | Src:MaD:1 | | tst.go:10:13:10:35 | call to FormValue | tst.go:18:12:18:18 | tainted | provenance | Src:MaD:1 | -| tst.go:10:13:10:35 | call to FormValue | tst.go:21:34:21:40 | tainted | provenance | Src:MaD:1 | -| tst.go:10:13:10:35 | call to FormValue | tst.go:24:66:24:72 | tainted | provenance | Src:MaD:1 | -| tst.go:10:13:10:35 | call to FormValue | tst.go:27:11:27:29 | ...+... | provenance | Src:MaD:1 | -| tst.go:10:13:10:35 | call to FormValue | tst.go:29:11:29:40 | ...+... | provenance | Src:MaD:1 | -| tst.go:10:13:10:35 | call to FormValue | tst.go:36:11:36:17 | tainted | provenance | Src:MaD:1 | -| tst.go:35:2:35:2 | definition of u [pointer] | tst.go:36:2:36:2 | u [pointer] | provenance | | -| tst.go:36:2:36:2 | implicit dereference | tst.go:35:2:35:2 | definition of u [pointer] | provenance | | -| tst.go:36:2:36:2 | implicit dereference | tst.go:36:2:36:2 | u | provenance | | -| tst.go:36:2:36:2 | implicit dereference | tst.go:37:11:37:11 | u | provenance | | -| tst.go:36:2:36:2 | u | tst.go:36:2:36:2 | implicit dereference | provenance | | -| tst.go:36:2:36:2 | u | tst.go:37:11:37:11 | u | provenance | | -| tst.go:36:2:36:2 | u [pointer] | tst.go:36:2:36:2 | implicit dereference | provenance | | -| tst.go:36:11:36:17 | tainted | tst.go:36:2:36:2 | u | provenance | Config | -| tst.go:36:11:36:17 | tainted | tst.go:37:11:37:11 | u | provenance | Config | -| tst.go:37:11:37:11 | u | tst.go:37:11:37:20 | call to String | provenance | MaD:3 | +| tst.go:10:13:10:35 | call to FormValue | tst.go:20:16:20:22 | tainted | provenance | Src:MaD:1 | +| tst.go:10:13:10:35 | call to FormValue | tst.go:23:35:23:41 | tainted | provenance | Src:MaD:1 | +| tst.go:10:13:10:35 | call to FormValue | tst.go:26:68:26:74 | tainted | provenance | Src:MaD:1 | +| tst.go:10:13:10:35 | call to FormValue | tst.go:29:13:29:19 | tainted | provenance | Src:MaD:1 | +| tst.go:10:13:10:35 | call to FormValue | tst.go:30:14:30:20 | tainted | provenance | Src:MaD:1 | +| tst.go:10:13:10:35 | call to FormValue | tst.go:31:18:31:24 | tainted | provenance | Src:MaD:1 | +| tst.go:10:13:10:35 | call to FormValue | tst.go:33:11:33:29 | ...+... | provenance | Src:MaD:1 | +| tst.go:10:13:10:35 | call to FormValue | tst.go:35:11:35:40 | ...+... | provenance | Src:MaD:1 | +| tst.go:10:13:10:35 | call to FormValue | tst.go:42:11:42:17 | tainted | provenance | Src:MaD:1 | +| tst.go:41:2:41:2 | definition of u [pointer] | tst.go:42:2:42:2 | u [pointer] | provenance | | +| tst.go:42:2:42:2 | implicit dereference | tst.go:41:2:41:2 | definition of u [pointer] | provenance | | +| tst.go:42:2:42:2 | implicit dereference | tst.go:42:2:42:2 | u | provenance | | +| tst.go:42:2:42:2 | implicit dereference | tst.go:43:11:43:11 | u | provenance | | +| tst.go:42:2:42:2 | u | tst.go:42:2:42:2 | implicit dereference | provenance | | +| tst.go:42:2:42:2 | u | tst.go:43:11:43:11 | u | provenance | | +| tst.go:42:2:42:2 | u [pointer] | tst.go:42:2:42:2 | implicit dereference | provenance | | +| tst.go:42:11:42:17 | tainted | tst.go:42:2:42:2 | u | provenance | Config | +| tst.go:42:11:42:17 | tainted | tst.go:43:11:43:11 | u | provenance | Config | +| tst.go:43:11:43:11 | u | tst.go:43:11:43:20 | call to String | provenance | MaD:3 | | websocket.go:60:21:60:31 | call to Referer | websocket.go:65:27:65:40 | untrustedInput | provenance | Src:MaD:2 | | websocket.go:74:21:74:31 | call to Referer | websocket.go:78:36:78:49 | untrustedInput | provenance | Src:MaD:2 | | websocket.go:88:21:88:31 | call to Referer | websocket.go:91:31:91:44 | untrustedInput | provenance | Src:MaD:2 | @@ -54,17 +62,21 @@ nodes | tst.go:10:13:10:35 | call to FormValue | semmle.label | call to FormValue | | tst.go:14:11:14:17 | tainted | semmle.label | tainted | | tst.go:18:12:18:18 | tainted | semmle.label | tainted | -| tst.go:21:34:21:40 | tainted | semmle.label | tainted | -| tst.go:24:66:24:72 | tainted | semmle.label | tainted | -| tst.go:27:11:27:29 | ...+... | semmle.label | ...+... | -| tst.go:29:11:29:40 | ...+... | semmle.label | ...+... | -| tst.go:35:2:35:2 | definition of u [pointer] | semmle.label | definition of u [pointer] | -| tst.go:36:2:36:2 | implicit dereference | semmle.label | implicit dereference | -| tst.go:36:2:36:2 | u | semmle.label | u | -| tst.go:36:2:36:2 | u [pointer] | semmle.label | u [pointer] | -| tst.go:36:11:36:17 | tainted | semmle.label | tainted | -| tst.go:37:11:37:11 | u | semmle.label | u | -| tst.go:37:11:37:20 | call to String | semmle.label | call to String | +| tst.go:20:16:20:22 | tainted | semmle.label | tainted | +| tst.go:23:35:23:41 | tainted | semmle.label | tainted | +| tst.go:26:68:26:74 | tainted | semmle.label | tainted | +| tst.go:29:13:29:19 | tainted | semmle.label | tainted | +| tst.go:30:14:30:20 | tainted | semmle.label | tainted | +| tst.go:31:18:31:24 | tainted | semmle.label | tainted | +| tst.go:33:11:33:29 | ...+... | semmle.label | ...+... | +| tst.go:35:11:35:40 | ...+... | semmle.label | ...+... | +| tst.go:41:2:41:2 | definition of u [pointer] | semmle.label | definition of u [pointer] | +| tst.go:42:2:42:2 | implicit dereference | semmle.label | implicit dereference | +| tst.go:42:2:42:2 | u | semmle.label | u | +| tst.go:42:2:42:2 | u [pointer] | semmle.label | u [pointer] | +| tst.go:42:11:42:17 | tainted | semmle.label | tainted | +| tst.go:43:11:43:11 | u | semmle.label | u | +| tst.go:43:11:43:20 | call to String | semmle.label | call to String | | websocket.go:60:21:60:31 | call to Referer | semmle.label | call to Referer | | websocket.go:65:27:65:40 | untrustedInput | semmle.label | untrustedInput | | websocket.go:74:21:74:31 | call to Referer | semmle.label | call to Referer | diff --git a/go/ql/test/query-tests/Security/CWE-918/tst.go b/go/ql/test/query-tests/Security/CWE-918/tst.go index 00a09fef0f7..5ca6641fb06 100644 --- a/go/ql/test/query-tests/Security/CWE-918/tst.go +++ b/go/ql/test/query-tests/Security/CWE-918/tst.go @@ -17,12 +17,18 @@ func handler2(w http.ResponseWriter, req *http.Request) { http.Post(tainted, "text/basic", nil) // $ Alert - client := &http.Client{} - rq, _ := http.NewRequest("GET", tainted, nil) // $ Sink - client.Do(rq) // $ Alert + http.PostForm(tainted, nil) // $ Alert - rq, _ = http.NewRequestWithContext(context.Background(), "GET", tainted, nil) // $ Sink - client.Do(rq) // $ Alert + client := &http.Client{} + rq1, _ := http.NewRequest("GET", tainted, nil) // $ Sink + client.Do(rq1) // $ Alert + + rq2, _ := http.NewRequestWithContext(context.Background(), "GET", tainted, nil) // $ Sink + client.Do(rq2) // $ Alert + + client.Get(tainted) // $ Alert + client.Post(tainted, "text/basic", nil) // $ Alert + client.PostForm(tainted, nil) // $ Alert http.Get("http://" + tainted) // $ Alert From 5f7d746266e64e664264afb5c372ee9cf9b41362 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 8 Jul 2025 14:53:39 +0200 Subject: [PATCH 035/199] Java: Add query to detect non-case labels in switch statements --- .../java-code-quality-extended.qls.expected | 1 + .../java-code-quality.qls.expected | 1 + java/ql/src/Language Abuse/LabelInSwitch.md | 33 +++++++++++++++++++ java/ql/src/Language Abuse/LabelInSwitch.ql | 25 ++++++++++++++ .../LabelInSwitch/LabelInSwitch.expected | 2 ++ .../LabelInSwitch/LabelInSwitch.qlref | 2 ++ .../test/query-tests/LabelInSwitch/Test.java | 21 ++++++++++++ 7 files changed, 85 insertions(+) create mode 100644 java/ql/src/Language Abuse/LabelInSwitch.md create mode 100644 java/ql/src/Language Abuse/LabelInSwitch.ql create mode 100644 java/ql/test/query-tests/LabelInSwitch/LabelInSwitch.expected create mode 100644 java/ql/test/query-tests/LabelInSwitch/LabelInSwitch.qlref create mode 100644 java/ql/test/query-tests/LabelInSwitch/Test.java diff --git a/java/ql/integration-tests/java/query-suite/java-code-quality-extended.qls.expected b/java/ql/integration-tests/java/query-suite/java-code-quality-extended.qls.expected index 5c82bd5e349..7de884f0081 100644 --- a/java/ql/integration-tests/java/query-suite/java-code-quality-extended.qls.expected +++ b/java/ql/integration-tests/java/query-suite/java-code-quality-extended.qls.expected @@ -6,6 +6,7 @@ ql/java/ql/src/Compatibility/JDK9/UnderscoreIdentifier.ql ql/java/ql/src/DeadCode/UselessParameter.ql ql/java/ql/src/Language Abuse/EmptyMethod.ql ql/java/ql/src/Language Abuse/IterableIterator.ql +ql/java/ql/src/Language Abuse/LabelInSwitch.ql ql/java/ql/src/Language Abuse/TypeVariableHidesType.ql ql/java/ql/src/Language Abuse/UselessNullCheck.ql ql/java/ql/src/Language Abuse/UselessTypeTest.ql diff --git a/java/ql/integration-tests/java/query-suite/java-code-quality.qls.expected b/java/ql/integration-tests/java/query-suite/java-code-quality.qls.expected index e558cf3ffc4..c85479a29b0 100644 --- a/java/ql/integration-tests/java/query-suite/java-code-quality.qls.expected +++ b/java/ql/integration-tests/java/query-suite/java-code-quality.qls.expected @@ -5,6 +5,7 @@ ql/java/ql/src/Compatibility/JDK9/JdkInternalAccess.ql ql/java/ql/src/Compatibility/JDK9/UnderscoreIdentifier.ql ql/java/ql/src/DeadCode/UselessParameter.ql ql/java/ql/src/Language Abuse/IterableIterator.ql +ql/java/ql/src/Language Abuse/LabelInSwitch.ql ql/java/ql/src/Language Abuse/UselessNullCheck.ql ql/java/ql/src/Language Abuse/UselessTypeTest.ql ql/java/ql/src/Language Abuse/WrappedIterator.ql diff --git a/java/ql/src/Language Abuse/LabelInSwitch.md b/java/ql/src/Language Abuse/LabelInSwitch.md new file mode 100644 index 00000000000..d8b39e08d15 --- /dev/null +++ b/java/ql/src/Language Abuse/LabelInSwitch.md @@ -0,0 +1,33 @@ +## Overview + +Java allows to freely mix `case` labels and ordinary statement labels in the body of +a `switch` statement. However, this is confusing to read and may be the result of a typo. + +## Recommendation + +Examine the non-`case` labels to see whether they were meant to be `case` labels. If not, consider placing the non-`case` label headed code into a function, and use a function call inline in the `switch` body instead. + +## Example + +```java +public class Test { + void test_noncase_label_in_switch(int p) { + switch (p) { + case 1: // Compliant + case2: // Non-compliant, likely a typo + break; + case 3: + notcaselabel: // Non-compliant, confusing to read + for (;;) { + break notcaselabel; + } + } + } +} +``` + +In the example, `case2` is most likely a typo and should be fixed. For the intensional `notcaselabel`, placing the labelled code into a function and then calling that function is more readable. + +## References + +Similar to the JS CodeQL query - [js/label-in-switch](https://codeql.github.com/codeql-query-help/javascript/js-label-in-switch/). diff --git a/java/ql/src/Language Abuse/LabelInSwitch.ql b/java/ql/src/Language Abuse/LabelInSwitch.ql new file mode 100644 index 00000000000..56245df8033 --- /dev/null +++ b/java/ql/src/Language Abuse/LabelInSwitch.ql @@ -0,0 +1,25 @@ +/** + * @id java/label-in-switch + * @name Non-case label in switch statement + * @description A non-case label appearing in a switch statement + * is confusing to read or may even indicate a bug. + * @previous-id java/label-in-case + * @kind problem + * @precision very-high + * @problem.severity recommendation + * @tags quality + * maintainability + * readability + */ + +import java + +from LabeledStmt l, SwitchStmt s, string alert +where + l = s.getAStmt+() and + if exists(JumpStmt jump | jump.getTargetLabel() = l) + then alert = "Confusing non-case label in switch statement." + else + alert = + "Possibly erroneous non-case label in switch statement. The case keyword might be missing." +select l, alert diff --git a/java/ql/test/query-tests/LabelInSwitch/LabelInSwitch.expected b/java/ql/test/query-tests/LabelInSwitch/LabelInSwitch.expected new file mode 100644 index 00000000000..40b1bf38242 --- /dev/null +++ b/java/ql/test/query-tests/LabelInSwitch/LabelInSwitch.expected @@ -0,0 +1,2 @@ +| Test.java:14:17:14:31 |